@venturekit/auth API
Functions
Section titled “Functions”Cognito
Section titled “Cognito”| Function | Description |
|---|---|
createCognitoConfig(security) | Create Cognito config from SecurityConfig |
buildUserPoolConfig(config) | Build User Pool infrastructure config |
| Function | Signature | Description |
|---|---|---|
hasScope | (roles: string[], scope: string, config: RolesConfig) => boolean | Check if roles grant a scope |
hasAnyScope | (roles: string[], scopes: string[], config: RolesConfig) => boolean | Check if roles grant any of the scopes |
hasAllScopes | (roles: string[], scopes: string[], config: RolesConfig) => boolean | Check if roles grant all scopes |
getScopesForRoles | (roles: string[], config: RolesConfig) => string[] | Get all scopes granted by roles |
validateRolesConfig | (config: RolesConfig) => ValidationResult | Validate a roles configuration |
DB-backed role → scopes (vk_role_scopes)
Section titled “DB-backed role → scopes (vk_role_scopes)”A mutable role → scope matrix backed by the vk_role_scopes table. The table structure ships with this package’s migrations (vk_auth_003_role_scopes.sql); the rows are your app’s authorization policy — seed them in an app data migration and change them at runtime (e.g. from an admin UI) without redeploying. Every helper takes a caller-supplied Querier (same shape as @venturekit/data’s query), so the package keeps no hard data-layer dependency.
Baseline authorization for any app: single-tenant apps resolve a user’s global role through the resolver and grant the result; multi-tenant apps pass resolver.lookup as scopesByRole to @venturekit-pro/tenancy’s createTenantUserScopesMiddleware.
| Function | Signature | Description |
|---|---|---|
listRoleScopes(q) | (Querier) => Promise<Record<string, string[]>> | The full mapping, { role: [scope, …] } (scopes sorted). |
getRoleScopes(q, role) | (Querier, string) => Promise<string[]> | Scopes granted by one role ([] when unknown). |
setRoleScopes(q, role, scopes) | (Querier, string, readonly string[]) => Promise<void> | Replace a role’s scope set atomically. An empty array removes the role. |
grantScopeToRole(q, role, scope) | (Querier, string, string) => Promise<void> | Add one grant (idempotent). |
revokeScopeFromRole(q, role, scope) | (Querier, string, string) => Promise<void> | Remove one grant (idempotent). |
createRoleScopesResolver(options) | (RoleScopesResolverOptions) => RoleScopesResolver | Cached hot-path resolver (below). |
createRoleScopesResolver reads the whole table once and caches it per process with a TTL (ttlMs, default 30_000):
interface RoleScopesResolverOptions { querier: Querier; ttlMs?: number }interface RoleScopesResolver { lookup: (role: string) => Promise<readonly string[]> | readonly string[]; // pass as scopesByRole invalidate(): void; // drop the cache — the next lookup reloads from the DB}Consistency: the mutating instance calls invalidate() and sees the change immediately; other warm instances converge within one TTL. Availability: if a reload fails but a previous snapshot exists, the stale snapshot is served; a cold-start failure with no snapshot throws (failing loudly rather than silently granting nothing to everyone).
Federated sign-in (@venturekit/auth/server)
Section titled “Federated sign-in (@venturekit/auth/server)”These helpers implement the server-side OAuth Authorization Code
flow. VentureKit does not enable the Cognito Hosted UI; the SPA
runs the redirect dance, the API exchanges the code with the IdP
back-channel (so the client_secret never leaves the server).
| Function | Signature | Description |
|---|---|---|
generateOAuthState() | () => string | Mint a random URL-safe state token. The /start route returns it AND pins it to the browser via an HttpOnly cookie. |
verifyOAuthState(fromQuery, fromCookie) | (string?, string?) => boolean | Constant-time compare for the /complete CSRF check. |
buildAuthorizeUrl(input, env?) | (BuildAuthorizeUrlInput) => Promise<string> | Build the IdP authorize URL the SPA navigates to. Loads client_id from Secrets Manager. |
exchangeAuthorizationCode(input, env?) | (ExchangeAuthorizationCodeInput) => Promise<FederatedProfile> | Back-channel POST to the IdP token endpoint, then resolve the verified profile (Google id_token claims / Facebook /me Graph). |
signInAsFederatedUser(input, config?) | (SignInAsFederatedUserInput) => Promise<SignInResult> | Idempotently create / refresh the Cognito user for a verified FederatedProfile and mint session tokens via ADMIN_USER_PASSWORD_AUTH. |
loadFederatedProviderCredentials(provider, env?) | (FederatedProvider) => Promise<FederatedProviderCredentials> | Read the OAuth client id/secret from the Secrets Manager placeholder. Cached per Lambda container. |
Verification codes (@venturekit/auth/server)
Section titled “Verification codes (@venturekit/auth/server)”OTP toolkit for the “we’ll text you a 6-digit code” gate. Pluggable
storage via VerificationCodeStore; channel is opaque ('email' /
'whatsapp' / anything else the application defines).
| Function | Signature | Description |
|---|---|---|
generateVerificationCode(length?) | (number?) => string | crypto.randomInt-backed digits. Default 6, range 4–10. |
hashVerificationCode(code) | (string) => string | SHA-256 hex digest stored on disk. |
requestVerificationCode(input) | (RequestVerificationCodeInput) => Promise<{ code, expiresAt }> | Mint + persist + return plaintext for delivery. Overwrites any previous code for the same (channel, identifier). |
verifyVerificationCode(input) | (VerifyVerificationCodeInput) => Promise<void> | Constant-time check; deletes on success, increments attempts on mismatch, wipes after maxAttempts. Throws verification_failed (HTTP 401). |
createPostgresVerificationCodeStore(q?) | (Querier?) => VerificationCodeStore | Production store over vk_verification_codes (table ships with this package’s migrations). Pass a transaction’s query to enlist writes in an open transaction; omit for the global pool. Import from @venturekit/auth/server/store/postgres. |
createInMemoryVerificationCodeStore() | () => VerificationCodeStore | Tests / vk dev only. |
The placeholder secret VentureKit provisions for each declared
AuthIntent.federated provider is named
venturekit/<project>/<stage>/auth/<intent.id>/<provider> and holds
{"clientId":"PLACEHOLDER","clientSecret":"PLACEHOLDER"}. Populate it
after the first deploy:
aws secretsmanager put-secret-value \ --secret-id <arn-from-cfn-output> \ --secret-string '{"clientId":"…","clientSecret":"…"}'Session / JWT
Section titled “Session / JWT”| Function | Signature | Description |
|---|---|---|
decodeTokenUnsafe | (jwt: string) => Record<string, unknown> | null | Decode JWT without verifying the signature. Use only when the token has already been verified upstream (e.g. API Gateway Cognito Authorizer). |
decodeToken | (jwt: string) => Record<string, unknown> | null | Deprecated alias of decodeTokenUnsafe. Prefer the explicit name. |
verifyAndDecode | (jwt: string, opts: VerifyOptions) => Promise<Record<string, unknown> | null> | Verify the JWT signature against the Cognito JWKS and decode the claims. Use when the token has not been gated upstream. |
extractUserFromToken | (jwt: string) => User | null | Extract user from ID token |
isTokenExpired | (jwt: string) => boolean | Check if token is expired |
getTokenExpiry | (jwt: string) => Date | null | Get token expiry as Date |
Auth Domain Types
Section titled “Auth Domain Types”Exported from ./types/index.js — includes User, Session, Role, Permission, RolesConfig, and related types.
Infrastructure Types
Section titled “Infrastructure Types”| Type | Description |
|---|---|
UserPoolOutputs | Cognito User Pool deployment outputs |
UserPoolInfraConfig | Cognito infrastructure configuration |
Role → scopes types
Section titled “Role → scopes types”Exported from ./roles/index.js (see the DB-backed role → scopes section above): Querier, RoleScopeRow, RoleScopesLookup, RoleScopesResolver, RoleScopesResolverOptions.
Constants
Section titled “Constants”| Constant | Description |
|---|---|
DEFAULT_COGNITO_CONFIG | Default Cognito configuration |