Skip to content

Authentication

Thogits uses session-based authentication. All auth endpoints are under /api/auth/. After a successful login or registration, the server sets an HTTPOnly session cookie that authenticates subsequent requests.

  • HTTPOnly — not accessible from JavaScript
  • SameSite=Lax — sent with top-level navigations and same-origin requests
  • Secure — always enabled (HTTPS only)
  • Expiry — 7 days of inactivity; each request resets the timer

All curl examples use -b cookies.txt -c cookies.txt to persist the session cookie across requests.


Create a new account with an email and password. Password must be at least 8 characters.

Terminal window
curl -X POST https://app.thogits.com/api/auth/register \
-H "Content-Type: application/json" \
-b cookies.txt -c cookies.txt \
-d '{
"email": "alice@example.com",
"password": "s3cur3pass!"
}'
{
"user_id": "01JQXYZ1234567890ABCDEFGH",
"email": "alice@example.com",
"display_name": null,
"has_totp": false,
"has_passkey": false,
"linked_google": false,
"linked_apple": false
}

Registration automatically logs you in — no separate login step needed.

Terminal window
curl -X POST https://app.thogits.com/api/auth/login \
-H "Content-Type: application/json" \
-b cookies.txt -c cookies.txt \
-d '{
"email": "alice@example.com",
"password": "s3cur3pass!"
}'

Without 2FA:

{
"user_id": "01JQXYZ1234567890ABCDEFGH",
"email": "alice@example.com",
"display_name": null,
"has_totp": false,
"has_passkey": false,
"linked_google": false,
"linked_apple": false
}

With 2FA enabled:

{
"needs_2fa": true
}

When needs_2fa is true, the session is partially authenticated. You must call the TOTP verify endpoint before accessing protected resources.

Terminal window
curl -X POST https://app.thogits.com/api/auth/logout \
-b cookies.txt -c cookies.txt

Flushes the session. Returns 200 OK with an empty body.

Requires authentication. If the account has an existing password, the current password must be provided.

Terminal window
curl -X POST https://app.thogits.com/api/auth/password \
-H "Content-Type: application/json" \
-b cookies.txt -c cookies.txt \
-d '{
"current_password": "s3cur3pass!",
"new_password": "n3wS3cur3pass!"
}'

Returns the authenticated user’s profile. Useful for checking session validity and seeing which auth methods are configured.

Terminal window
curl https://app.thogits.com/api/auth/me \
-b cookies.txt -c cookies.txt
{
"user_id": "01JQXYZ1234567890ABCDEFGH",
"email": "alice@example.com",
"display_name": "Alice",
"has_totp": true,
"has_passkey": false,
"linked_google": true,
"linked_apple": false
}

Returns 401 Unauthorized if the session is missing, expired, or requires 2FA verification.


OAuth login uses a browser redirect flow with PKCE. Both Google and Apple are supported.

  1. Redirect the user to the provider’s auth URL:

    • Google: GET /api/auth/oauth/google
    • Apple: GET /api/auth/oauth/apple

    The server generates a PKCE challenge, stores the CSRF token and verifier in the session, and returns a 302 redirect to the provider.

  2. User authenticates with Google or Apple in their browser.

  3. Provider redirects back to the callback URL:

    • Google: GET /api/auth/oauth/google/callback?code=...&state=...
    • Apple: POST /api/auth/oauth/apple/callback (form-encoded)

    The server exchanges the authorization code for tokens, extracts the user’s email, and either finds an existing account or creates a new one.

  4. Session is set and the user is redirected to /. The session cookie is now valid for all API requests.

If a user registers with email/password and later logs in with Google using the same email, the accounts are automatically linked. The user can then sign in with either method.

Remove a linked OAuth provider from an authenticated account:

Terminal window
curl -X DELETE https://app.thogits.com/api/auth/link/google \
-b cookies.txt -c cookies.txt

This fails if the provider is the user’s only login method (no password and no other linked providers).


Time-based One-Time Password (TOTP) adds a second factor to email/password login. Compatible with any authenticator app (Google Authenticator, Authy, 1Password, etc.).

  1. Start setup — generates a secret and QR code:

    Terminal window
    curl -X POST https://app.thogits.com/api/auth/2fa/totp/setup \
    -b cookies.txt -c cookies.txt
    {
    "secret": "JBSWY3DPEHPK3PXP",
    "qr_code": "data:image/png;base64,iVBOR..."
    }

    Scan the QR code (a data: URI containing a PNG) with your authenticator app, or manually enter the secret.

  2. Confirm setup — verify the first code to activate 2FA:

    Terminal window
    curl -X POST https://app.thogits.com/api/auth/2fa/totp/confirm \
    -H "Content-Type: application/json" \
    -b cookies.txt -c cookies.txt \
    -d '{"code": "123456"}'

    Returns 200 OK. TOTP is now active on the account.

When TOTP is enabled, POST /api/auth/login returns {"needs_2fa": true} instead of the user profile. The session is partially authenticated — you must verify a TOTP code before accessing any other endpoint.

Terminal window
curl -X POST https://app.thogits.com/api/auth/2fa/totp/verify \
-H "Content-Type: application/json" \
-b cookies.txt -c cookies.txt \
-d '{"code": "654321"}'
{
"user_id": "01JQXYZ1234567890ABCDEFGH",
"email": "alice@example.com",
"display_name": "Alice",
"has_totp": true,
"has_passkey": false,
"linked_google": false,
"linked_apple": false
}

The session is now fully authenticated.

Requires a valid TOTP code to disable (prevents disabling without access to the authenticator):

Terminal window
curl -X POST https://app.thogits.com/api/auth/2fa/totp/disable \
-H "Content-Type: application/json" \
-b cookies.txt -c cookies.txt \
-d '{"code": "789012"}'

Passkeys provide passwordless login using biometrics, hardware security keys, or platform authenticators. Passkey login bypasses TOTP 2FA entirely.

Registration is a two-step challenge-response flow. The user must already be authenticated.

  1. Begin registrationPOST /api/auth/passkey/register/begin

    Returns a CreationChallengeResponse (WebAuthn spec). Pass this to navigator.credentials.create() in the browser.

  2. Complete registrationPOST /api/auth/passkey/register/complete

    Send the credential response from the browser along with a human-readable name:

    {
    "name": "MacBook Touch ID",
    "credential": { /* PublicKeyCredential from browser */ }
    }
  1. Begin authenticationPOST /api/auth/passkey/auth/begin

    Send the user’s email to look up their registered passkeys:

    {"email": "alice@example.com"}

    Returns a RequestChallengeResponse. Pass this to navigator.credentials.get() in the browser.

  2. Complete authenticationPOST /api/auth/passkey/auth/complete

    Send the assertion response from the browser. On success, the session is fully authenticated (no 2FA step required) and the response contains the user profile.

List registered passkeys:

Terminal window
curl https://app.thogits.com/api/auth/passkeys \
-b cookies.txt -c cookies.txt
[
{
"credential_id": "abc123...",
"name": "MacBook Touch ID",
"created_at": "2026-04-01T10:00:00Z"
}
]

Delete a passkey:

Terminal window
curl -X DELETE https://app.thogits.com/api/auth/passkeys/abc123... \
-b cookies.txt -c cookies.txt

MethodEndpointAuth requiredDescription
POST/api/auth/registerNoCreate account with email/password
POST/api/auth/loginNoLogin with email/password
POST/api/auth/logoutYesDestroy session
GET/api/auth/meYesGet current user profile
PUT/api/auth/profileYesUpdate display name
POST/api/auth/passwordYesChange password
GET/api/auth/oauth/googleNoStart Google OAuth flow
GET/api/auth/oauth/appleNoStart Apple OAuth flow
DELETE/api/auth/link/{provider}YesUnlink OAuth provider
POST/api/auth/2fa/totp/setupYesGenerate TOTP secret and QR
POST/api/auth/2fa/totp/confirmYesConfirm TOTP with first code
POST/api/auth/2fa/totp/verifyPartialVerify TOTP during login
POST/api/auth/2fa/totp/disableYesDisable TOTP (requires code)
POST/api/auth/passkey/register/beginYesStart passkey registration
POST/api/auth/passkey/register/completeYesComplete passkey registration
POST/api/auth/passkey/auth/beginNoStart passkey authentication
POST/api/auth/passkey/auth/completeNoComplete passkey authentication
GET/api/auth/passkeysYesList registered passkeys
DELETE/api/auth/passkeys/{credential_id}YesDelete a passkey