v2026.1 Open Portal ↗
On this page

Authentication & Authorization

Overview

StackFlow uses AWS Cognito User Pool (us-east-1_WKK1AVJ2m) as its identity provider. Every API request (except /health) must carry a valid Cognito ID token in the Authorization: Bearer header. The API Gateway Lambda authorizer decodes the JWT, validates the signature against Cognito's JWKS endpoint, and checks the user's role claims before forwarding the request to the StackFlowAPI Lambda.

ID token, not access token: Always pass the id_token, not the access_token. The ID token contains the custom:role and custom:tenant_id claims that StackFlow's authorizer requires. Requests using an access token will return 403 Forbidden.

Obtaining a Token via Cognito

Use the Cognito hosted UI or the /oauth2/token endpoint to acquire tokens. The hosted UI is at https://stackflow-identity-373544523367.auth.us-east-1.amazoncognito.com.

# Step 1: Build the authorization URL (PKCE flow)
# Redirect user to:
https://stackflow-identity-373544523367.auth.us-east-1.amazoncognito.com/oauth2/authorize
  ?response_type=code
  &client_id=570cnagpgoochn29a113du6jnt
  &redirect_uri=https://your-instance.stackflow-tech.com/callback
  &scope=openid+email+profile
  &code_challenge=BASE64URL(SHA256(code_verifier))
  &code_challenge_method=S256

# Step 2: Exchange authorization code for tokens
curl -X POST   https://stackflow-identity-373544523367.auth.us-east-1.amazoncognito.com/oauth2/token   -H "Content-Type: application/x-www-form-urlencoded"   -d "grant_type=authorization_code&client_id=570cnagpgoochn29a113du6jnt&code=AUTH_CODE&redirect_uri=https://your-instance.stackflow-tech.com/callback&code_verifier=PKCE_CODE_VERIFIER"
// Token response
{
  "access_token": "eyJraWQiOiJ...",
  "id_token": "eyJraWQiOiJ...",
  "refresh_token": "eyJjdHkiOiJ...",
  "expires_in": 3600,
  "token_type": "Bearer"
}

Token Types

TokenValidityUseClaims
ID Token1 hourStackFlow API authorizationemail, name, custom:role, custom:tenant_id
Access Token1 hourCognito UserInfo endpoint onlyscope, cognito:groups
Refresh Token30 daysSilently renew ID + access tokensn/a

Using the ID Token

# Store the id_token in an env var
export ID_TOKEN="eyJraWQiOiJ..."

# Make an authenticated API call
curl -H "Authorization: Bearer $ID_TOKEN"   https://your-instance.stackflow-tech.com/prod/api/incidents?limit=10
import requests

headers = {"Authorization": f"Bearer {id_token}"}
resp = requests.get(
    "https://your-instance.stackflow-tech.com/prod/api/incidents",
    headers=headers,
    params={"limit": 10, "state": "new"}
)
data = resp.json()

Refreshing Tokens

curl -X POST   https://stackflow-identity-373544523367.auth.us-east-1.amazoncognito.com/oauth2/token   -H "Content-Type: application/x-www-form-urlencoded"   -d "grant_type=refresh_token&client_id=570cnagpgoochn29a113du6jnt&refresh_token=REFRESH_TOKEN"

OAuth 2.0 Client Credentials

Service accounts and machine-to-machine integrations use the client credentials flow. Create a Cognito App Client with client credentials enabled (no hosted UI) and store the client secret in AWS Secrets Manager.

# Create a client credentials app client
aws cognito-idp create-user-pool-client   --user-pool-id us-east-1_WKK1AVJ2m   --client-name stackflow-service-account   --generate-secret   --allowed-o-auth-flows client_credentials   --allowed-o-auth-scopes "stackflow/api.read" "stackflow/api.write"   --allowed-o-auth-flows-user-pool-client   --region us-east-1

# Get a machine token
curl -X POST   https://stackflow-identity-373544523367.auth.us-east-1.amazoncognito.com/oauth2/token   -H "Content-Type: application/x-www-form-urlencoded"   -u "CLIENT_ID:CLIENT_SECRET"   -d "grant_type=client_credentials&scope=stackflow/api.read"

API Keys

For simpler integrations, StackFlow supports static API keys tied to a service account. API keys are generated in Admin → API Keys and passed via the x-api-key header. Keys are stored hashed in Aurora and can be revoked instantly.

curl -H "x-api-key: sfk_prod_abc123..."   https://your-instance.stackflow-tech.com/prod/api/incidents
API Key Scopes: Each API key is assigned a scope at creation: read-only, itsm-write, admin. Keys cannot exceed the permissions of the user account they are associated with.

Role-Based Access Control

RoleReadWriteAdminAI Endpoints
viewerYesNoNoNo
itsm_agentYesITSM onlyNoYes
itsm_managerYesYesITSM configYes
cloud_adminYesYesCloud moduleYes
super_adminYesYesFullYes
service_accountScopedScopedNoScoped

Token Troubleshooting

ErrorCodeCauseFix
401 UnauthorizedTOKEN_MISSINGNo Authorization headerAdd Authorization: Bearer <token>
401 UnauthorizedTOKEN_EXPIREDID token older than 1 hourRefresh using refresh token
403 ForbiddenWRONG_TOKEN_TYPEUsing access_token not id_tokenSwitch to id_token
403 ForbiddenINSUFFICIENT_ROLERole lacks required permissionRequest role elevation from admin
403 ForbiddenTENANT_MISMATCHToken tenant_id != resource tenantVerify user is in correct tenant