PATTERN Cited by 1 source
Pre-token-generation hook¶
Shape¶
A pre-token-generation hook is a function an identity provider invokes between authentication success and token signing, allowing the app to fetch and inject custom claims into the resulting JWT. The claims then travel with every subsequent request and can be read by downstream authorizers without any additional lookup.
Canonical AWS instance: Amazon Cognito's pre-token-generation Lambda trigger.
User login → Cognito validates credentials
→ Pre-token Lambda invoked (given user identity)
├── Query application DB (RDS / DynamoDB)
├── Return {role, group_memberships, tenant_id, ...}
→ Cognito signs JWT with enriched claims
→ Client receives JWT
→ Every subsequent API call carries these claims
→ Lambda authorizer evaluates policies over claims only
(Source: sources/2026-02-05-aws-convera-verified-permissions-fine-grained-authorization)
Why it works¶
- Pushes per-user attribute lookup off the hot path. The lookup happens once per session at login, not once per API call. Downstream authorization reads claims directly from the signed JWT.
- Cryptographically bound attributes. Because the JWT is signed, the client cannot modify the claims. Attributes are trustworthy without further verification.
- Native integration with policy engines.
AVP's
IsAuthorizedWithTokenAPI evaluates Cedar policies directly against JWT claims; no claim-to-attribute translation code needed. - Separates authorship of identity (IdP) from authorship of authorization attributes (app). The IdP holds identity; the hook populates app-specific attributes at the join point.
Flow variants (Convera)¶
Four flows, same hook mechanism, different sources:
- Customer: hook reads user roles from RDS; enriches JWT with
roleclaim. - Internal (Okta-federated): hook reads attributes from DynamoDB (user attribute store); customizes access token (not ID token).
- Machine-to-machine: service clients registered in a client config system; access tokens minted via OAuth client-credentials carry service identifier, tier, allowed ops, rate limits (may or may not use the hook depending on how much the client-config system pushes into Cognito registration).
- Multi-tenant: hook reads
user_id → tenant_idmapping from DynamoDB; enriches JWT withtenant_idclaim.
Trade-offs¶
- Token-lifetime pinning. Attributes are pinned for the token lifetime (typically minutes to hours). Attribute changes (role demoted, tenant added) do not take effect until token refresh. Mitigations: short token lifetimes (expensive), denylist (defeats the no-lookup advantage), or per-request lookup for volatile attributes only.
- Hook latency affects login latency. The hook is on the login path; slow database lookups there degrade user login experience. Keep the hook query small and indexed.
- Hook failure modes. If the hook throws, Cognito either fails the login or (with care) can sign a token without enrichment. The downstream authorizer must handle missing-claims gracefully.
- Hook = additional IAM surface. The Lambda needs IAM to read RDS / DynamoDB; that IAM is on the authorization-critical path.
Where to customize: ID vs access token¶
- ID token: identity assertion (who), audience = client app. Don't pollute with authz-relevant attributes the client shouldn't see.
- Access token: authorization grant (what), audience = resource server / authorizer. The right place for enriched authz claims.
Convera's internal flow explicitly customizes the access token only.
Cross-IdP portability¶
The pattern generalizes:
- Auth0 — Actions / Rules.
- Keycloak — Token Mappers / Script Mappers.
- Okta — Inline Hooks / Token Inline Hook.
- Azure AD — Claims mapping policies.
Cognito's hook is distinguished mainly by being a first-class Lambda with full AWS-SDK access (can query any AWS data store cheaply).
Seen in¶
- sources/2026-02-05-aws-convera-verified-permissions-fine-grained-authorization — canonical production instance across all four Convera flows (customer, internal Okta-federated, machine-to-machine, multi-tenant); each flow uses the hook to inject authorization-relevant attributes from RDS / DynamoDB into the Cognito-issued JWT so the downstream Lambda authorizer + AVP can evaluate policies with no secondary lookup.
Related¶
- concepts/token-enrichment — the concept this pattern implements.
- systems/amazon-cognito — the native AWS IdP substrate.
- systems/aws-lambda — the hook compute.
- patterns/lambda-authorizer — the downstream consumer of enriched tokens.
- concepts/fine-grained-authorization — the evaluation model token enrichment serves.