DeployStack Docs

OAuth2 Server Implementation

This document describes the OAuth2 authorization server implementation in the DeployStack backend, which enables CLI tools and applications to access APIs using Bearer tokens. For general authentication, see Backend Authentication System. For OAuth provider integration (social login), see Providers OAuth Implementation.

Overview

The OAuth2 server provides RFC 6749 compliant authorization for programmatic API access. This enables the DeployStack Gateway CLI and other tools to authenticate users and access APIs on their behalf using Bearer tokens instead of cookies.

Architecture

The OAuth2 server implementation includes:

  • Authorization Server - Handles OAuth2 authorization flow with PKCE
  • Token Management - Issues and validates access/refresh tokens
  • Consent System - User authorization interface
  • Dual Authentication - Supports both cookies and Bearer tokens
  • Scope-based Access - Fine-grained permission control

OAuth2 Flow

Authorization Code Flow with PKCE

The implementation follows the OAuth2 Authorization Code flow enhanced with PKCE (Proof Key for Code Exchange) for additional security:

  1. Client generates PKCE challenge - Creates code verifier and SHA256 challenge
  2. Authorization request - Client redirects to /api/oauth2/auth
  3. User consent - User approves requested scopes
  4. Authorization code - Server returns code to callback
  5. Token exchange - Client exchanges code for tokens
  6. API access - Client uses Bearer token for requests

PKCE Implementation

PKCE provides security for public clients (like CLI tools):

Code Verifier

  • 128 random bytes encoded as base64url
  • Generated by client, kept secret
  • Used during token exchange

Code Challenge

  • SHA256 hash of verifier
  • Sent with authorization request
  • Stored with authorization code

Validation

  • Server verifies challenge matches verifier
  • Prevents code interception attacks
  • Required for all authorization requests

Service Architecture

AuthorizationService

Manages the authorization flow:

Client Validation

  • Validates client_id against whitelist
  • Currently supports deploystack-gateway-cli
  • Extensible for additional clients

Redirect URI Validation

  • Checks URI against allowed list
  • Supports localhost callbacks for CLI
  • Prevents redirect attacks

Scope Validation

  • Validates requested scopes
  • Ensures scopes are recognized
  • Limits access appropriately

Authorization Storage

  • Stores authorization requests
  • Links PKCE challenges
  • Manages request lifecycle

Code Generation

  • Creates authorization codes
  • Associates with user session
  • Implements expiration

Code Verification

  • Validates authorization codes
  • Verifies PKCE challenge
  • Ensures single use

TokenService

Handles token lifecycle:

Token Generation

  • Creates cryptographically secure tokens
  • Generates appropriate expiration
  • Stores hashed versions

Access Token Management

  • Issues 1-hour access tokens
  • Includes user and scope data
  • Enables API authentication

Refresh Token Handling

  • Issues 30-day refresh tokens
  • Allows token renewal
  • Maintains session continuity

Token Verification

  • Validates token format
  • Checks expiration
  • Verifies against database

Token Refresh

  • Exchanges refresh for access token
  • Validates client identity
  • Maintains scope consistency

Token Revocation

  • Invalidates tokens on demand
  • Cleans up related tokens
  • Ensures immediate effect

OAuthCleanupService

Automatic maintenance:

Scheduled Cleanup

  • Runs hourly via cron
  • Removes expired tokens
  • Prevents database bloat

Cleanup Scope

  • Authorization codes > 10 minutes
  • Expired access tokens
  • Expired refresh tokens

OAuth2 Endpoints Overview

The OAuth2 server implements standard OAuth2 endpoints following RFC 6749:

Authorization Flow Endpoints

  • Authorization Endpoint (/api/oauth2/auth) - Initiates the OAuth2 flow with PKCE parameters
  • Consent Endpoints (/api/oauth2/consent) - Displays and processes user authorization consent
  • Token Endpoint (/api/oauth2/token) - Exchanges authorization codes for access tokens and handles token refresh
  • User Info Endpoint (/api/oauth2/userinfo) - Returns authenticated user information

For complete API specifications including request parameters, response schemas, and examples, see the Backend API Documentation. The API documentation provides OpenAPI specifications for all OAuth2 endpoints.

OAuth2 Scopes

Available Scopes

For the current list of supported scopes, see the source code at services/backend/src/services/oauth/authorizationService.ts in the validateScope() method.

Scope Enforcement

Scopes are enforced at the endpoint level:

Middleware Integration

  • requireOAuthScope() - Single scope requirement
  • requireAnyOAuthScope() - Multiple scope options
  • Skip enforcement for cookie auth

Scope Checking

  • Validates token contains required scope
  • Returns 403 for insufficient scope
  • Provides clear error messages

Dual Authentication

Supporting Both Methods

Endpoints can accept cookies or Bearer tokens:

Middleware: requireAuthenticationAny()

  1. First checks cookie session (from authHook)
  2. Falls back to Bearer token validation
  3. Populates unified request.user
  4. Maintains authentication type context

Implementation Pattern

Routes support both authentication methods:

  • Define both security schemes in OpenAPI
  • Use dual authentication middleware
  • Apply scope requirements conditionally
  • Handle both response formats

Authentication Context

The system maintains context about authentication:

  • Cookie Auth: request.user and request.session
  • OAuth2 Auth: request.user and request.tokenPayload
  • Type Detection: Check for tokenPayload presence
  • Unified Interface: Same user object structure

Client Configuration

DeployStack Gateway CLI

Pre-registered OAuth2 client:

  • Client ID: deploystack-gateway-cli
  • Client Type: Public (no secret)
  • Redirect URIs:
    • http://localhost:8976/oauth/callback
    • http://127.0.0.1:8976/oauth/callback
  • Required: PKCE with SHA256
  • Token Lifetime: 1-hour access, 30-day refresh

Adding New Clients

To support additional OAuth2 clients:

  1. Add client_id to validation whitelist
  2. Configure allowed redirect URIs
  3. Define client-specific settings
  4. Update documentation

Security Implementation

PKCE Security

Protection against authorization code interception:

  • Required for all authorization requests
  • SHA256 challenge method only
  • Cryptographically secure verifier generation
  • Single-use authorization codes

Token Security

Multiple layers of token protection:

  • Argon2 hashing for stored tokens
  • Constant-time comparison
  • Secure random generation
  • Automatic expiration
  • Regular cleanup

Authorization Security

Secure authorization flow:

  • CSRF protection via state parameter
  • Session requirement for authorization
  • Validated redirect URIs
  • Clear consent interface

Bearer Token Security

API access security:

  • Standard Authorization header
  • Token validation on each request
  • Scope-based access control
  • Automatic token refresh

Integration Examples

CLI Authentication Flow

Example OAuth2 flow for CLI tools:

  1. Generate PKCE challenge
  2. Open browser for authorization
  3. Start callback server
  4. User approves in browser
  5. Receive authorization code
  6. Exchange for tokens
  7. Store tokens securely
  8. Use Bearer token for API

API Request Example

Using Bearer token for API access:

GET /api/teams/me/default
Authorization: Bearer <access_token>

Token Refresh Example

Refreshing expired access token:

POST /api/oauth2/token
Content-Type: application/json

{
  "grant_type": "refresh_token",
  "refresh_token": "<refresh_token>",
  "client_id": "deploystack-gateway-cli"
}

Monitoring

Metrics to Track (TODO)

  • Authorization requests
  • Token issuance rate
  • Refresh token usage
  • Failed authentication attempts
  • Cleanup effectiveness

Logging (TODO)

Comprehensive logging for debugging:

  • Authorization flow steps
  • Token operations
  • Scope validations
  • Error conditions
  • Security events

OAuth Scope Management

The backend validates OAuth scopes to control API access. Scope configuration must stay synchronized between the backend and gateway.

Current Scopes

For the current list of supported scopes, check the source code at:

  • Backend validation: services/backend/src/services/oauth/authorizationService.ts in the validateScope() method
  • Gateway requests: services/gateway/src/utils/auth-config.ts in the scopes array

Adding New Scopes

When adding support for a new OAuth scope in the backend:

  1. Add the scope to the allowedScopes array in services/backend/src/services/oauth/authorizationService.ts
  2. Update the gateway to request the new scope (see Gateway OAuth Implementation)
  3. Apply scope enforcement to relevant API endpoints using middleware
  4. Test the complete flow to ensure proper scope validation

Example:

// In services/backend/src/services/oauth/authorizationService.ts
static validateScope(scope: string): boolean {
  const requestedScopes = scope.split(' ');
  const allowedScopes = [
    'mcp:read',
    'mcp:categories:read',
    'your-new-scope',  // Add new scope here
    // ... other scopes
  ];
  
  return requestedScopes.every(s => allowedScopes.includes(s));
}

Scope Enforcement in Routes

Apply scope requirements to API endpoints:

// Single scope requirement
server.get('/api/your-endpoint', {
  preValidation: [
    requireValidAccessToken(),
    requireOAuthScope('your-new-scope')
  ]
}, async (request, reply) => {
  // Your endpoint logic
});

// Multiple scope options
server.get('/api/another-endpoint', {
  preValidation: [
    requireValidAccessToken(),
    requireAnyOAuthScope(['scope1', 'scope2'])
  ]
}, async (request, reply) => {
  // Your endpoint logic
});

Scope Synchronization

Critical: The backend and gateway must have matching scope configurations:

  • If backend supports a scope but gateway doesn't request it, users won't get that permission
  • If gateway requests a scope but backend doesn't support it, authentication will fail

Always coordinate scope changes between both services.

Gateway Integration

The OAuth2 server integrates with the DeployStack Gateway:

Gateway OAuth Client

See Gateway OAuth Implementation for:

  • Client-side PKCE generation
  • Browser integration
  • Callback server
  • Token storage
  • Automatic refresh