Skip to content

Authentication

Orphnet Logging supports four authentication methods. All methods produce the same JWT access/refresh token pair for subsequent API calls.

Email/Password

Register

Create a new account with email and password. A personal workspace is created automatically.

bash
curl -X POST https://api.logvista.orph.dev/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "min-8-chars",
    "name": "Optional Name"
  }'

Response (201):

json
{
  "success": true,
  "data": {
    "user": { "id": "usr_...", "email": "user@example.com", "name": "Optional Name" },
    "accessToken": "eyJ...",
    "refreshToken": "rt_...",
    "personalWorkspace": { "id": "ws_...", "slug": "optional-name" }
  }
}

A verification email is sent automatically. The email is fire-and-forget -- it does not block the response.

Login

bash
curl -X POST https://api.logvista.orph.dev/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "min-8-chars"
  }'

Response (200):

json
{
  "success": true,
  "data": {
    "user": { "id": "usr_...", "email": "user@example.com" },
    "accessToken": "eyJ...",
    "refreshToken": "rt_...",
    "personalWorkspace": { "id": "ws_...", "slug": "user-slug" }
  }
}

Refresh Token

Access tokens expire after 15 minutes. Use the refresh token to get a new pair:

bash
curl -X POST https://api.logvista.orph.dev/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{ "refreshToken": "rt_..." }'

Refresh tokens use rotation -- each use issues a new refresh token and invalidates the old one. Tokens share a family_id for theft detection.

Logout

Revoke the current refresh token:

bash
curl -X POST https://api.logvista.orph.dev/auth/logout \
  -H "Content-Type: application/json" \
  -d '{ "refreshToken": "rt_..." }'

Passwordless authentication via email. Users who do not have an account are auto-registered on first verify.

bash
curl -X POST https://api.logvista.orph.dev/auth/magic-link \
  -H "Content-Type: application/json" \
  -d '{ "email": "user@example.com" }'

Response (200):

json
{
  "success": true,
  "data": { "message": "If an account exists, a magic link has been sent" }
}

The endpoint always returns 200 regardless of whether the email exists (anti-enumeration).

The user clicks the link in their email, which hits:

bash
curl https://api.logvista.orph.dev/auth/magic-link/verify?token=abc123

Response (200):

json
{
  "success": true,
  "data": {
    "user": { "id": "usr_...", "email": "user@example.com" },
    "accessToken": "eyJ...",
    "refreshToken": "rt_...",
    "personalWorkspace": { "id": "ws_...", "slug": "user-slug" },
    "isNewUser": true
  }
}

If the user does not exist, they are auto-registered with email_verified = true and a null password hash. They can later set a password or link OAuth providers.

GitHub OAuth

Initiate

Redirect the user to start the OAuth flow:

bash
curl -L https://api.logvista.orph.dev/auth/oauth/github

This returns a 302 redirect to GitHub's authorization page with PKCE code challenge (S256).

Callback

GitHub redirects back to {BASE_URL}/auth/oauth/github/callback with an authorization code. The server:

  1. Exchanges the code for an access token (with PKCE verifier)
  2. Fetches the user's GitHub profile
  3. Handles three cases:
    • Existing link: Logs in the user
    • Auto-link by email: If a user with the same email exists, links the GitHub account
    • Auto-register: Creates a new user with a personal workspace

The callback redirects the user to the frontend with tokens in query parameters.

Authenticated users can link their GitHub account:

bash
curl -X POST https://api.logvista.orph.dev/auth/link/github \
  -H "Authorization: Bearer eyJ..."

Returns { authorizeUrl: "https://github.com/login/oauth/authorize?..." } for the frontend to redirect to.

Google OAuth

Initiate

bash
curl -L https://api.logvista.orph.dev/auth/oauth/google

Redirects to Google's consent screen with PKCE code challenge.

Callback

Identical flow to GitHub: exchange code, fetch profile, login/link/register.

bash
curl -X POST https://api.logvista.orph.dev/auth/link/google \
  -H "Authorization: Bearer eyJ..."

Account Linking

View Auth Methods

Check which authentication methods are linked to the current account:

bash
curl https://api.logvista.orph.dev/auth/methods \
  -H "Authorization: Bearer eyJ..."

Response:

json
{
  "success": true,
  "data": {
    "hasPassword": true,
    "providers": ["github", "google"]
  }
}

Remove an OAuth provider from your account:

bash
curl -X DELETE https://api.logvista.orph.dev/auth/link/github \
  -H "Authorization: Bearer eyJ..."

WARNING

You cannot unlink your last authentication method. The countAuthMethods guard ensures at least one method (password or OAuth provider) remains active.

Email Verification

After registration, a verification email is sent with a 24-hour token. Verify by clicking the link:

bash
curl https://api.logvista.orph.dev/auth/verify-email?token=vt_abc123

Some operations (like creating workspaces) require a verified email via the requireVerifiedEmail middleware.

Password Reset

Request Reset

bash
curl -X POST https://api.logvista.orph.dev/auth/forgot-password \
  -H "Content-Type: application/json" \
  -d '{ "email": "user@example.com" }'

Always returns 200 (anti-enumeration). If the email exists, a reset link is sent.

Complete Reset

bash
curl -X POST https://api.logvista.orph.dev/auth/reset-password \
  -H "Content-Type: application/json" \
  -d '{
    "token": "vt_abc123",
    "password": "new-secure-password"
  }'

Password reset revokes all existing refresh tokens to force re-login on all devices.

Rate Limiting

All auth endpoints are rate-limited to 5 requests per minute per IP using the AUTH preset. See Rate Limits for details.

Security Properties

  • Passwords are hashed with PBKDF2 at 100,000 iterations with SHA-256
  • Password hash format: pbkdf2:iterations:salt:hash for future algorithm upgradability
  • JWT signed with JWT_SECRET environment variable
  • OAuth uses PKCE S256 via Web Crypto API for edge-compatible security
  • Emails are normalized to lowercase on all operations
  • Refresh tokens use family-based rotation for theft detection

Next Steps

LogVista — Edge-native structured logging API