3 API Authentication
Insidious Fiddler edited this page 2026-02-06 21:04:12 +00:00

API Authentication

Hoist supports multiple authentication methods for different use cases.

Authentication Methods

Method Use Case Header/Parameter
JWT Token Dashboard users Authorization: Bearer <token>
API Key SDKs and integrations X-API-Key: <key>
OAuth/OIDC SSO login Redirect flow

JWT Authentication (Dashboard)

Dashboard users authenticate with email/password or OAuth, receiving JWT tokens.

Login

curl -X POST https://hoist.example.com/api/v1/auth/login \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "your-password"
  }'

Response:

{
  "success": true,
  "data": {
    "accessToken": "eyJhbGciOiJIUzI1NiIs...",
    "refreshToken": "eyJhbGciOiJIUzI1NiIs...",
    "expiresIn": 900,
    "user": {
      "id": "user-uuid",
      "email": "user@example.com",
      "name": "John Doe"
    }
  }
}

Using the Token

Include the access token in subsequent requests:

curl https://hoist.example.com/api/v1/organizations \
  -H "Authorization: Bearer eyJhbGciOiJIUzI1NiIs..."

Token Refresh

Refresh tokens before expiration:

curl -X POST https://hoist.example.com/api/v1/auth/refresh \
  -H "Content-Type: application/json" \
  -d '{
    "refreshToken": "eyJhbGciOiJIUzI1NiIs..."
  }'

Token Expiration

Token Type Default Expiry Configuration
Access Token 15 minutes auth.jwt_expiry
Refresh Token 7 days auth.refresh_token_expiry

API Key Authentication (SDKs)

SDKs use API keys for authentication.

API Key Types

Type Prefix Description
Server Live hoist_live_ Production server-side
Server Test hoist_test_ Non-production server-side
Client hoist_pk_ Client-side (browser/mobile)

Creating API Keys

  1. Go to Project > Settings > API Keys
  2. Click Create API Key
  3. Select the key type and environment
  4. Copy and securely store the key

Using API Keys

Include the key in SDK configuration:

client, _ := hoist.NewClient(hoist.Config{
    APIKey:  "hoist_live_xxx",
    BaseURL: "https://hoist.example.com",
})

Or via HTTP header:

curl https://hoist.example.com/api/v1/flags/config \
  -H "X-API-Key: hoist_live_xxx"

API Key Capabilities

Capability Server Key Client Key
Fetch flag config Yes No
Local evaluation Yes No
Remote evaluation Yes Yes
WebSocket streaming Yes No

OAuth/OIDC Authentication

Configure external identity providers for SSO.

Supported Providers

  • Google
  • GitHub
  • Okta
  • Azure AD
  • Any OIDC-compliant provider

Configuration

Add providers in config.yaml:

auth:
  oidc:
    - name: google
      display_name: "Sign in with Google"
      client_id: "your-client-id"
      client_secret: ""  # Set via HOIST_AUTH_OIDC_GOOGLE_CLIENT_SECRET
      discovery_url: "https://accounts.google.com/.well-known/openid-configuration"
      scopes:
        - openid
        - email
        - profile
      icon_url: "https://example.com/google-icon.svg"

OAuth Flow

  1. User clicks "Sign in with Google" in dashboard
  2. Redirect to provider login page
  3. User authenticates with provider
  4. Provider redirects back with authorization code
  5. Hoist exchanges code for tokens
  6. User account created/linked
  7. JWT tokens issued

Callback URL

Configure in your OAuth provider:

https://hoist.example.com/api/v1/auth/oidc/{provider}/callback

Example for Google:

https://hoist.example.com/api/v1/auth/oidc/google/callback

Multi-Factor Authentication (MFA)

Enable TOTP-based MFA for additional security.

Configuration

auth:
  mfa:
    enabled: true
    issuer: "Hoist"  # Shown in authenticator apps

Setup MFA

  1. User goes to Account Settings > Security
  2. Clicks Enable MFA
  3. Scans QR code with authenticator app
  4. Enters verification code to confirm

MFA Login Flow

  1. User enters email/password
  2. If MFA enabled, prompted for TOTP code
  3. User enters code from authenticator app
  4. JWT tokens issued

API Endpoints

# Setup MFA (returns QR code)
POST /api/v1/auth/mfa/setup

# Verify MFA setup
POST /api/v1/auth/mfa/verify
{
  "code": "123456"
}

# Disable MFA
DELETE /api/v1/auth/mfa

# Login with MFA
POST /api/v1/auth/login
{
  "email": "user@example.com",
  "password": "password",
  "mfaCode": "123456"
}

Local Authentication

Email/password authentication for users without SSO.

Configuration

auth:
  local:
    enabled: true
    allow_registration: true  # Allow self-registration

Registration

curl -X POST https://hoist.example.com/api/v1/auth/register \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com",
    "password": "secure-password",
    "name": "John Doe"
  }'

Password Reset

# Request reset email
curl -X POST https://hoist.example.com/api/v1/auth/forgot-password \
  -H "Content-Type: application/json" \
  -d '{
    "email": "user@example.com"
  }'

# Reset password with token
curl -X POST https://hoist.example.com/api/v1/auth/reset-password \
  -H "Content-Type: application/json" \
  -d '{
    "token": "reset-token-from-email",
    "password": "new-secure-password"
  }'

Security Best Practices

API Keys

  1. Never expose server keys - Keep hoist_live_* keys server-side only
  2. Use client keys for browsers - Use hoist_pk_* for frontend apps
  3. Rotate regularly - Rotate keys periodically
  4. Limit scope - Create keys per project/environment

JWT Tokens

  1. Use HTTPS - Always use TLS in production
  2. Short expiration - Keep access tokens short-lived
  3. Secure storage - Store refresh tokens securely
  4. Validate origin - Configure allowed_origins

OAuth/OIDC

  1. Secure client secrets - Use environment variables
  2. Validate redirect URIs - Configure exact callback URLs
  3. Use state parameter - CSRF protection (handled automatically)

Error Responses

401 Unauthorized

{
  "success": false,
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid or expired token"
  }
}

Causes:

  • Missing or invalid token
  • Expired access token
  • Invalid API key

403 Forbidden

{
  "success": false,
  "error": {
    "code": "FORBIDDEN",
    "message": "Insufficient permissions"
  }
}

Causes:

  • User lacks required role
  • API key doesn't have access to resource

Rate Limiting

API requests are rate-limited to prevent abuse.

Configuration

security:
  rate_limit:
    requests_per_minute: 100
    backend: memory  # or redis for distributed

Rate Limit Headers

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1609459200

429 Too Many Requests

{
  "success": false,
  "error": {
    "code": "RATE_LIMITED",
    "message": "Rate limit exceeded"
  }
}

Next Steps