Skip to content

OAuth Flow

Rack Gateway uses Google OAuth 2.0 with OpenID Connect (OIDC) for authentication. The implementation uses vetted libraries and follows security best practices including PKCE for CLI flows.

  1. Create OAuth Client

    In Google Cloud Console → APIs & Services → Credentials:

    • Click “Create Credentials” → “OAuth client ID”
    • Application type: “Web application”
    • Name: “Rack Gateway”
  2. Configure Redirect URIs

    Add authorized redirect URIs:

    https://gateway.example.com/api/v1/auth/web/callback
    https://gateway.example.com/api/v1/auth/cli/callback
  3. Set Environment Variables

    Terminal window
    GOOGLE_CLIENT_ID=your-client-id.apps.googleusercontent.com
    GOOGLE_CLIENT_SECRET=your-client-secret
    GOOGLE_ALLOWED_DOMAIN=yourcompany.com

The web flow uses standard OAuth 2.0 authorization code flow:

ParameterValuePurpose
response_typecodeRequest authorization code
scopeopenid profile emailRequest user info
stateRandom 32 bytesCSRF protection
access_typeonlineNo refresh token needed
promptselect_accountAlways show account picker
hdAllowed domainFilter to organization accounts

The CLI uses OAuth 2.0 with PKCE (Proof Key for Code Exchange) for enhanced security:

PKCE prevents authorization code interception attacks:

  1. Code verifier: High-entropy random string (128 bytes)
  2. Code challenge: SHA-256 hash of verifier
  3. Verification: Google verifies the verifier matches the challenge

Even if an attacker intercepts the authorization code, they cannot exchange it without the code verifier.

ParameterDescription
code_verifier128-byte random string (base64url encoded)
code_challengeSHA-256(code_verifier), base64url encoded
code_challenge_methodAlways S256

The gateway verifies Google’s ID token using the go-oidc library:

  1. Signature verification

    Validates the JWT signature against Google’s public keys (fetched from OIDC discovery)

  2. Issuer validation

    Confirms the token was issued by https://accounts.google.com

  3. Audience validation

    Confirms the token was issued for our client ID

  4. Expiration check

    Ensures the token hasn’t expired

  5. Domain validation

    Extracts email from claims and validates domain

Claims extracted from Google’s ID token:

{
"iss": "https://accounts.google.com",
"aud": "your-client-id.apps.googleusercontent.com",
"sub": "unique-user-id",
"email": "user@yourcompany.com",
"email_verified": true,
"name": "User Name",
"hd": "yourcompany.com"
}
ClaimDescriptionValidation
emailUser’s email addressRequired, domain checked
email_verifiedEmail verification statusMust be true
nameDisplay nameUsed for user record
hdHosted domainMust match allowed domain

Error: “email domain not allowed”

Cause: User attempted to sign in with an email outside the allowed domain.

Solution: Ensure users sign in with their organization email.

OAuth errors return structured JSON:

{
"error": "domain_not_allowed",
"error_description": "Email domain not allowed: user@external.com"
}
  • Generated using cryptographically secure random bytes
  • 32 bytes, base64url encoded
  • Stored server-side and validated on callback
  • Prevents CSRF attacks
  • ID tokens are verified and discarded immediately
  • Session tokens (not OAuth tokens) are stored hashed
  • No refresh tokens stored for web flow
  • Redirect URIs must exactly match those registered in Google Cloud Console
  • No wildcards or pattern matching
  • Separate URIs for web and CLI flows

For local development, use the mock OAuth server:

Terminal window
# Uses mock OAuth server at localhost:3345
task dev

The mock server simulates Google OAuth without requiring real credentials.

For integration testing against real Google OAuth:

  1. Create a separate OAuth client for testing
  2. Add http://localhost:8447/api/v1/auth/*/callback as redirect URIs
  3. Use test accounts from your Google Workspace

The redirect URI in your request doesn’t match any authorized URI in Google Cloud Console.

  1. Check the exact URI (including protocol and path)
  2. Ensure no trailing slashes mismatch
  3. Verify the GATEWAY_URL environment variable

Client ID or secret is incorrect.

  1. Verify GOOGLE_CLIENT_ID matches the Cloud Console
  2. Verify GOOGLE_CLIENT_SECRET is correct
  3. Ensure the OAuth client hasn’t been deleted

If users aren’t seeing the account picker:

  1. Verify prompt=select_account is in the auth URL
  2. Check if the browser has cached credentials
  3. Try incognito/private browsing