Skip to main content

Authentication

Overview

All APIs use AWS Cognito for authentication:

  • User Pool: us-east-1_75Rp4zNBg
  • JWT validated via JWKS endpoint
  • Token extraction: httpOnly cookie first, Bearer header fallback

Token Extraction Priority

JwtStrategy extracts tokens in this order:

  1. httpOnly cookie statux_id_token (browser requests via credentials: 'include')
  2. Authorization: Bearer header (API clients, mobile app, testing)

Auth Flows

Browser Auth (httpOnly Cookies)

The primary auth flow for web dashboards uses httpOnly cookies managed by AuthCookieController (registered on all APIs):

EndpointMethodAuthDescription
/auth/set-cookiePOSTJWTStore tokens in httpOnly cookies
/auth/meGETCookie/JWTGet current user from session
/auth/refreshPOSTCookieRefresh tokens using refresh cookie
/auth/logoutPOSTPublicClear httpOnly auth cookies

Frontend flow:

  1. User signs in via Cognito hosted UI
  2. Frontend calls POST /auth/set-cookie with the Cognito tokens
  3. API sets statux_id_token and statux_refresh_token as httpOnly cookies
  4. All subsequent requests include cookies automatically via credentials: 'include'
  5. Token refresh handled via POST /auth/refresh

Cookie settings:

  • Domain: .statux.io
  • SameSite: Lax
  • Secure: true
  • Max-Age: 30 days (refresh token), 1 hour (ID token)

API Client Auth (Bearer Token)

Mobile apps, API clients, and testing use the standard Bearer header:

curl -H "Authorization: Bearer $TOKEN" https://alerts-api.statux.io/api/v1/users/me

Guards

JwtAuthGuard (Global)

Applied globally via APP_GUARD -- all endpoints require valid JWT unless marked @Public().

OrgAccessGuard

Validates organization membership, attaches request.organization:

@UseGuards(JwtAuthGuard, OrgAccessGuard)
@Controller('organizations/:orgId/components')
export class ComponentsController {
// User must be a member of :orgId
}

OrgRolesGuard

Validates organization role (admin, owner, etc.):

@OrgRoles('admin', 'owner')
@UseGuards(JwtAuthGuard, OrgRolesGuard)
@Controller('organizations/:orgId/settings')
export class OrgSettingsController {
// User must be admin or owner of :orgId
}

OrgProductAccessGuard

Validates per-product role with hierarchy checks:

@ProductAccess('alerting', 'manager')
@UseGuards(JwtAuthGuard, OrgAccessGuard, OrgProductAccessGuard)
@Controller('organizations/:orgId/alerts')
export class AlertsController {
// User must have manager+ role for alerting product
}

Org OWNER, GLOBAL_ADMIN, and ADMIN bypass product role checks automatically.

PlatformAdminGuard

Restricts to Cognito PlatformAdmins group:

@PlatformAdmin()
@UseGuards(JwtAuthGuard, PlatformAdminGuard)
export class AdminController { ... }

ScimAuthGuard

Validates SCIM 2.0 bearer tokens (SHA256 hash lookup, revokedAt check):

@UseGuards(ScimAuthGuard)
@Controller('scim/v2')
export class ScimController { ... }

Accessing User Info

// Full user object
@Get('me')
getProfile(@CurrentUser() user: AuthUser) {
// user.userId, user.email, user.groups, user.isPlatformAdmin
}

// Shorthand: just the user ID
@Get('widgets')
getWidgets(@User('userId') userId: string) { ... }

Impersonation

Platform admins can impersonate users by setting the x-impersonate-user-id header. The original admin's identity is preserved:

  • user.originalUserId -- the admin's real user ID
  • user.originalEmail -- the admin's real email

This allows debugging user-specific issues without sharing credentials.

JWT Testing with curl

For testing production APIs from the command line:

One-Time Setup

Cache a refresh token (valid 30 days):

cd statux-api
AWS_CLI="aws" bash scripts/get-refresh-token.sh <your-email>

This prompts for your Cognito password once and saves the refresh token to ~/.statux-refresh-token.

Get a Fresh ID Token

TOKEN=$(aws cognito-idp admin-initiate-auth \
--user-pool-id us-east-1_75Rp4zNBg \
--client-id 2u986rkhchk6mur28sgpt0bm8p \
--auth-flow REFRESH_TOKEN_AUTH \
--auth-parameters "REFRESH_TOKEN=$(cat ~/.statux-refresh-token)" \
--query "AuthenticationResult.IdToken" --output text)

ID tokens expire after 1 hour. Re-run the command to get a fresh one. If the refresh token expires (after 30 days), re-run get-refresh-token.sh.

Use the Token

# Any API
curl -s -H "Authorization: Bearer $TOKEN" https://platform-api.statux.io/api/v1/users/me

# Org-scoped endpoint
ORG_ID="<org-uuid>"
curl -s -H "Authorization: Bearer $TOKEN" \
"https://alerts-api.statux.io/api/v1/organizations/$ORG_ID/alerts?page=1&limit=10"
note

The Cognito client has ALLOW_ADMIN_USER_PASSWORD_AUTH enabled. admin-initiate-auth requires AWS IAM credentials (SSO admin role) and is not exposed to the internet.