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 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
| Token | Validity | Use | Claims |
|---|---|---|---|
| ID Token | 1 hour | StackFlow API authorization | email, name, custom:role, custom:tenant_id |
| Access Token | 1 hour | Cognito UserInfo endpoint only | scope, cognito:groups |
| Refresh Token | 30 days | Silently renew ID + access tokens | n/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
read-only, itsm-write, admin. Keys cannot exceed the permissions of the user account they are associated with.
Role-Based Access Control
| Role | Read | Write | Admin | AI Endpoints |
|---|---|---|---|---|
viewer | Yes | No | No | No |
itsm_agent | Yes | ITSM only | No | Yes |
itsm_manager | Yes | Yes | ITSM config | Yes |
cloud_admin | Yes | Yes | Cloud module | Yes |
super_admin | Yes | Yes | Full | Yes |
service_account | Scoped | Scoped | No | Scoped |
Token Troubleshooting
| Error | Code | Cause | Fix |
|---|---|---|---|
| 401 Unauthorized | TOKEN_MISSING | No Authorization header | Add Authorization: Bearer <token> |
| 401 Unauthorized | TOKEN_EXPIRED | ID token older than 1 hour | Refresh using refresh token |
| 403 Forbidden | WRONG_TOKEN_TYPE | Using access_token not id_token | Switch to id_token |
| 403 Forbidden | INSUFFICIENT_ROLE | Role lacks required permission | Request role elevation from admin |
| 403 Forbidden | TENANT_MISMATCH | Token tenant_id != resource tenant | Verify user is in correct tenant |