Authentication
Unseenr uses different authentication methods for different contexts.
Dashboard Authentication
GitHub OAuth
The primary authentication method. Users sign in with their GitHub account. Unseenr uses the better-auth library for session management.
Email / Password
Available as a fallback. Password requirements:
- Minimum 12 characters
- Validated server-side with Zod
Two-Factor Authentication (2FA)
TOTP-based two-factor authentication is available for all accounts. When enabled:
- Users must enter a 6-digit code from their authenticator app on login
- Backup codes are provided for recovery
- 2FA can be enabled/disabled in account settings
Sessions
- Sessions use secure tokens with expiration
- IP address and user agent are logged for security
- Sessions can be managed (viewed and revoked) in account settings
SDK / Ingest Authentication
SDK requests to the ingest endpoint use DSN-based authentication. The DSN contains a public key that identifies the project:
https://<PUBLIC_KEY>@app.unseenr.io/<PROJECT_ID>
The public key is sent via:
x-unseenr-authheaderx-sentry-authheader (Sentry compatibility)sentry_keyquery parameter
Public keys are safe to include in client-side code. They only allow sending events to a specific project, not reading data.
Client Keys
Each project has one or more client keys, each with:
- A unique public key
- A unique DSN
- An optional environment name
- Active/inactive status
Inactive keys are rejected at the ingest layer. Key rotation (create new + revoke old) is supported.
Internal Worker API
The worker communicates with the main app via an internal API secured by a shared secret (WORKER_API_SECRET). This is used by the uptime API workers in remote regions (HEL1, ASH) that don't have direct database access.
Security Headers
All authenticated pages include:
| Header | Value |
|---|---|
X-Content-Type-Options |
nosniff |
X-Frame-Options |
DENY |
X-XSS-Protection |
1; mode=block |
Referrer-Policy |
strict-origin-when-cross-origin |
Strict-Transport-Security |
max-age=63072000; includeSubDomains; preload |
Content-Security-Policy |
Restrictive policy (no external scripts) |
Permissions-Policy |
Camera, microphone, geolocation disabled |