Cognito: API reference
LocalEmu generates real RS256-signed JWT tokens for Cognito user pools. Tokens are verifiable with standard libraries, JWKS endpoints work, and OIDC discovery is fully functional.
Want a runnable walkthrough? See Cognito: demo & walkthrough.
Token Overview
Endpoints
| Endpoint | URL |
|---|---|
| JWKS | <base>/<pool-id>/.well-known/jwks.json |
| OIDC discovery | <base>/<pool-id>/.well-known/openid-configuration |
Token issuer (iss claim) | <base>/<pool-id> |
| OAuth2 authorize | <base>/oauth2/authorize |
| OAuth2 token | <base>/oauth2/token |
| OAuth2 userInfo | <base>/oauth2/userInfo |
<base> is whatever
external_service_url() returns for this LocalEmu instance:
http://localhost:4566 on a default install, or
the value of LOCALEMU_HOST /
LOCALEMU_PUBLISH_URL when set. The
iss claim in every issued JWT uses the same base,
so a JWT verifier configured against the discovery document will accept the tokens this LocalEmu
instance signs without an issuer-mismatch error. Only the per-pool URLs
(jwks.json, openid-configuration,
the iss URL itself) carry the
<pool-id> path segment; the OAuth2 endpoints do not.
Token Claims
ID Token
| Claim | Description |
|---|---|
| sub | Unique user identifier (UUID) |
| User's email address | |
| cognito:username | The username used for authentication |
| cognito:groups | List of groups the user belongs to |
| token_use | Always id |
Access Token
| Claim | Description |
|---|---|
| username | The authenticated username |
| client_id | The app client ID used for authentication |
| scope | OAuth2 scopes granted to the token |
| token_use | Always access |
Refresh Token
Refresh tokens are opaque strings, not JWTs. They can be used with
AdminInitiateAuth using the
REFRESH_TOKEN_AUTH flow to obtain new ID and access tokens.
Example: Full Authentication Flow
Step 1: Create a user pool
$ awsemu cognito-idp create-user-pool \
--pool-name my-app-pool
UserPool:
Id: us-east-1_abc123XYZ
Name: my-app-pool Step 2: Create an app client
$ awsemu cognito-idp create-user-pool-client \
--user-pool-id us-east-1_abc123XYZ \
--client-name my-app \
--explicit-auth-flows ALLOW_ADMIN_USER_PASSWORD_AUTH
UserPoolClient:
ClientId: 3abcdef12345
ClientName: my-app Step 3: Create a user and set their password
$ awsemu cognito-idp admin-create-user \
--user-pool-id us-east-1_abc123XYZ \
--username testuser \
--user-attributes Name=email,Value=test@example.com
$ awsemu cognito-idp admin-set-user-password \
--user-pool-id us-east-1_abc123XYZ \
--username testuser \
--password 'Str0ng!Pass' \
--permanent Step 4: Authenticate and get tokens
$ awsemu cognito-idp admin-initiate-auth \
--user-pool-id us-east-1_abc123XYZ \
--client-id 3abcdef12345 \
--auth-flow ADMIN_USER_PASSWORD_AUTH \
--auth-parameters USERNAME=testuser,PASSWORD='Str0ng!Pass'
AuthenticationResult:
AccessToken: eyJraWQiOiJhYmMx... (truncated)
IdToken: eyJraWQiOiJhYmMx... (truncated)
RefreshToken: a1b2c3d4e5... (opaque)
ExpiresIn: 3600
TokenType: Bearer Step 5: Fetch the JWKS public key
$ curl -s http://localhost:4566/us-east-1_abc123XYZ/.well-known/jwks.json | python3 -m json.tool
{
"keys": [
{
"kty": "RSA",
"kid": "abc123",
"use": "sig",
"alg": "RS256",
"n": "0vx7agoebGcQ...",
"e": "AQAB"
}
]
} Step 6: Check OIDC discovery
$ curl -s http://localhost:4566/us-east-1_abc123XYZ/.well-known/openid-configuration | python3 -m json.tool
{
"issuer": "http://localhost:4566/us-east-1_abc123XYZ",
"jwks_uri": "http://localhost:4566/us-east-1_abc123XYZ/.well-known/jwks.json",
"authorization_endpoint": "http://localhost:4566/oauth2/authorize",
"token_endpoint": "http://localhost:4566/oauth2/token",
"userinfo_endpoint": "http://localhost:4566/oauth2/userInfo",
"id_token_signing_alg_values_supported": ["RS256"],
"response_types_supported": ["code", "token"],
"scopes_supported": ["openid", "email", "phone", "profile"],
"subject_types_supported": ["public"],
"token_endpoint_auth_methods_supported": [
"client_secret_basic",
"client_secret_post"
],
"claims_supported": [
"sub", "iss", "auth_time",
"email", "email_verified",
"phone_number", "phone_number_verified",
"cognito:username", "cognito:groups"
]
} Python Token Verification
Verify tokens using PyJWT and
requests. Install with:
pip install PyJWT cryptography requests
import jwt
import requests
POOL_ID = "us-east-1_abc123XYZ"
JWKS_URL = f"http://localhost:4566/{POOL_ID}/.well-known/jwks.json"
# Fetch the public keys
jwks = requests.get(JWKS_URL).json()
jwk_key = jwks["keys"][0]
public_key = jwt.algorithms.RSAAlgorithm.from_jwk(jwk_key)
# Verify the ID token
id_token = "eyJraWQiOiJhYmMx..." # from AuthenticationResult
decoded = jwt.decode(
id_token,
key=public_key,
algorithms=["RS256"],
issuer=f"http://localhost:4566/{POOL_ID}",
options={"verify_aud": False},
)
print(f"Subject: {decoded['sub']}")
print(f"Email: {decoded['email']}")
print(f"Username: {decoded['cognito:username']}")
print(f"Groups: {decoded.get('cognito:groups', [])}") API Gateway V2 JWT Authorizers
LocalEmu's Cognito tokens work with API Gateway V2 (HTTP API) JWT authorizers. The authorizer fetches the JWKS from the issuer URL and validates the token signature, expiration, and audience automatically.
http://localhost:4566/<pool-id>