Skip to content

Authentication

Authentication is hosted at https://haneoka.org/api/auth. The worker delegates the supported Better Auth routes below and adds Haneoka’s email-registration flow at /api/v1/account/register.

GET /api/v1/account/config

Example:

{
"available": true,
"emailDeliveryEnabled": true,
"emailSignUpEnabled": true,
"providers": ["github", "google"],
"turnstileSiteKey": "public-site-key-or-null"
}

providers lists configured social provider IDs. Secrets, client secrets, auth keys, and Turnstile secret keys are never part of this response.

POST /api/v1/account/register
Content-Type: application/json
X-Captcha-Response: <turnstile-token-when-enabled>
{ "email": "person@example.test" }

The route is same-origin and accepts only an email field. A successful request returns 202:

{ "accepted": true }

The response is uniform for existing and new addresses. If Turnstile is enabled, send the browser challenge token in X-Captcha-Response; the site key comes from the config endpoint.

The following routes are supported under /api/auth:

MethodPathAuthPurpose
GET, HEAD/api/auth/get-sessionAnonymousRead the current session; an absent cookie is a valid anonymous result.
POST/api/auth/sign-in/emailAnonymousSign in with email/password.
POST/api/auth/sign-in/socialAnonymousStart a configured social sign-in.
POST/api/auth/sign-outCookieEnd the current session.
POST/api/auth/send-verification-emailCookieRequest a verification email when email delivery is enabled.
GET/api/auth/verify-emailTokenConsume an email verification link.
POST/api/auth/request-password-resetAnonymousRequest a reset email.
POST/api/auth/reset-passwordTokenSet a new password with the reset token in the body or query.
GET/api/auth/reset-password/{token}TokenOpen a password reset continuation link; no session cookie is required.
POST/api/auth/change-emailCookieRequest an email change.
POST/api/auth/change-passwordCookieChange the current password.
GET/api/auth/list-accountsCookieList linked accounts.
POST/api/auth/link-socialCookieLink a configured social account.
POST/api/auth/unlink-accountCookieUnlink an account, subject to account policy.
GET/api/auth/list-sessionsCookieList active sessions.
POST/api/auth/revoke-sessionCookieRevoke one session.
POST/api/auth/revoke-sessionsCookieRevoke selected/all sessions per Better Auth payload.
POST/api/auth/revoke-other-sessionsCookieRevoke sessions other than the current one.
GET, POST/api/auth/callback/{provider}OAuthComplete a configured provider callback.
GET/api/auth/errorAnonymousRender an auth error response.
GET/api/auth/okAnonymousHealth/OK response from Better Auth.

The provider callback only accepts discord, github, google, or twitter when that provider is configured. A provider missing from providers is not a supported route for the current deployment.

Use credentials: "include" and keep the origin same-origin for account mutations:

const response = await fetch("/api/auth/get-session", {
credentials: "include",
headers: { Accept: "application/json" },
});

Authentication responses are Cache-Control: no-store. Do not cache session JSON, copy cookies into logs, or place client secrets in frontend code.

If the worker lacks a database or a 32-character auth secret, auth routes return 503 auth_not_configured. Email-only routes return 503 when delivery is not configured. Registration can return 400 for invalid email/body, 403 for cross-origin or failed verification, 413 for an oversized body, 415 for a non-JSON body, or 429 with Retry-After: 60 when rate-limited.

Better Auth may evolve provider-specific request and response fields. Use the Better Auth route’s documented payload for the selected operation and treat additional response fields as optional; the Haneoka worker contract guarantees the route availability and cookie/same-origin behavior above.