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.
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):
{
"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
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):
{
"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:
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:
curl -X POST https://api.logvista.orph.dev/auth/logout \
-H "Content-Type: application/json" \
-d '{ "refreshToken": "rt_..." }'Magic Link
Passwordless authentication via email. Users who do not have an account are auto-registered on first verify.
Request a Magic Link
curl -X POST https://api.logvista.orph.dev/auth/magic-link \
-H "Content-Type: application/json" \
-d '{ "email": "user@example.com" }'Response (200):
{
"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).
Verify Magic Link
The user clicks the link in their email, which hits:
curl https://api.logvista.orph.dev/auth/magic-link/verify?token=abc123Response (200):
{
"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:
curl -L https://api.logvista.orph.dev/auth/oauth/githubThis 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:
- Exchanges the code for an access token (with PKCE verifier)
- Fetches the user's GitHub profile
- 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.
Link GitHub to Existing Account
Authenticated users can link their GitHub account:
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
curl -L https://api.logvista.orph.dev/auth/oauth/googleRedirects to Google's consent screen with PKCE code challenge.
Callback
Identical flow to GitHub: exchange code, fetch profile, login/link/register.
Link Google to Existing Account
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:
curl https://api.logvista.orph.dev/auth/methods \
-H "Authorization: Bearer eyJ..."Response:
{
"success": true,
"data": {
"hasPassword": true,
"providers": ["github", "google"]
}
}Unlink a Provider
Remove an OAuth provider from your account:
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:
curl https://api.logvista.orph.dev/auth/verify-email?token=vt_abc123Some operations (like creating workspaces) require a verified email via the requireVerifiedEmail middleware.
Password Reset
Request Reset
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
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:hashfor future algorithm upgradability - JWT signed with
JWT_SECRETenvironment 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
- Workspaces -- Create and manage team workspaces
- API Keys -- Generate keys for programmatic access
- API Reference: Auth -- Full endpoint documentation