Sign in

Use your cloudflare-auth account

Third-party application

Application

New here? Create an account

Looking for integration details? Read the docs

Create your account

Continue to cloudflare-auth

Third-party application

Application

Already have an account? Sign in

New to cloudflare-auth? How accounts work

Continue

You are signed in. Confirm to continue to the application.

Not you?

Profile

Your account and session details.

Email
—
Username
—
Created
—
User ID
—

Session status

Current session

Active · Expires in 24h

This session will expire at —.

API Base URL

Your authentication API base URL

Copied

Regenerating your token will invalidate the current token and issue a new one.

Applications

Apply for an App ID to connect each product. Secrets are shown only once.

App created

Copy this secret now. You will not be able to see it again.

sec_…

Register a new app

Create an App ID, then register redirect URIs for redirect login.

Required for redirect login. Exact match; max 20 URIs.

Center-cropped & compressed on server

HTTPS image on sign-in / consent. Empty = generated icon.

Your apps

Documentation

Choose the guide that matches how you use cloudflare-auth — integrate the API as a developer, or manage your own account as a user.

Docs/Developers

Developer guide

Integrate cloudflare-auth into your app with email/password accounts and revocable sessions.

Quick start

Base URL for this prototype environment:

https://auth.dayti.de

Local Worker (during development):

http://127.0.0.1:8787
  1. Register a user with POST /auth/register.
  2. Receive a JWT token and store it on the client.
  3. Call protected routes with Authorization: Bearer <token>.
  4. Revoke the session with POST /auth/logout when done.

API reference

Method Path Auth Description
POST /auth/register 鈥?/td> Create account, auto sign-in, return token
POST /auth/login 鈥?/td> Exchange email + password for a token
GET /auth/me Bearer Return the current user profile
POST /auth/logout Bearer Revoke the current session
GET /health 鈥?/td> Liveness check

POST /auth/register

Request body (JSON):

{ "email": "alice@example.com", "username": "alice", "password": "password123" }

Rules: email must be valid; username ^[A-Za-z0-9_]{3,32}$; password ≥ 8 characters.

Success 201:

{ "user": { "id": "…", "email": "alice@example.com", "username": "alice", "createdAt": "2026-09-17" }, "token": "eyJhbGciOi…", "expiresIn": 86400 }

POST /auth/login

Request body:

{ "email": "alice@example.com", "password": "password123" }

Success 200 returns the same shape as register. Invalid credentials always return 401 with invalid_credentials — the API does not reveal whether the email exists.

GET /auth/me · PATCH /auth/me

GET returns the current user. PATCH updates profile (email / username / password).

PATCH /auth/me Authorization: Bearer <token> { "email": "new@example.com", "username": "newname", "currentPassword": "old", // required only when changing password "newPassword": "new-pass-9" }

Header:

Authorization: Bearer <token>

Success 200:

{ "user": { "id": "…", "email": "alice@example.com", "username": "alice", "createdAt": "…" } }

POST /auth/logout

Requires the Bearer token. Success 200 {"ok":true}. The session row is deleted; the same token cannot be reused.

App ID integration guide

Each product that calls this auth service should use its own App ID. That keeps integrations isolated — you can rotate or revoke one app without affecting others.

1

Apply

Developer creates an application and receives App ID + one-time Secret.

2

Configure

Store credentials on your server only (env / secret manager).

3

Call auth

Backend sends X-App-Id + X-App-Secret on register/login.

4

Operate

Use the user token; rotate secret or revoke app when needed.

Who holds which credential

Developer console

  • Account email / password
  • Issues App ID + Secret
  • Rotate / revoke apps

Your backend

  • APP_ID + APP_SECRET
  • Attaches app headers
  • Never ships secret to clients

End user / client

  • Email + password
  • Receives user token
  • Never sees App Secret

Integration flow

  1. Create a developer account — sign up on this console (or via POST /auth/register).
  2. Apply for an App ID — on the Applications page, or via POST /apps.
  3. Store credentials — save app_… and the one-time sec_… in your server secret store.
  4. Call register / login — send both app headers from your backend when signing end users in.
  5. Use the user token — call GET /auth/me and logout with Authorization: Bearer <user_token>.
  6. Operate the app — rotate the secret if leaked; revoke the app to block all further logins with it.

Step 1 — Apply for credentials

UI: Sign in → Applications → Create application → copy App ID + Secret immediately (Secret is shown once).

API: with a developer Bearer token:

curl -X POST $BASE/apps \ -H "content-type: application/json" \ -H "Authorization: Bearer <developer_token>" \ -d '{"name":"Acme Dashboard","description":"Prod web"}' # Response (201) { "app": { "id": "…", "appId": "app_e14bab3b…, "name": "Acme Dashboard", "status": "active" }, "appSecret": "sec_7fd81b96…, "warning": "Store appSecret now. It will not be shown again." }

List / inspect apps you own:

curl $BASE/apps -H "Authorization: Bearer <developer_token>" # → { "apps": [ { "id", "appId", "name", "status", "createdAt", … } ] }

Step 2 — Configure your backend

Environment variables (example):

AUTH_BASE=https://auth.dayti.de APP_ID=app_e14bab3b6711ae118ae68418 APP_SECRET=sec_7fd81b9627936e5c…/div>
Keep secrets server-side. Never put APP_SECRET in browser or mobile clients. Only your backend attaches X-App-Id / X-App-Secret.

Step 3 — Call auth APIs with app credentials

Send both headers from your server on /auth/register and /auth/login:

POST /auth/login HTTP/1.1 content-type: application/json X-App-Id: app_e14bab3b6711ae118ae68418 X-App-Secret: sec_7fd81b9627936e5c… {"email":"alice@example.com","password":"password123"}

Success responses include the bound appId. Sessions created this way are tied to that app.

# Register an end user through your app curl -X POST $BASE/auth/register \ -H "content-type: application/json" \ -H "X-App-Id: $APP_ID" \ -H "X-App-Secret: $APP_SECRET" \ -d '{"email":"alice@example.com","username":"alice","password":"password123"}' # → 201 { user, token, expiresIn, appId } # Login an existing end user curl -X POST $BASE/auth/login \ -H "content-type: application/json" \ -H "X-App-Id: $APP_ID" \ -H "X-App-Secret: $APP_SECRET" \ -d '{"email":"alice@example.com","password":"password123"}' # → 200 { user, token, expiresIn, appId }

Omitting both headers still works for direct first-party use. Providing only one of the two is rejected with 401 invalid_app_credentials.

Step 4 — Use the user session

After login/register, your client (or BFF) uses only the user token — never the App Secret:

curl $BASE/auth/me \ -H "Authorization: Bearer <user_token>" # → { "user": { 鈥?}, "appId": "app_鈥? } curl -X POST $BASE/auth/logout \ -H "Authorization: Bearer <user_token>" # → { "ok": true }

Step 5 — Lifecycle

ActionWhenEffect
Rotate secret Suspected leak / periodic rotation Old sec_… stops working immediately; new one returned once
Revoke app Decommission product / security incident All further register/login with that App ID return 401 invalid_app_credentials
curl -X POST $BASE/apps/<internal-id>/rotate-secret \ -H "Authorization: Bearer <developer_token>" # → { app, appSecret, warning } curl -X POST $BASE/apps/<internal-id>/revoke \ -H "Authorization: Bearer <developer_token>" # → { app: { status: "revoked", … } }

Server-side example (Node)

// .env: APP_ID, APP_SECRET, AUTH_BASE const headers = { "content-type": "application/json", "X-App-Id": process.env.APP_ID, "X-App-Secret": process.env.APP_SECRET, }; export async function registerEndUser({ email, username, password }) { const res = await fetch(`${process.env.AUTH_BASE}/auth/register`, { method: "POST", headers, body: JSON.stringify({ email, username, password }), }); const data = await res.json(); if (!res.ok) throw new Error(data.message || "register failed"); // data.token → give to your client; never expose APP_SECRET return data; // { user, token, expiresIn, appId } } export async function loginEndUser(email, password) { const res = await fetch(`${process.env.AUTH_BASE}/auth/login`, { method: "POST", headers, body: JSON.stringify({ email, password }), }); const data = await res.json(); if (!res.ok) throw new Error(data.message || "login failed"); return data; } export async function getMe(userToken) { const res = await fetch(`${process.env.AUTH_BASE}/auth/me`, { headers: { Authorization: `Bearer ${userToken}` }, }); return res.json(); }

Troubleshooting app credentials

ResponseLikely causeFix
401 invalid_app_credentials Only one of X-App-Id / X-App-Secret sent Always send both headers together
401 invalid_app_credentials Wrong secret or secret already rotated Use the latest secret; rotate again if lost
401 invalid_app_credentials App revoked or appId typo Check Applications list; create a new app if revoked
401 invalid_credentials End-user email/password wrong Unrelated to App ID — fix user credentials
401 unauthorized Missing/expired user token on /auth/me Send Authorization: Bearer <user_token>

Manage apps (developer session required)

MethodPathDescription
POST/appsCreate app — returns App ID + one-time secret
GET/appsList your applications
GET/apps/:idGet one application
POST/apps/:id/rotate-secretIssue a new secret
POST/apps/:id/revokeRevoke the application

Create body:

{ "name": "Acme Dashboard", "description": "Optional" }

Integration checklist

  • One App ID per product / environment (dev / staging / prod)
  • Secret stored in env / secret manager, not in git
  • App headers only on server-to-server calls
  • User tokens only on client after login (or via your BFF)
  • Rotate plan documented; revoke path tested

Redirect login (take over sign-in)

Already signed in? The console shows a confirmation card (Continue / Use another account / Sign out) instead of auto-redirecting.

Use redirect mode when your product wants auth.dayti.de to host login, then bounce the user back to your app. Register Redirect URIs on the Applications page first (exact match, one per line).

Flow

  1. Your app redirects the browser to https://auth.dayti.de/?client_id=…&redirect_uri=…&state=…&response_type=code
  2. User signs in (or creates an account) on this console
  3. If the user is already signed in, they see a confirmation screen: Continue / Use another account / Sign out
  4. After confirm or a fresh sign-in, console calls POST /auth/authorize and navigates to your redirect_uri
  5. Your backend exchanges the one-time code with App Secret via POST /auth/token

1) Start authorize from your app

const url = new URL("https://auth.dayti.de/"); url.searchParams.set("client_id", "app_xxx"); url.searchParams.set("redirect_uri", "https://app.example.com/callback"); url.searchParams.set("response_type", "code"); // or "token" url.searchParams.set("state", crypto.randomUUID()); window.location.assign(url.toString());

redirect_uri must match a URI registered on the application, or authorize fails.

2) After redirect back (code mode)

// callback: ?code=ac_…&state=… curl -X POST $BASE/auth/token \ -H "content-type: application/json" \ -d '{ "code": "ac_…", "client_id": "app_xxx", "client_secret": "sec_…" }' # → { user, token, expiresIn, appId }

Codes expire in 5 minutes and are single-use. Keep state and verify it on return.

3) Token mode (implicit, fragment)

response_type=token # redirect_uri#access_token=…&token_type=Bearer&expires_in=86400&state=…
Prefer code mode for server-side apps. Token mode puts a JWT in the URL fragment — only use it if you accept that risk (e.g. pure SPA with no backend).

API summary

MethodPathDescription
GET/userinfoThird-party profile: id / email / avatar
GET/v1/users/:idLookup by userId (App credentials)
GET/authorizeValidate client_id + redirect_uri (JSON)
POST/auth/authorizeComplete login; returns redirectTo (Bearer user token)
POST/auth/tokenExchange code + client_secret for JWT
POST/appsCreate app with redirectUris: string[]
PUT/apps/:idUpdate redirect URIs / name / description

Error codes

StatuserrorWhen
400invalid_jsonBody is not valid JSON
400invalid_emailEmail format rejected
400invalid_usernameUsername pattern rejected
400weak_passwordPassword shorter than 8
401invalid_credentialsLogin failed
401unauthorizedMissing / expired / revoked token
401invalid_app_credentialsBad or revoked X-App-Id / X-App-Secret
409conflictEmail or username already taken
404not_foundUnknown route
500internal_errorUnexpected server failure

Example: fetch client

const res = await fetch(`${BASE}/auth/login`, { method: "POST", headers: { "content-type": "application/json" }, body: JSON.stringify({ email, password }), }); const { user, token, expiresIn } = await res.json(); const me = await fetch(`${BASE}/auth/me`, { headers: { Authorization: `Bearer ${token}` }, });

Local development

npm install npm run db:schema:local npm run dev # http://127.0.0.1:8787
Security notes. Passwords are stored as PBKDF2-SHA256 (100k iterations). Sessions are revocable server-side. Set a long JWT_SECRET with wrangler secret put JWT_SECRET before production. Prefer httpOnly cookies over localStorage when shipping a real frontend.

Docs/Users

User guide

How to create an account, sign in, keep your session secure, and sign out.

Create an account

  1. Open Create an account from the sign-in screen.
  2. Enter a valid email, a username, and a password.
  3. Confirm your password, then choose Create account.

What we ask for

  • Email — used to sign in. Must look like name@example.com.
  • Username 鈥?3–32 characters: letters, numbers, underscore only.
  • Password — at least 8 characters. Longer is better.
If the email or username is already taken, you’ll see Email or username already taken. Try a different value — we never show who already owns an email.

Sign in

  1. Go to the sign-in screen.
  2. Enter the email and password you registered with.
  3. Choose Sign in.

Wrong email or password shows a single message: Invalid email or password. That is intentional — it does not tell you whether the account exists.

Live service. This console talks to the deployed Worker API on the same origin. Create an account to manage App IDs.

Your profile page

After a successful sign-in you land on Profile, which shows:

  • Email, Username, Created, and User ID
  • Session status — a green Active pill and when this session expires
  • API Base URL — only relevant if you are also integrating the API

These fields mirror the account we store for you. Passwords are never shown here (or anywhere).

Sessions & security

  • Signing in creates a session that stays valid until it expires (default 24 hours) or you sign out.
  • Signing out immediately revokes that session — the same token cannot be used again.
  • If a session expires or is revoked, you are returned to the sign-in screen.
  • On a shared computer, always Sign out when finished.

What we store

  • Email and username (as you entered them)
  • A one-way password hash — never your password in plain text
  • Account creation time and active session records

Sign out

  1. Click Sign out in the sidebar.
  2. You return to the sign-in screen; the previous session is revoked.

Troubleshooting

You seeWhat to do
Invalid email or password Check spelling and caps lock; reset is not available in this version — register again if needed.
Email is invalid Use a full address like name@example.com.
Password must be at least 8 characters Choose a longer password and confirm it matches.
Email or username already taken Pick a different email or username.
Sent back to sign-in unexpectedly Your session expired or was revoked. Sign in again.

Need the API?

If you are building an app on top of cloudflare-auth, switch to the developer guide for endpoints and examples.