Skip to main content
Aya provides secure, user-friendly authentication through trusted OAuth providers with cross-domain session support.

Supported Providers

GitHub

OAuth 2.0 with scope management for profile linking

Apple

Sign in with Apple using OpenID Connect

LinkedIn

OAuth 2.0 for professional profiles

X (Twitter)

OAuth 2.0 with tweet and media permissions

YouTube

OAuth 2.0 for video content creators

Authentication Flow

1

User clicks 'Sign in'

User chooses their preferred OAuth provider from the login page
2

Redirect to provider

User is redirected to provider’s authorization page (GitHub, Apple, etc.)
3

User authorizes

User grants permissions to Aya on the provider’s site
4

Provider redirects back

Provider redirects to Aya callback URL with authorization code
5

Aya exchanges code for token

Backend exchanges authorization code for access token
6

Profile creation or login

  • New user: Individual profile created automatically
  • Existing user: Logged into existing account
7

Session created

JWT session token issued and stored in secure cookie

Session Management

JWT Tokens

Aya uses JSON Web Tokens (JWT) for stateless session management: Token Structure:
{
  "session_id": "ulid-unique-identifier",
  "expires_at": 1735689600
}
Token Properties:
  • Signed with HMAC-SHA256 using server secret
  • Default TTL: 8760 hours (365 days)
  • Stored in HTTP-only secure cookies
  • Cross-domain support for *.aya.is
Never expose the jwt_secret configuration value. Keep it secure in environment variables.

Session Cookies

Cookie Configuration:
  • Name: aya_session (configurable)
  • Domain: .aya.is (configurable for custom domains)
  • Secure: true in production (HTTPS only)
  • HttpOnly: true (JavaScript cannot access)
  • SameSite: Configured for CORS support
Cross-domain cookie sharing enables seamless authentication across all Aya subdomains and custom domains.

CORS Configuration

Cross-Origin Resource Sharing (CORS) is configured to support: Allowed Origins (default):
  • https://aya.is
  • https://www.aya.is
  • http://localhost:3000 (development)
  • http://localhost:5173 (development)
  • http://localhost:4173 (development)
Allowed Headers:
  • Accept
  • Authorization
  • Content-Type
  • Origin
  • X-Requested-With
  • Traceparent, Tracestate (distributed tracing)
Allowed Methods: GET, POST, PUT, DELETE, PATCH, HEAD, OPTIONS
CORS settings are configurable via environment variables for custom deployments.

Provider-Specific Details

GitHub Authentication

OAuth Scopes:
read:user user:email
Allows Aya to:
  • Read basic profile information
  • Access user email addresses
  • Create user account and individual profile
read:user user:email read:org public_repo
Adds permissions to:
  • Read organization memberships
  • Link organization accounts
  • Sync organization repositories
Account Selection: GitHub OAuth supports multi-account selection:
  1. User authorizes with GitHub
  2. System queries GitHub API for user + organizations
  3. User selects which account to link (personal or org)
  4. Profile link created with selected account

Apple Authentication

Configuration Requirements:
  • Client ID (Service ID from Apple Developer)
  • Team ID
  • Key ID
  • Private Key (P8 file from Apple)
OAuth Scope:
name email
Apple-Specific Features:
  • Sign in with Apple button styling
  • Native iOS app support (future)
  • Email relay privacy protection
Apple provides email relay addresses to protect user privacy. These are treated as verified emails.

LinkedIn Authentication

OAuth Scopes:
openid profile email
Basic OpenID Connect authentication for login.
Account Selection: Similar to GitHub, LinkedIn supports organization page selection:
  1. User authorizes
  2. System fetches personal profile + managed organization pages
  3. User selects account to link
  4. Profile link created

X (Twitter) Authentication

OAuth Scopes:
tweet.read users.read offline.access
Basic authentication and profile reading.
Refresh Tokens: X OAuth includes refresh tokens for long-lived access without re-authorization.

YouTube Authentication

OAuth Scope:
https://www.googleapis.com/auth/youtube.readonly
Use Cases:
  • Link YouTube channel to profile
  • Display live stream status
  • Sync channel information
  • Show subscriber counts
YouTube authentication is primarily for profile linking, not user login. Users should use Google/Gmail OAuth for login (if supported).

User Account Creation

New User Flow

1

OAuth callback received

Provider returns user identity data
2

Check if user exists

System checks if email already has an account
3

Create user record

New user created with:
  • Unique user ID
  • Email (verified from provider)
  • Name from provider
  • User kind (“user” or “admin”)
4

Create individual profile

Automatic profile creation with:
  • Generated slug (from name or email)
  • Profile picture from provider avatar
  • Default locale from browser/system
5

Create session

Session and JWT token issued
6

Redirect to onboarding

New users directed to profile completion

Existing User Flow

1

OAuth callback received

Provider returns user identity
2

Match to existing user

System finds user by email
3

Create session

New session record created
4

Issue JWT

Token signed and returned in cookie
5

Redirect to dashboard

User returned to intended destination

Session Lifecycle

Active Sessions

Sessions include:
  • Unique session ID (ULID)
  • User ID
  • Created timestamp
  • Expiry timestamp (365 days default)
  • User preferences (locale, theme, etc.)

Session Preferences

Stored per-session:
  • UI locale preference
  • Theme (light/dark/system)
  • Feature flags
  • Last visited pages

Session Invalidation

Automatic:
  • Token expires after TTL (365 days default)
  • Cookie expires client-side
Manual:
  • User clicks “Logout”
  • Session deleted from database
  • Cookie cleared
JWT tokens remain valid until expiry even if session is deleted. Set appropriate TTL values.

Security Features

PKCE for OAuth

Aya uses PKCE (Proof Key for Code Exchange) for OAuth flows:
  • Code challenge generated client-side
  • Code verifier stored securely
  • Prevents authorization code interception
  • Required for public clients

State Parameter

OAuth state includes:
  • Random state string (CSRF protection)
  • Profile context (for profile linking)
  • Redirect URI
  • Expiry timestamp
Stored in temporary cache, validated on callback.

Protection Against Attacks

CSRF Protection

OAuth state parameter prevents cross-site request forgery

Token Signing

HMAC-SHA256 signature prevents token tampering

Secure Cookies

HttpOnly + Secure flags prevent XSS attacks

PKCE

Code challenge prevents authorization code interception

API Authentication

For API requests, include JWT in header:
curl -H "Authorization: Bearer <jwt-token>" \
  https://api.aya.is/profiles/me
Or rely on cookie authentication for same-origin requests.

Logout Flow

1

User clicks logout

Logout endpoint called
2

Session deleted

Session record removed from database
3

Cookie cleared

Browser instructed to delete session cookie
4

Redirect to homepage

User sent to public homepage

Troubleshooting

  • Check JWT secret matches across services
  • Verify cookie domain configuration
  • Confirm CORS headers allow credentials
  • Check browser cookie settings (third-party cookies)
  • Verify provider client ID and secret
  • Check redirect URI matches provider config exactly
  • Ensure state parameter hasn’t expired (5 min default)
  • Confirm provider account has email verified
  • Check token_ttl configuration
  • Verify server time is synchronized (NTP)
  • Review JWT expiry timestamp in token

Configuration Reference

Environment Variables:
# GitHub
AUTH__GITHUB__CLIENT_ID=your_client_id
AUTH__GITHUB__CLIENT_SECRET=your_secret

# Apple
AUTH__APPLE__CLIENT_ID=your_service_id
AUTH__APPLE__TEAM_ID=your_team_id
AUTH__APPLE__KEY_ID=your_key_id
AUTH__APPLE__PRIVATE_KEY=base64_encoded_p8

# JWT
AUTH__JWT_SECRET=your_secret_key_min_32_chars
AUTH__TOKEN_TTL=8760h  # 365 days

# Cookies
AUTH__COOKIE_DOMAIN=.aya.is
AUTH__COOKIE_NAME=aya_session
AUTH__SECURE_COOKIE=true

# CORS
AUTH__CORS_ALLOWED_ORIGINS=https://aya.is,https://www.aya.is

Next Steps

Profiles

Set up your profile after authentication

Organizations

Link organization accounts via OAuth

Telegram Bot

Link Telegram account to your profile

Mailbox

Access authenticated messaging

Build docs developers (and LLMs) love