Security-sensitive controls must be enforced at the boundary (before business logic) and granted with the minimum required scope. Avoid designs where access is only checked after the request reaches handlers or where automation receives broad credentials.
Apply this as follows:
Example (pattern):
cognito:groups contains the admin group.Pseudocode for the custom authorizer decision:
// In custom Lambda authorizer
const groups = event.requestContext.authorizer.claims['cognito:groups'] || [];
const isAdmin = Array.isArray(groups) ? groups.includes('admin') : false;
if (!isAdmin) {
return generatePolicy('Deny', event.methodArn);
}
return generatePolicy('Allow', event.methodArn);
permissions to least privilege at the workflow level, then override per-job. Grant id-token: write only to jobs that need OIDC role assumption; other jobs should use only contents: read or similarly minimal scopes.Example:
permissions: read-all
jobs:
unit:
permissions:
contents: read
e2e:
permissions:
contents: read
id-token: write
Outcome: fewer authorization gaps across routes and fewer accidental credential overexposures in CI, improving overall security posture.