Skip to main content
Loom supports multiple authentication methods to provide secure, flexible access across different use cases: web-based OAuth flows, passwordless magic links, and device code flow for CLI and headless environments.

Authentication Methods

OAuth 2.0

Industry-standard OAuth flows for Google and GitHub

Magic Links

Passwordless email-based authentication

Device Code Flow

CLI and VS Code authentication via browser

Okta SSO

Enterprise SAML/OIDC authentication

OAuth 2.0 Providers

Loom implements OAuth 2.0 / OpenID Connect flows for third-party authentication providers.

Google OAuth

1

Configure OAuth App

Set up a Google OAuth 2.0 application in the Google Cloud Console:
2

OAuth Flow

The Google OAuth flow uses OpenID Connect with the following scopes:
  • openid - Required for OIDC
  • email - Access to user’s email address
  • profile - Access to user’s display name and avatar
Security features:
  • State parameter for CSRF protection (random, unguessable)
  • Nonce parameter for replay protection (validated in ID token)
  • ID token signature verification using Google’s public keys
3

User Claims

After successful authentication, Loom extracts user identity from the ID token:
Available claims:
  • sub - Google’s unique user ID (stable identifier)
  • email - User’s email address
  • email_verified - Whether email is verified by Google
  • name - User’s display name
  • picture - Avatar image URL
The ID token approach is preferred over the /userinfo endpoint because it avoids an extra API call and provides cryptographically verifiable claims.

GitHub OAuth

GitHub OAuth provides seamless authentication for developers already using GitHub.
Requested scopes:
  • user:email - Read user’s email addresses (including private)
  • read:user - Read user profile information
Authentication flow:
1

Authorization URL Generation

2

Code Exchange

Exchange the authorization code for an access token:
3

Fetch User Data

Retrieve user profile and verified emails:
Always use verified emails (email_verified: true for GitHub emails) for security. Unverified emails can be set by anyone and should not be trusted for authentication.
Magic links provide passwordless authentication via email. Users receive a unique, time-limited link that logs them in when clicked.

Security Properties

Single-Use

Each link can only be used once. After verification, the link is marked as used and cannot be reused.

Short-Lived

Links expire after 10 minutes to minimize the window for token interception.

Cryptographically Secure

Tokens are generated using 32 bytes of cryptographically secure random data (256 bits of entropy).

Argon2id Hashing

Tokens are hashed with Argon2id before storage, protecting against database leaks.

Flow Overview

Implementation Details

Token generation:
Why Argon2id over SHA-256?
While 32-byte tokens have 256 bits of entropy (making brute-force infeasible), Argon2id provides defense-in-depth:
  1. Brute-force resistance - Memory-hard design makes GPU/ASIC attacks significantly more expensive
  2. Future-proof - Additional protection if token generation is ever weakened
  3. Industry best practice - OWASP recommends Argon2id for password and token hashing
  4. Salt included - Each hash includes a unique salt, preventing rainbow table attacks
The trade-off is slightly higher CPU cost per verification (~50-100ms), which is acceptable for the low-frequency magic link flow.
Token verification:
When a new magic link is requested, any previous links for that email are invalidated. This prevents accumulation of valid tokens and reduces the attack surface.

Device Code Flow

Device code flow enables authentication on headless or input-constrained devices (CLIs, VS Code) by offloading the authentication to a browser.

Flow Diagram

Two Codes: Why?

The flow uses two distinct codes for security and usability:
Purpose: Internal identifier used by the CLI for polling.
  • Cryptographically random UUID (128 bits of entropy)
  • Hard to guess, making brute-force polling infeasible
  • Never displayed to users
  • Only travels in CLI ↔ Server communication
Purpose: Human-readable code displayed to the user.
  • Format: 9 digits grouped by dashes (XXX-XXX-XXX)
  • Easy to read aloud and type on any keyboard
  • 10^9 possibilities = ~30 bits of entropy
  • Users enter this in the browser to link authentication
Security benefit: Even if an attacker observes the user_code (e.g., shoulder surfing), they cannot poll for the result without the device_code.

Security Properties

Device codes expire after 10 minutes to limit the attack window:
Polling is rate-limited to 1 request per second to prevent abuse:
The server may return slow_down if the client polls too frequently.
User codes are single-use and bound to a specific device code. Once a user completes authentication:
The flow is immune to CSRF attacks because it doesn’t rely on browser cookies. The CLI holds the device_code secret, and the browser only knows the user_code.

State Machine

State transitions:
  • A code starts as Pending
  • It transitions to either Completed (user authenticated) or Expired (timeout)
  • Once in a terminal state, the status never changes

Enterprise SSO (Okta)

For enterprise deployments, Loom supports Okta SAML/OIDC authentication.
The Okta integration uses the same OAuth 2.0 patterns as Google and GitHub, with Okta-specific discovery endpoints and token validation.

Security Best Practices

Secret Protection

All secrets (API keys, client secrets, tokens) are wrapped in SecretString types that auto-redact in logs, Debug output, and serialization.

State Validation

Always validate the state parameter in OAuth callbacks to prevent CSRF attacks. Use cryptographically random values.

Nonce Validation

For OIDC flows, validate the nonce claim in ID tokens to prevent replay attacks.

Email Verification

Only trust verified email addresses from OAuth providers. Unverified emails can be set by anyone.

API Reference

Device Code Flow Endpoints

See loom-server/src/routes/auth/ for complete route implementations.