Auth Architecture
Last Updated: 2026-03-06 Sources:
innovation-sandbox-on-aws(auth-api.ts, rest-api-all.ts, authorizer-handler.ts, authorization.ts, authorization-map.ts, sso-handler, jwt.ts),.state/scps/*.json
Executive Summary
The NDX:Try AWS platform implements a layered authentication and authorization model combining SAML 2.0 via AWS IAM Identity Center for user identity, JWT bearer tokens for stateless API authentication, role-based access control (RBAC) with three ISB roles (Admin, Manager, User), and GitHub OIDC for credential-less CI/CD deployments. All authentication flows converge in the Hub account (568672915267), where a Lambda authorizer validates JWT tokens against secrets stored in AWS Secrets Manager, with WAF-enforced IP allow-listing and rate limiting providing defence in depth at the API Gateway layer.
Authentication Architecture Overview
1. IAM Identity Center (SAML 2.0) Configuration
Identity Source
| Property | Value |
|---|---|
| Identity Source | Identity Center Directory (AWS Managed) |
| Region | us-west-2 |
| SAML Application | Innovation Sandbox on AWS |
| Application Start URL | https://isb.try.ndx.digital.cabinet-office.gov.uk |
| NameID Format | urn:oasis:names:tc:SAML:2.0:nameid-format:persistent |
SAML Attribute Mappings
| Attribute | Source | Purpose |
|---|---|---|
Subject | ${user:subject} | Unique user identifier (nameID) |
email | ${user:email} | User email address |
name | ${user:name} | Display name |
department | ${user:department} | Organization/Department |
IdP Certificate Storage
The IdP X.509 certificate used to validate SAML assertions is stored in AWS Secrets Manager:
- Secret Name:
/isb/<namespace>/Auth/IdpCert - Encryption: Customer-managed KMS key
- Rotation: Manual (when the IdP certificate rotates, typically annually)
Source: auth-api.ts lines 91-101
User Groups
| Group | Purpose |
|---|---|
| ISB-Admins | Platform administrators with full control |
| ISB-Users | Standard sandbox requesters |
| ISB-Managers | Lease approval and operational management |
2. SAML Authentication Flow
SSO Handler Implementation
The SSO handler is an Express.js application running inside a Lambda function, using @node-saml/passport-saml for SAML processing. It exposes the following routes via /api/auth/{action+}:
| Route | Method | Auth Required | Purpose |
|---|---|---|---|
/auth/login | GET | No | Initiate SAML authentication |
/auth/login/callback | POST | No | Process SAML assertion |
/auth/login/status | GET | JWT | Check authentication status |
/auth/logout | GET | No | Redirect to IdP sign-out |
Configuration: Loaded from AppConfig (global configuration) and Secrets Manager, including session duration, IdP URLs, and IdP audience.
Source: sso-handler/src/server.ts, sso-handler/src/config.ts
SAML Validation
The passport-saml strategy validates:
- XML signature using the stored IdP X.509 certificate
- Audience restriction against the configured
idpAudience - Timestamp validity (NotBefore/NotOnOrAfter)
After validation, the handler resolves the user's ISB identity by calling User.getIsbUser(nameID), which assumes a cross-account role into the Identity Center account via IntermediateRole to query the Identity Center directory.
Source: sso-handler/src/user.ts
3. JWT Token Management
JWT Structure
The JWT tokens are signed using the jsonwebtoken library with HMAC-SHA256:
Payload:
{
"user": {
"displayName": "User Name",
"userName": "user@example.gov.uk",
"email": "user@example.gov.uk",
"roles": ["User"]
},
"iat": 1709337600,
"exp": 1709351400
}
Signing: jwt.sign({user: isbUser}, jwtSecret, {expiresIn: sessionDuration})
Session Duration: Configurable via AppConfig (auth.sessionDurationInMinutes)
Source: sso-handler/src/server.ts line 212, common/utils/jwt.ts
JWT Secret
| Property | Value |
|---|---|
| Storage | AWS Secrets Manager |
| Secret Name | /isb/<namespace>/Auth/JwtSecret |
| Encryption | Customer-managed KMS key |
| Length | 32 characters (alphanumeric + symbols) |
| Rotation | Automatic every 30 days |
| Rotation Lambda | JwtSecretRotator (reserved concurrency: 1) |
Source: auth-api.ts lines 47-89
JWT Secret Rotation
The rotation Lambda (secret-rotator-handler.ts) follows the four-step Secrets Manager rotation protocol:
- createSecret: Generates a new 32-character random password via
GetRandomPasswordCommandand stores it asAWSPENDING - setSecret: No-op (no external system to update)
- testSecret: No-op (JWT validation is inherently tested on next use)
- finishSecret: Promotes
AWSPENDINGtoAWSCURRENTand demotes old version
Source: secret-rotator/src/secret-rotator-handler.ts
4. API Gateway Authorization
Request Authorizer
The API Gateway uses a Request-based Lambda authorizer (not Token-based), with identity sources drawn from the Authorization header, request path, and HTTP method:
const authorizer = new RequestAuthorizer(scope, "Authorizer", {
handler: authorizerLambdaFunction.lambdaFunction,
identitySources: [
IdentitySource.header("Authorization"),
IdentitySource.context("path"),
IdentitySource.context("httpMethod"),
],
resultsCacheTtl: Duration.minutes(5),
});
Cache TTL: 5 minutes (reduces Secrets Manager API calls)
Source: rest-api-all.ts lines 101-109
Authorization Flow
Role-Based Access Control (RBAC)
ISB defines three roles as a Zod enum: Admin, Manager, User.
Source: common/types/isb-types.ts line 5
The authorization map defines which roles can access which endpoints:
| Endpoint | GET | POST | PATCH | PUT | DELETE |
|---|---|---|---|---|---|
/leases | Manager, Admin, User | User, Manager, Admin | - | - | - |
/leases/{param} | User, Manager, Admin | - | Manager, Admin | - | - |
/leases/{param}/review | - | Manager, Admin | - | - | - |
/leases/{param}/terminate | - | Manager, Admin | - | - | - |
/leases/{param}/freeze | - | Manager, Admin | - | - | - |
/leases/{param}/unfreeze | - | Manager, Admin | - | - | - |
/leaseTemplates | User, Manager, Admin | Admin, Manager | - | - | - |
/leaseTemplates/{param} | User, Manager, Admin | - | - | Admin, Manager | Admin, Manager |
/configurations | Manager, Admin, User | - | - | - | - |
/accounts | Admin | Admin | - | - | - |
/accounts/{param} | Admin | - | - | - | - |
/accounts/{param}/retryCleanup | - | Admin | - | - | - |
/accounts/{param}/eject | - | Admin | - | - | - |
/accounts/unregistered | Admin | - | - | - | - |
Source: authorizer/src/authorization-map.ts
Maintenance Mode
When globalConfig.maintenanceMode is enabled, only Admin users and GET /configurations requests are allowed. All other requests receive a Deny policy.
Source: authorizer-handler.ts lines 63-70
5. WAF Protection
The API Gateway has a regional WAF WebACL attached with five rules, evaluated in priority order:
| Priority | Rule | Action | Description |
|---|---|---|---|
| 0 | IsbAllowListRule | Block (non-matching) | IP allow-list using X-Forwarded-For header; blocks requests not from allowed CIDRs |
| 1 | IsbRateLimitRule | Block (429) | Rate-based rule: 200 requests per 60-second window per forwarded IP |
| 2 | AWSManagedRulesCommonRuleSet | Override:none | AWS managed rules (excludes SizeRestrictions_BODY, SizeRestrictions_QUERYSTRING, CrossSiteScripting_BODY) |
| 3 | AWSManagedRulesAmazonIpReputationList | Override:none | Blocks known malicious IPs |
| 4 | AWSManagedRulesAnonymousIpList | Override:none | Blocks VPN/proxy/Tor exit nodes |
Source: rest-api-all.ts lines 135-272
6. Cross-Account IAM Role Chains
Hub to Pool Account
The SSO handler and other Lambda functions use a two-hop role chain:
- Lambda execution role assumes
IntermediateRolein the Hub account IntermediateRoleassumesOrganizationAccountAccessRolein the target pool account
Hub to Identity Center Account
For user lookups during SAML callback:
- SSO Handler Lambda assumes
IntermediateRole IntermediateRoleassumes the IDC role in the Identity Center account (specified byIDC_ROLE_ARN)
Source: sso-handler/src/user.ts lines 13-23
7. GitHub Actions OIDC Authentication
GitHub Actions workflows authenticate to AWS using OIDC without long-lived credentials:
- Workflow requests a JWT from GitHub's OIDC provider
- AWS STS validates the JWT against
token.actions.githubusercontent.com - Trust policy conditions verify repository ownership (
co-cddo/*) and audience (sts.amazonaws.com) - STS returns temporary credentials (1-hour session)
See 51-oidc-configuration.md for the full OIDC provider and role inventory.
8. Security Controls Summary
| Control | Implementation |
|---|---|
| SAML Assertion Validation | X.509 signature, timestamp, audience restriction via passport-saml |
| JWT Signing | HMAC-SHA256 with 32-character secret |
| JWT Secret Rotation | Automatic 30-day rotation via Secrets Manager |
| Authorizer Caching | 5-minute cache TTL on API Gateway |
| RBAC Enforcement | Path+method authorization map with three ISB roles |
| Maintenance Mode | AppConfig-driven, restricts to Admin only |
| IP Allow-Listing | WAF IP set on X-Forwarded-For header |
| Rate Limiting | 200 requests/minute per IP via WAF |
| Managed WAF Rules | Common Rule Set, IP Reputation, Anonymous IP List |
| HTTPS Enforcement | CloudFront REDIRECT_TO_HTTPS, TLS 1.2+ minimum |
| Security Headers | HSTS, X-Frame-Options DENY, CSP, X-Content-Type-Options, Referrer-Policy |
| No Auth on SSO Endpoints | /auth/{action+} explicitly uses AuthorizationType.NONE |
| Cross-Account Roles | IntermediateRole with explicit trust, short-lived STS credentials |
| OIDC for CI/CD | No long-lived access keys; repository-scoped trust |
Related Documents
- 05-service-control-policies.md - SCP guardrails applied to pool accounts
- 10-isb-core-architecture.md - Core ISB architecture and Lambda functions
- 51-oidc-configuration.md - GitHub OIDC provider and role details
- 04-cross-account-trust.md - Full IAM role inventory
- 62-secrets-management.md - Secrets architecture and rotation
Generated from source analysis. See 00-repo-inventory.md for full inventory.