@happyvertical/auth 0.103.4 → 0.103.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENT.md +1 -1
- package/README.md +61 -0
- package/dist/chunks/{decode_jwt-DyHK2A0i.js → decode_jwt-ob-gfrt8.js} +2 -2
- package/dist/chunks/{decode_jwt-DyHK2A0i.js.map → decode_jwt-ob-gfrt8.js.map} +1 -1
- package/dist/chunks/{google-D8L8_cDF.js → google-CyESKfaj.js} +4 -3
- package/dist/chunks/{google-D8L8_cDF.js.map → google-CyESKfaj.js.map} +1 -1
- package/dist/chunks/{kanidm-YfZNisdt.js → kanidm-XUwRGxXX.js} +4 -3
- package/dist/chunks/{kanidm-YfZNisdt.js.map → kanidm-XUwRGxXX.js.map} +1 -1
- package/dist/chunks/{keycloak-hR2UOZ1n.js → keycloak-Bfk3iJUJ.js} +4 -3
- package/dist/chunks/{keycloak-hR2UOZ1n.js.map → keycloak-Bfk3iJUJ.js.map} +1 -1
- package/dist/chunks/remote-D3qRdbiU.js +274 -0
- package/dist/chunks/remote-D3qRdbiU.js.map +1 -0
- package/dist/chunks/{remote-C3O0f74l.js → verify-CGYWoFss.js} +80 -274
- package/dist/chunks/verify-CGYWoFss.js.map +1 -0
- package/dist/index.js +3 -3
- package/dist/local.js +2 -1
- package/dist/local.js.map +1 -1
- package/dist/server/index.d.ts +90 -0
- package/dist/server/index.d.ts.map +1 -0
- package/dist/server/index.js +761 -0
- package/dist/server/index.js.map +1 -0
- package/dist/server/memory.d.ts +34 -0
- package/dist/server/memory.d.ts.map +1 -0
- package/dist/server/types.d.ts +182 -0
- package/dist/server/types.d.ts.map +1 -0
- package/metadata.json +2 -1
- package/package.json +6 -2
- package/dist/chunks/remote-C3O0f74l.js.map +0 -1
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","names":["#payload","#protectedHeader","#unprotectedHeader","b64u","encode","#flattened","#jwt","#protectedHeader"],"sources":["../../../../node_modules/.pnpm/jose@6.2.2/node_modules/jose/dist/webapi/jws/flattened/sign.js","../../../../node_modules/.pnpm/jose@6.2.2/node_modules/jose/dist/webapi/jws/compact/sign.js","../../../../node_modules/.pnpm/jose@6.2.2/node_modules/jose/dist/webapi/jwt/sign.js","../../src/server/types.ts","../../src/server/memory.ts","../../src/server/index.ts"],"sourcesContent":["import { encode as b64u } from '../../util/base64url.js';\nimport { sign } from '../../lib/signing.js';\nimport { isDisjoint } from '../../lib/type_checks.js';\nimport { JWSInvalid } from '../../util/errors.js';\nimport { concat, encode } from '../../lib/buffer_utils.js';\nimport { checkKeyType } from '../../lib/check_key_type.js';\nimport { validateCrit } from '../../lib/validate_crit.js';\nimport { normalizeKey } from '../../lib/normalize_key.js';\nimport { assertNotSet } from '../../lib/helpers.js';\nexport class FlattenedSign {\n #payload;\n #protectedHeader;\n #unprotectedHeader;\n constructor(payload) {\n if (!(payload instanceof Uint8Array)) {\n throw new TypeError('payload must be an instance of Uint8Array');\n }\n this.#payload = payload;\n }\n setProtectedHeader(protectedHeader) {\n assertNotSet(this.#protectedHeader, 'setProtectedHeader');\n this.#protectedHeader = protectedHeader;\n return this;\n }\n setUnprotectedHeader(unprotectedHeader) {\n assertNotSet(this.#unprotectedHeader, 'setUnprotectedHeader');\n this.#unprotectedHeader = unprotectedHeader;\n return this;\n }\n async sign(key, options) {\n if (!this.#protectedHeader && !this.#unprotectedHeader) {\n throw new JWSInvalid('either setProtectedHeader or setUnprotectedHeader must be called before #sign()');\n }\n if (!isDisjoint(this.#protectedHeader, this.#unprotectedHeader)) {\n throw new JWSInvalid('JWS Protected and JWS Unprotected Header Parameter names must be disjoint');\n }\n const joseHeader = {\n ...this.#protectedHeader,\n ...this.#unprotectedHeader,\n };\n const extensions = validateCrit(JWSInvalid, new Map([['b64', true]]), options?.crit, this.#protectedHeader, joseHeader);\n let b64 = true;\n if (extensions.has('b64')) {\n b64 = this.#protectedHeader.b64;\n if (typeof b64 !== 'boolean') {\n throw new JWSInvalid('The \"b64\" (base64url-encode payload) Header Parameter must be a boolean');\n }\n }\n const { alg } = joseHeader;\n if (typeof alg !== 'string' || !alg) {\n throw new JWSInvalid('JWS \"alg\" (Algorithm) Header Parameter missing or invalid');\n }\n checkKeyType(alg, key, 'sign');\n let payloadS;\n let payloadB;\n if (b64) {\n payloadS = b64u(this.#payload);\n payloadB = encode(payloadS);\n }\n else {\n payloadB = this.#payload;\n payloadS = '';\n }\n let protectedHeaderString;\n let protectedHeaderBytes;\n if (this.#protectedHeader) {\n protectedHeaderString = b64u(JSON.stringify(this.#protectedHeader));\n protectedHeaderBytes = encode(protectedHeaderString);\n }\n else {\n protectedHeaderString = '';\n protectedHeaderBytes = new Uint8Array();\n }\n const data = concat(protectedHeaderBytes, encode('.'), payloadB);\n const k = await normalizeKey(key, alg);\n const signature = await sign(alg, k, data);\n const jws = {\n signature: b64u(signature),\n payload: payloadS,\n };\n if (this.#unprotectedHeader) {\n jws.header = this.#unprotectedHeader;\n }\n if (this.#protectedHeader) {\n jws.protected = protectedHeaderString;\n }\n return jws;\n }\n}\n","import { FlattenedSign } from '../flattened/sign.js';\nexport class CompactSign {\n #flattened;\n constructor(payload) {\n this.#flattened = new FlattenedSign(payload);\n }\n setProtectedHeader(protectedHeader) {\n this.#flattened.setProtectedHeader(protectedHeader);\n return this;\n }\n async sign(key, options) {\n const jws = await this.#flattened.sign(key, options);\n if (jws.payload === undefined) {\n throw new TypeError('use the flattened module for creating JWS with b64: false');\n }\n return `${jws.protected}.${jws.payload}.${jws.signature}`;\n }\n}\n","import { CompactSign } from '../jws/compact/sign.js';\nimport { JWTInvalid } from '../util/errors.js';\nimport { JWTClaimsBuilder } from '../lib/jwt_claims_set.js';\nexport class SignJWT {\n #protectedHeader;\n #jwt;\n constructor(payload = {}) {\n this.#jwt = new JWTClaimsBuilder(payload);\n }\n setIssuer(issuer) {\n this.#jwt.iss = issuer;\n return this;\n }\n setSubject(subject) {\n this.#jwt.sub = subject;\n return this;\n }\n setAudience(audience) {\n this.#jwt.aud = audience;\n return this;\n }\n setJti(jwtId) {\n this.#jwt.jti = jwtId;\n return this;\n }\n setNotBefore(input) {\n this.#jwt.nbf = input;\n return this;\n }\n setExpirationTime(input) {\n this.#jwt.exp = input;\n return this;\n }\n setIssuedAt(input) {\n this.#jwt.iat = input;\n return this;\n }\n setProtectedHeader(protectedHeader) {\n this.#protectedHeader = protectedHeader;\n return this;\n }\n async sign(key, options) {\n const sig = new CompactSign(this.#jwt.data());\n sig.setProtectedHeader(this.#protectedHeader);\n if (Array.isArray(this.#protectedHeader?.crit) &&\n this.#protectedHeader.crit.includes('b64') &&\n this.#protectedHeader.b64 === false) {\n throw new JWTInvalid('JWTs MUST NOT use unencoded payload');\n }\n return sig.sign(key, options);\n }\n}\n","import type { JWK } from 'jose';\n\n/** OAuth errors safe to serialize at an endpoint or redirect to a registered callback. */\nexport class OAuthServerError extends Error {\n constructor(\n readonly error: OAuthErrorCode,\n readonly description: string,\n readonly status = 400,\n ) {\n super(description);\n this.name = 'OAuthServerError';\n }\n}\n\n/** Errors defined by OAuth 2.0 endpoints supported by this server. */\nexport type OAuthErrorCode =\n | 'server_error'\n | 'access_denied'\n | 'invalid_client'\n | 'invalid_grant'\n | 'invalid_request'\n | 'invalid_request_uri'\n | 'invalid_scope'\n | 'invalid_token'\n | 'unsupported_grant_type'\n | 'unsupported_response_type';\n\n/** A client registered by an operator or dynamic-client-registration endpoint. */\nexport interface OAuthClient {\n readonly id: string;\n readonly redirectUris: readonly string[];\n readonly allowedScopes: readonly string[];\n readonly tokenEndpointAuthMethod: 'none' | 'client_secret_post';\n /** Unsalted base64url SHA-256 of the client secret (compared in constant time). Use only high-entropy generated secrets; never store the raw secret or a password-hashing (bcrypt/argon2) digest. */\n readonly secretHash?: string;\n readonly allowedResources?: readonly string[];\n readonly createdAt: Date;\n}\n\n/** A subject and current application context approved by the host's authenticated session. */\nexport interface OAuthConsentContext {\n readonly subject: string;\n /** Optional tenant selected and authorized by trusted application state. */\n readonly tenantId?: string;\n /** Additional JSON-safe access-token claims supplied by the application. */\n readonly claims?: Readonly<Record<string, string | number | boolean>>;\n readonly scopes?: readonly string[];\n}\n\n/** Request parsed from an OAuth authorization endpoint request. */\nexport interface OAuthAuthorizationRequest {\n readonly clientId: string;\n readonly redirectUri: string;\n readonly responseType: 'code';\n readonly scopes: readonly string[];\n readonly resource?: string;\n readonly state?: string;\n readonly codeChallenge: string;\n readonly codeChallengeMethod: 'S256';\n}\n\n/** A durable authorization-code grant; codeHash must be a SHA-256 hash, not a bearer secret. */\nexport interface OAuthAuthorizationCodeGrant {\n readonly id: string;\n readonly codeHash: string;\n readonly clientId: string;\n readonly subject: string;\n readonly tenantId?: string;\n readonly claims?: Readonly<Record<string, string | number | boolean>>;\n readonly redirectUri: string;\n readonly scopes: readonly string[];\n readonly resource?: string;\n readonly codeChallenge: string;\n readonly expiresAt: Date;\n}\n\n/** A durable rotating refresh-token grant; tokenHash must be a SHA-256 hash. */\nexport interface OAuthRefreshGrant {\n readonly id: string;\n readonly tokenHash: string;\n readonly familyId: string;\n readonly clientId: string;\n readonly subject: string;\n readonly tenantId?: string;\n readonly claims?: Readonly<Record<string, string | number | boolean>>;\n readonly scopes: readonly string[];\n readonly resource?: string;\n readonly expiresAt: Date;\n}\n\n/** Redirect response to return after an authenticated user has approved consent. */\nexport interface OAuthAuthorizationRedirect {\n readonly redirectUri: string;\n}\n\n/** Result of an atomic code consume operation. */\nexport type OAuthCodeConsumeResult =\n | { readonly status: 'consumed'; readonly grant: OAuthAuthorizationCodeGrant }\n | { readonly status: 'invalid' | 'expired' | 'replayed' };\n\n/** Result of an atomic refresh rotation operation. */\nexport type OAuthRefreshRotateResult =\n | { readonly status: 'rotated'; readonly grant: OAuthRefreshGrant }\n | { readonly status: 'invalid' | 'expired' | 'replayed' | 'revoked' };\n\n/** Durable persistence boundary. Implement consume/rotate as one database transaction or compare-and-swap. */\nexport interface OAuthAuthorizationStorage {\n getClient(clientId: string): Promise<OAuthClient | null>;\n registerClient(client: OAuthClient): Promise<void>;\n createAuthorizationCode(grant: OAuthAuthorizationCodeGrant): Promise<void>;\n /** Atomically validates the exact binding and marks the code permanently consumed. */\n consumeAuthorizationCode(input: {\n readonly id: string;\n readonly codeHash: string;\n readonly clientId: string;\n readonly redirectUri: string;\n readonly resource?: string;\n readonly now: Date;\n }): Promise<OAuthCodeConsumeResult>;\n createRefreshGrant(grant: OAuthRefreshGrant): Promise<void>;\n /** Atomically persist refreshed scopes and claims before exposing the replacement token. Undefined claims clear prior claims. Reject missing, consumed, revoked or mismatched grants and scope expansion. Required: every refresh-token exchange persists through it. */\n narrowRefreshGrant(input: {\n readonly id: string;\n readonly tokenHash: string;\n readonly scopes: readonly string[];\n readonly claims: OAuthRefreshGrant['claims'];\n }): Promise<void>;\n /** Atomically consumes a refresh token, creates replacement, and revokes its family on replay. */\n rotateRefreshGrant(input: {\n readonly id: string;\n readonly tokenHash: string;\n readonly clientId: string;\n readonly resource?: string;\n /** Storage derives the replacement's subject, scopes and family from the atomically consumed grant. */\n readonly replacement: Pick<\n OAuthRefreshGrant,\n 'id' | 'tokenHash' | 'expiresAt'\n >;\n readonly now: Date;\n }): Promise<OAuthRefreshRotateResult>;\n revokeRefreshGrant(input: {\n readonly id: string;\n readonly tokenHash: string;\n readonly now: Date;\n }): Promise<void>;\n revokeAccessToken(input: {\n readonly jti: string;\n readonly expiresAt: Date;\n }): Promise<void>;\n isAccessTokenRevoked(jti: string, now: Date): Promise<boolean>;\n}\n\n/** Application-owned authorization checks. The server never authenticates browser sessions itself. */\nexport interface OAuthIdentityProvider {\n /** Called before every token issue; return null when live authorization is inactive. */\n revalidateConsent?(\n context: OAuthConsentContext,\n grant: OAuthAuthorizationCodeGrant | OAuthRefreshGrant,\n ): Promise<OAuthConsentContext | null>;\n /** Fallback for revalidateConsent, invoked for both authorization-code exchange and refresh (the grant's familyId/tokenHash are unset for code grants); return null when the identity, tenant, or permissions are no longer active. */\n refreshConsent?(\n context: OAuthConsentContext,\n grant: OAuthRefreshGrant,\n ): Promise<OAuthConsentContext | null>;\n}\n\n/** Signing material controlled by the host. Publish only publicJwk through JWKS. */\nexport interface OAuthSigningKey {\n readonly privateKey: CryptoKey | Uint8Array;\n /** Public key paired with privateKey, used only for local verification helpers. */\n readonly publicKey: CryptoKey | Uint8Array;\n readonly publicJwk: JWK;\n readonly algorithm: 'RS256' | 'ES256';\n readonly keyId: string;\n}\n\n/** Configuration for a framework-independent OAuth authorization server. */\nexport interface OAuthAuthorizationServerOptions {\n readonly issuer: string;\n readonly signingKey: OAuthSigningKey;\n readonly storage: OAuthAuthorizationStorage;\n readonly identity: OAuthIdentityProvider;\n readonly scopes: readonly string[];\n readonly resources?: readonly string[];\n readonly authorizationCodeLifetimeSeconds?: number;\n readonly accessTokenLifetimeSeconds?: number;\n readonly refreshTokenLifetimeSeconds?: number;\n readonly issueRefreshTokens?: boolean;\n /** Enables RFC 7591 public-client registration. It is disabled by default. */\n readonly dynamicClientRegistration?: boolean;\n /** Explicit opt-in for HTTP loopback redirects used by native/development clients. HTTPS is the default. */\n readonly allowLoopbackRedirects?: boolean;\n}\n\n/** Tokens returned by successful token endpoint grants. */\nexport interface OAuthTokenResponse {\n readonly access_token: string;\n readonly token_type: 'Bearer';\n readonly expires_in: number;\n readonly scope: string;\n readonly refresh_token?: string;\n}\n\n/** RFC 7591 client registration response: identifiers plus the effective registered metadata. */\nexport interface OAuthRegistrationResponse {\n readonly client_id: string;\n readonly client_id_issued_at: number;\n readonly redirect_uris: readonly string[];\n readonly token_endpoint_auth_method: 'none';\n readonly grant_types: readonly string[];\n readonly response_types: readonly ['code'];\n readonly scope: string;\n readonly client_name?: string;\n}\n","import type {\n OAuthAuthorizationCodeGrant,\n OAuthAuthorizationStorage,\n OAuthClient,\n OAuthCodeConsumeResult,\n OAuthRefreshGrant,\n OAuthRefreshRotateResult,\n} from './types.js';\n\n/** Test-only reference store. Production callers must provide durable transactional persistence. */\nexport class InMemoryOAuthAuthorizationStorage\n implements OAuthAuthorizationStorage\n{\n readonly clients = new Map<string, OAuthClient>();\n readonly codes = new Map<string, OAuthAuthorizationCodeGrant>();\n readonly refreshes = new Map<string, OAuthRefreshGrant>();\n readonly usedCodes = new Set<string>();\n readonly usedRefreshes = new Set<string>();\n readonly revokedFamilies = new Set<string>();\n readonly revokedAccess = new Map<string, Date>();\n\n async getClient(clientId: string) {\n return this.clients.get(clientId) ?? null;\n }\n async registerClient(client: OAuthClient) {\n this.clients.set(client.id, client);\n }\n async createAuthorizationCode(grant: OAuthAuthorizationCodeGrant) {\n this.codes.set(grant.id, grant);\n }\n async consumeAuthorizationCode(\n input: Parameters<OAuthAuthorizationStorage['consumeAuthorizationCode']>[0],\n ): Promise<OAuthCodeConsumeResult> {\n const grant = this.codes.get(input.id);\n if (!grant || grant.codeHash !== input.codeHash)\n return { status: 'invalid' };\n if (this.usedCodes.has(grant.id)) return { status: 'replayed' };\n if (grant.expiresAt <= input.now) return { status: 'expired' };\n if (\n grant.clientId !== input.clientId ||\n grant.redirectUri !== input.redirectUri ||\n grant.resource !== input.resource\n )\n return { status: 'invalid' };\n this.usedCodes.add(grant.id);\n return { status: 'consumed', grant };\n }\n async createRefreshGrant(grant: OAuthRefreshGrant) {\n this.refreshes.set(grant.id, grant);\n }\n async narrowRefreshGrant(input: {\n readonly id: string;\n readonly tokenHash: string;\n readonly scopes: readonly string[];\n readonly claims: OAuthRefreshGrant['claims'];\n }) {\n const grant = this.refreshes.get(input.id);\n if (\n !grant ||\n this.usedRefreshes.has(grant.id) ||\n this.revokedFamilies.has(grant.familyId) ||\n grant.tokenHash !== input.tokenHash ||\n input.scopes.some((scope) => !grant.scopes.includes(scope))\n )\n throw new Error('Invalid refresh narrowing');\n this.refreshes.set(input.id, {\n ...grant,\n scopes: [...input.scopes],\n claims: input.claims,\n });\n }\n async rotateRefreshGrant(\n input: Parameters<OAuthAuthorizationStorage['rotateRefreshGrant']>[0],\n ): Promise<OAuthRefreshRotateResult> {\n const grant = this.refreshes.get(input.id);\n if (!grant || grant.tokenHash !== input.tokenHash)\n return { status: 'invalid' };\n if (this.revokedFamilies.has(grant.familyId)) return { status: 'revoked' };\n if (this.usedRefreshes.has(grant.id)) {\n this.revokedFamilies.add(grant.familyId);\n return { status: 'replayed' };\n }\n if (grant.expiresAt <= input.now) return { status: 'expired' };\n if (grant.clientId !== input.clientId || grant.resource !== input.resource)\n return { status: 'invalid' };\n this.usedRefreshes.add(grant.id);\n this.refreshes.set(input.replacement.id, {\n ...grant,\n ...input.replacement,\n });\n return { status: 'rotated', grant };\n }\n async revokeRefreshGrant(input: {\n readonly id: string;\n readonly tokenHash: string;\n readonly now: Date;\n }) {\n const grant = this.refreshes.get(input.id);\n if (grant?.tokenHash === input.tokenHash)\n this.revokedFamilies.add(grant.familyId);\n }\n async revokeAccessToken(input: {\n readonly jti: string;\n readonly expiresAt: Date;\n }) {\n this.revokedAccess.set(input.jti, input.expiresAt);\n }\n async isAccessTokenRevoked(jti: string, now: Date) {\n const expiry = this.revokedAccess.get(jti);\n return Boolean(expiry && expiry > now);\n }\n}\n","import {\n createHash,\n randomBytes,\n randomUUID,\n timingSafeEqual,\n} from 'node:crypto';\nimport {\n type JWTPayload,\n errors as joseErrors,\n jwtVerify,\n SignJWT,\n} from 'jose';\nimport {\n type OAuthAuthorizationCodeGrant,\n type OAuthAuthorizationRedirect,\n type OAuthAuthorizationRequest,\n type OAuthAuthorizationServerOptions,\n type OAuthClient,\n type OAuthConsentContext,\n type OAuthRefreshGrant,\n type OAuthRegistrationResponse,\n OAuthServerError,\n type OAuthTokenResponse,\n} from './types.js';\n\nexport { InMemoryOAuthAuthorizationStorage } from './memory.js';\nexport * from './types.js';\n\nconst maxRegistrationBodyBytes = 16 * 1024;\nconst maxRedirectUris = 10;\nconst maxMetadataStringLength = 2048;\nconst maxClientNameLength = 256;\n\nconst maxLifetime = 60 * 60 * 24 * 90;\nconst scopePattern = /^[\\x21\\x23-\\x5b\\x5d-\\x7e]+$/u;\n\nfunction opaque(): { id: string; secret: string; value: string; hash: string } {\n const id = randomUUID();\n const secret = randomBytes(32).toString('base64url');\n return { id, secret, value: `${id}.${secret}`, hash: hash(secret) };\n}\nfunction hash(value: string) {\n return createHash('sha256').update(value).digest('base64url');\n}\nfunction parseOpaque(value: string): { id: string; hash: string } | null {\n const [id, secret, extra] = value.split('.');\n if (\n !id ||\n !secret ||\n extra ||\n !/^[0-9a-f-]{36}$/iu.test(id) ||\n !/^[A-Za-z0-9_-]{32,}$/u.test(secret)\n )\n return null;\n return { id, hash: hash(secret) };\n}\nfunction same(a: string, b: string) {\n const left = Buffer.from(a);\n const right = Buffer.from(b);\n return left.length === right.length && timingSafeEqual(left, right);\n}\nfunction scopeList(value: string | null): string[] {\n if (!value) return [];\n const scopes = value.split(' ').filter(Boolean);\n if (!scopes.length || scopes.some((scope) => !scopePattern.test(scope)))\n throw new OAuthServerError('invalid_scope', 'Invalid scope.');\n return [...new Set(scopes)];\n}\nfunction endpoint(issuer: string, path: string) {\n return new URL(path, issuer.endsWith('/') ? issuer : `${issuer}/`).href;\n}\nfunction json(body: unknown, status = 200) {\n return new Response(JSON.stringify(body), {\n status,\n headers: {\n 'content-type': 'application/json',\n 'cache-control': 'no-store',\n pragma: 'no-cache',\n },\n });\n}\nfunction errorResponse(error: unknown) {\n const value =\n error instanceof OAuthServerError\n ? error\n : new OAuthServerError(\n 'server_error',\n 'The authorization server could not complete the request.',\n 500,\n );\n return json(\n { error: value.error, error_description: value.description },\n value.status,\n );\n}\n\n/** Framework-independent OAuth authorization server. Mount {@link handle} in any Fetch-compatible router. */\nexport class OAuthAuthorizationServer {\n private readonly issuer: string;\n private readonly issuerUrl: URL;\n private readonly options: Required<\n Pick<\n OAuthAuthorizationServerOptions,\n | 'authorizationCodeLifetimeSeconds'\n | 'accessTokenLifetimeSeconds'\n | 'refreshTokenLifetimeSeconds'\n | 'issueRefreshTokens'\n | 'dynamicClientRegistration'\n >\n > &\n OAuthAuthorizationServerOptions;\n\n constructor(options: OAuthAuthorizationServerOptions) {\n this.issuerUrl = this.assertIssuer(options.issuer);\n if (\n options.issueRefreshTokens !== false &&\n typeof options.storage.narrowRefreshGrant !== 'function'\n )\n throw new TypeError(\n 'OAuth storage must implement narrowRefreshGrant when refresh tokens are issued.',\n );\n this.issuer = this.issuerUrl.href.replace(/\\/$/u, '');\n for (const lifetime of [\n options.authorizationCodeLifetimeSeconds ?? 300,\n options.accessTokenLifetimeSeconds ?? 300,\n options.refreshTokenLifetimeSeconds ?? 60 * 60 * 24 * 30,\n ])\n if (\n !Number.isInteger(lifetime) ||\n lifetime < 30 ||\n lifetime > maxLifetime\n )\n throw new TypeError(\n 'OAuth lifetimes must be whole seconds between 30 and 90 days.',\n );\n this.options = {\n ...options,\n authorizationCodeLifetimeSeconds:\n options.authorizationCodeLifetimeSeconds ?? 300,\n accessTokenLifetimeSeconds: options.accessTokenLifetimeSeconds ?? 300,\n refreshTokenLifetimeSeconds:\n options.refreshTokenLifetimeSeconds ?? 60 * 60 * 24 * 30,\n issueRefreshTokens: options.issueRefreshTokens !== false,\n dynamicClientRegistration: options.dynamicClientRegistration === true,\n };\n }\n\n /** Parse and validate an authorization request without authenticating a browser session. */\n async parseAuthorizationRequest(\n input: URLSearchParams,\n ): Promise<OAuthAuthorizationRequest> {\n if (input.get('response_type') !== 'code')\n throw new OAuthServerError(\n 'unsupported_response_type',\n 'Only authorization code is supported.',\n );\n const clientId = required(input, 'client_id');\n const redirectUri = required(input, 'redirect_uri');\n const client = await this.options.storage.getClient(clientId);\n if (!client)\n throw new OAuthServerError('invalid_request', 'Unknown client.');\n this.assertRedirect(client, redirectUri);\n const codeChallenge = required(input, 'code_challenge');\n if (\n !/^[A-Za-z0-9_-]{43,128}$/u.test(codeChallenge) ||\n input.get('code_challenge_method') !== 'S256'\n )\n throw new OAuthServerError('invalid_request', 'S256 PKCE is required.');\n const scopes = scopeList(input.get('scope'));\n this.assertScopes(client, scopes);\n const resource = input.get('resource') ?? undefined;\n this.assertResource(client, resource);\n return {\n clientId,\n redirectUri,\n responseType: 'code',\n scopes,\n resource,\n state: input.get('state') ?? undefined,\n codeChallenge,\n codeChallengeMethod: 'S256',\n };\n }\n\n /** Records an application-approved authorization decision and returns its redirect URI. */\n async approve(\n request: OAuthAuthorizationRequest,\n consent: OAuthConsentContext,\n ): Promise<OAuthAuthorizationRedirect> {\n if (!consent.subject || consent.subject.length > 512)\n throw new OAuthServerError('access_denied', 'Authorization denied.');\n const client = await this.options.storage.getClient(request.clientId);\n if (!client)\n throw new OAuthServerError('invalid_request', 'Unknown client.');\n this.assertRedirect(client, request.redirectUri);\n this.assertScopes(client, request.scopes);\n this.assertResource(client, request.resource);\n const code = opaque();\n const now = new Date();\n const grant: OAuthAuthorizationCodeGrant = {\n id: code.id,\n codeHash: code.hash,\n clientId: request.clientId,\n subject: consent.subject,\n ...(consent.tenantId ? { tenantId: consent.tenantId } : {}),\n ...(consent.claims ? { claims: consent.claims } : {}),\n redirectUri: request.redirectUri,\n scopes: request.scopes,\n ...(request.resource ? { resource: request.resource } : {}),\n codeChallenge: request.codeChallenge,\n expiresAt: new Date(\n now.getTime() + this.options.authorizationCodeLifetimeSeconds * 1000,\n ),\n };\n await this.options.storage.createAuthorizationCode(\n this.applyConsent(grant, consent),\n );\n const redirect = new URL(request.redirectUri);\n redirect.searchParams.set('code', code.value);\n if (request.state) redirect.searchParams.set('state', request.state);\n redirect.searchParams.set('iss', this.issuer);\n return { redirectUri: redirect.href };\n }\n\n /** Exchanges an authorization code or a rotating refresh token for an access token. */\n async token(input: URLSearchParams): Promise<OAuthTokenResponse> {\n const grantType = required(input, 'grant_type');\n if (grantType === 'authorization_code') return this.exchangeCode(input);\n if (grantType === 'refresh_token') {\n if (!this.options.issueRefreshTokens)\n throw new OAuthServerError(\n 'unsupported_grant_type',\n 'Refresh tokens are not enabled.',\n );\n return this.refresh(input);\n }\n throw new OAuthServerError(\n 'unsupported_grant_type',\n 'Unsupported grant_type.',\n );\n }\n\n /** RFC 7009-style best-effort revocation; unknown token values deliberately succeed. */\n async revoke(input: URLSearchParams): Promise<void> {\n const token = required(input, 'token');\n const parsed = parseOpaque(token);\n if (parsed) {\n await this.options.storage.revokeRefreshGrant({\n id: parsed.id,\n tokenHash: parsed.hash,\n now: new Date(),\n });\n return;\n }\n try {\n await this.revokeAccessToken(token);\n } catch (error) {\n // Unknown token success must never conceal a failed durable read/write.\n if (error instanceof OAuthServerError && error.error === 'invalid_token')\n return;\n if (\n [\n joseErrors.JWTExpired,\n joseErrors.JWTClaimValidationFailed,\n joseErrors.JWTInvalid,\n joseErrors.JWSInvalid,\n joseErrors.JWSSignatureVerificationFailed,\n joseErrors.JOSEAlgNotAllowed,\n joseErrors.JOSENotSupported,\n ].some((ErrorType) => error instanceof ErrorType)\n )\n return;\n throw error;\n }\n }\n\n /** Immediately makes a valid, unexpired access JWT inactive through the injected revocation store. */\n async revokeAccessToken(token: string): Promise<void> {\n const payload = await this.verifyJwt(token);\n if (typeof payload.jti !== 'string' || typeof payload.exp !== 'number')\n throw new OAuthServerError('invalid_token', 'Invalid access token.', 401);\n await this.options.storage.revokeAccessToken({\n jti: payload.jti,\n expiresAt: new Date(payload.exp * 1000),\n });\n }\n\n /**\n * Verifies issuer, signature, expiry, the caller's own resource audience and\n * live server-side access-token revocation. Resource servers must always pass\n * the audience (resource URI) they serve so tokens minted for another\n * resource are rejected.\n */\n async verifyAccessToken(\n token: string,\n audience: string,\n ): Promise<JWTPayload> {\n if (!audience)\n throw new TypeError('verifyAccessToken requires the expected audience.');\n return this.verifyJwt(token, audience);\n }\n\n private async verifyJwt(\n token: string,\n audience?: string,\n ): Promise<JWTPayload> {\n const { payload } = await jwtVerify(\n token,\n this.options.signingKey.publicKey,\n {\n issuer: this.issuer,\n typ: 'at+jwt',\n requiredClaims: [\n 'exp',\n 'iat',\n 'sub',\n 'client_id',\n 'scope',\n 'aud',\n 'jti',\n ],\n ...(audience ? { audience } : {}),\n algorithms: [this.options.signingKey.algorithm],\n },\n );\n if (\n typeof payload.jti !== 'string' ||\n !payload.jti ||\n typeof payload.sub !== 'string' ||\n !payload.sub ||\n typeof payload.client_id !== 'string' ||\n !payload.client_id ||\n typeof payload.scope !== 'string' ||\n typeof payload.aud !== 'string' ||\n !payload.aud ||\n typeof payload.iat !== 'number' ||\n !Number.isInteger(payload.iat) ||\n typeof payload.exp !== 'number' ||\n !Number.isInteger(payload.exp) ||\n payload.exp <= payload.iat ||\n (payload.tenant_id !== undefined &&\n (typeof payload.tenant_id !== 'string' || !payload.tenant_id)) ||\n (await this.options.storage.isAccessTokenRevoked(payload.jti, new Date()))\n )\n throw new OAuthServerError('invalid_token', 'Invalid access token.', 401);\n return payload;\n }\n\n /** Returns RFC 8414 authorization-server metadata. */\n discovery() {\n return {\n issuer: this.issuer,\n authorization_endpoint: endpoint(this.issuer, 'authorize'),\n token_endpoint: endpoint(this.issuer, 'token'),\n jwks_uri: endpoint(this.issuer, 'jwks'),\n ...(this.options.dynamicClientRegistration\n ? { registration_endpoint: endpoint(this.issuer, 'register') }\n : {}),\n response_types_supported: ['code'],\n grant_types_supported: [\n 'authorization_code',\n ...(this.options.issueRefreshTokens ? ['refresh_token'] : []),\n ],\n token_endpoint_auth_methods_supported: ['none', 'client_secret_post'],\n code_challenge_methods_supported: ['S256'],\n authorization_response_iss_parameter_supported: true,\n scopes_supported: [...this.options.scopes],\n };\n }\n\n /** Returns the public signing JWK. */\n jwks() {\n return {\n keys: [\n {\n ...this.options.signingKey.publicJwk,\n kid: this.options.signingKey.keyId,\n alg: this.options.signingKey.algorithm,\n use: 'sig',\n },\n ],\n };\n }\n\n /** Safely registers a public authorization-code client when DCR is explicitly enabled. */\n async register(input: unknown): Promise<OAuthRegistrationResponse> {\n if (!this.options.dynamicClientRegistration)\n throw new OAuthServerError(\n 'invalid_request',\n 'Dynamic client registration is disabled.',\n 404,\n );\n if (!input || typeof input !== 'object' || Array.isArray(input))\n throw new OAuthServerError(\n 'invalid_request',\n 'Client metadata must be an object.',\n );\n const value = input as Record<string, unknown>;\n if (\n (value.client_name !== undefined &&\n (typeof value.client_name !== 'string' ||\n value.client_name.length > maxClientNameLength)) ||\n (typeof value.scope === 'string' &&\n value.scope.length > maxMetadataStringLength)\n )\n throw new OAuthServerError(\n 'invalid_request',\n 'Client metadata exceeds supported bounds.',\n );\n for (const [field, allowed] of [\n [\n 'grant_types',\n [\n 'authorization_code',\n ...(this.options.issueRefreshTokens ? ['refresh_token'] : []),\n ],\n ],\n ['response_types', ['code']],\n ] as const) {\n const values = value[field];\n if (\n values !== undefined &&\n (!Array.isArray(values) ||\n !values.length ||\n values.length > allowed.length ||\n values.some(\n (entry) =>\n typeof entry !== 'string' ||\n !(allowed as readonly string[]).includes(entry),\n ))\n )\n throw new OAuthServerError(\n 'invalid_request',\n 'Unsupported client metadata.',\n );\n }\n if (\n value.scope !== undefined &&\n (typeof value.scope !== 'string' ||\n scopeList(value.scope).some(\n (scope) => !this.options.scopes.includes(scope),\n ))\n )\n throw new OAuthServerError('invalid_scope', 'Unsupported client scope.');\n if (\n !Array.isArray(value.redirect_uris) ||\n !value.redirect_uris.length ||\n value.redirect_uris.length > maxRedirectUris ||\n value.redirect_uris.some(\n (uri) =>\n typeof uri !== 'string' || uri.length > maxMetadataStringLength,\n )\n )\n throw new OAuthServerError(\n 'invalid_request',\n 'redirect_uris is required.',\n );\n if (\n value.token_endpoint_auth_method !== undefined &&\n value.token_endpoint_auth_method !== 'none'\n )\n throw new OAuthServerError(\n 'invalid_request',\n 'Only public clients are supported.',\n );\n const client: OAuthClient = {\n id: randomUUID(),\n redirectUris: value.redirect_uris.map((uri) =>\n this.assertPublicRedirect(uri),\n ),\n allowedScopes:\n typeof value.scope === 'string'\n ? scopeList(value.scope)\n : this.options.scopes,\n tokenEndpointAuthMethod: 'none',\n createdAt: new Date(),\n };\n await this.options.storage.registerClient(client);\n // RFC 7591 section 3.2.1: echo the effective registered metadata. Grant\n // types are not per-client; every registered client may use every grant\n // the server supports, regardless of the grant_types it requested.\n const grantTypes = [\n 'authorization_code',\n ...(this.options.issueRefreshTokens ? ['refresh_token'] : []),\n ];\n return {\n client_id: client.id,\n client_id_issued_at: Math.floor(client.createdAt.getTime() / 1000),\n redirect_uris: [...client.redirectUris],\n token_endpoint_auth_method: 'none',\n grant_types: grantTypes,\n response_types: ['code'],\n scope: client.allowedScopes.join(' '),\n ...(typeof value.client_name === 'string'\n ? { client_name: value.client_name }\n : {}),\n };\n }\n\n /** Fetch-native routing for discovery, JWKS, registration, token and revocation endpoints. Authorization approval stays application-owned. */\n async handle(request: Request): Promise<Response> {\n try {\n const url = new URL(request.url);\n const path = url.pathname;\n const prefix = this.issuerUrl.pathname.replace(/\\/$/u, '');\n const route = path.startsWith(`${prefix}/`)\n ? path.slice(prefix.length)\n : path;\n if (\n request.method === 'GET' &&\n (path === `/.well-known/oauth-authorization-server${prefix}` ||\n route === '/.well-known/oauth-authorization-server')\n )\n return json(this.discovery());\n if (\n request.method === 'GET' &&\n (path === `/.well-known/openid-configuration${prefix}` ||\n route === '/.well-known/openid-configuration')\n )\n return json(this.discovery());\n if (request.method === 'GET' && route === '/jwks')\n return json(this.jwks());\n if (request.method === 'POST' && route === '/token')\n return json(await this.token(await form(request)));\n if (request.method === 'POST' && route === '/revoke') {\n await this.revoke(await form(request));\n return new Response(null, {\n status: 200,\n headers: { 'cache-control': 'no-store' },\n });\n }\n if (request.method === 'POST' && route === '/register')\n return json(await this.register(await registrationBody(request)), 201);\n return new Response(null, { status: 404 });\n } catch (error) {\n return errorResponse(error);\n }\n }\n\n private async exchangeCode(\n input: URLSearchParams,\n ): Promise<OAuthTokenResponse> {\n const client = await this.client(input);\n const raw = parseOpaque(required(input, 'code'));\n if (!raw)\n throw new OAuthServerError(\n 'invalid_grant',\n 'Invalid authorization code.',\n );\n const redirectUri = required(input, 'redirect_uri');\n const verifier = required(input, 'code_verifier');\n if (!/^[A-Za-z0-9._~-]{43,128}$/u.test(verifier))\n throw new OAuthServerError('invalid_grant', 'Invalid PKCE verifier.');\n const resource = input.get('resource') ?? undefined;\n const result = await this.options.storage.consumeAuthorizationCode({\n id: raw.id,\n codeHash: raw.hash,\n clientId: client.id,\n redirectUri,\n ...(resource ? { resource } : {}),\n now: new Date(),\n });\n if (result.status !== 'consumed')\n throw new OAuthServerError(\n 'invalid_grant',\n 'Invalid authorization code.',\n );\n if (!same(hash(verifier), result.grant.codeChallenge))\n throw new OAuthServerError(\n 'invalid_grant',\n 'Invalid authorization code.',\n );\n const consent = await this.revalidate(result.grant);\n return this.issue(this.applyConsent(result.grant, consent), true);\n }\n private async refresh(input: URLSearchParams): Promise<OAuthTokenResponse> {\n const client = await this.client(input);\n const raw = parseOpaque(required(input, 'refresh_token'));\n if (!raw)\n throw new OAuthServerError('invalid_grant', 'Invalid refresh token.');\n const resource = input.get('resource') ?? undefined;\n const candidate = opaque();\n const now = new Date();\n const replacement = {\n id: candidate.id,\n tokenHash: candidate.hash,\n expiresAt: new Date(\n now.getTime() + this.options.refreshTokenLifetimeSeconds * 1000,\n ),\n };\n const result = await this.options.storage.rotateRefreshGrant({\n id: raw.id,\n tokenHash: raw.hash,\n clientId: client.id,\n ...(resource ? { resource } : {}),\n replacement,\n now,\n });\n if (result.status !== 'rotated')\n throw new OAuthServerError('invalid_grant', 'Invalid refresh token.');\n try {\n const requestedScope = input.get('scope');\n const requestedScopes =\n requestedScope === null\n ? result.grant.scopes\n : [...new Set(requestedScope.split(' ').filter(Boolean))];\n if (requestedScopes.some((scope) => !result.grant.scopes.includes(scope)))\n throw new OAuthServerError(\n 'invalid_scope',\n 'Refresh scope expansion is not allowed.',\n );\n const consent = await this.revalidate(result.grant);\n const authorized = this.applyConsent(result.grant, consent);\n const grant = {\n ...authorized,\n scopes: authorized.scopes.filter((scope) =>\n requestedScopes.includes(scope),\n ),\n };\n await this.options.storage.narrowRefreshGrant({\n id: candidate.id,\n tokenHash: candidate.hash,\n scopes: grant.scopes,\n claims: grant.claims,\n });\n return await this.issue(grant, false, candidate.value);\n } catch (error) {\n await this.options.storage.revokeRefreshGrant({\n id: raw.id,\n tokenHash: raw.hash,\n now,\n });\n throw error;\n }\n }\n\n private async issue(\n grant: Pick<\n OAuthAuthorizationCodeGrant,\n 'clientId' | 'subject' | 'tenantId' | 'claims' | 'scopes' | 'resource'\n >,\n refresh = false,\n existingRefresh?: string,\n ): Promise<OAuthTokenResponse> {\n const now = Math.floor(Date.now() / 1000);\n const jti = randomUUID();\n const claims = grant.claims ?? {};\n for (const reserved of [\n 'scope',\n 'client_id',\n 'tenant_id',\n 'aud',\n 'iss',\n 'sub',\n 'jti',\n 'exp',\n 'iat',\n 'nbf',\n ])\n if (reserved in claims)\n throw new OAuthServerError('invalid_request', 'Reserved token claim.');\n const token = await new SignJWT({\n scope: grant.scopes.join(' '),\n client_id: grant.clientId,\n ...(grant.tenantId ? { tenant_id: grant.tenantId } : {}),\n ...claims,\n })\n .setProtectedHeader({\n alg: this.options.signingKey.algorithm,\n kid: this.options.signingKey.keyId,\n typ: 'at+jwt',\n })\n .setIssuer(this.issuer)\n .setSubject(grant.subject)\n .setJti(jti)\n .setIssuedAt(now)\n .setExpirationTime(now + this.options.accessTokenLifetimeSeconds)\n .setAudience(grant.resource ?? this.issuer)\n .sign(this.options.signingKey.privateKey);\n let refreshToken: string | undefined;\n if (this.options.issueRefreshTokens) {\n if (existingRefresh) refreshToken = existingRefresh;\n else {\n const raw = opaque();\n await this.options.storage.createRefreshGrant({\n id: raw.id,\n tokenHash: raw.hash,\n familyId: randomUUID(),\n clientId: grant.clientId,\n subject: grant.subject,\n ...(grant.tenantId ? { tenantId: grant.tenantId } : {}),\n ...(grant.claims ? { claims: grant.claims } : {}),\n scopes: grant.scopes,\n ...(grant.resource ? { resource: grant.resource } : {}),\n expiresAt: new Date(\n Date.now() + this.options.refreshTokenLifetimeSeconds * 1000,\n ),\n });\n refreshToken = raw.value;\n }\n }\n return {\n access_token: token,\n token_type: 'Bearer',\n expires_in: this.options.accessTokenLifetimeSeconds,\n scope: grant.scopes.join(' '),\n ...(refreshToken ? { refresh_token: refreshToken } : {}),\n };\n }\n private async client(input: URLSearchParams) {\n const id = required(input, 'client_id');\n const client = await this.options.storage.getClient(id);\n if (!client)\n throw new OAuthServerError('invalid_client', 'Invalid client.', 401);\n if (client.tokenEndpointAuthMethod === 'client_secret_post') {\n const secret = required(input, 'client_secret');\n if (!client.secretHash || !same(hash(secret), client.secretHash))\n throw new OAuthServerError('invalid_client', 'Invalid client.', 401);\n }\n return client;\n }\n private assertRedirect(client: OAuthClient, redirectUri: string) {\n if (!client.redirectUris.includes(redirectUri))\n throw new OAuthServerError('invalid_request', 'Invalid redirect_uri.');\n }\n private assertScopes(client: OAuthClient, scopes: readonly string[]) {\n if (\n scopes.some(\n (scope) =>\n !this.options.scopes.includes(scope) ||\n !client.allowedScopes.includes(scope),\n )\n )\n throw new OAuthServerError(\n 'invalid_scope',\n 'Requested scope is not allowed.',\n );\n }\n private assertResource(client: OAuthClient, resource?: string) {\n if (!resource) return;\n if (\n !this.options.resources?.includes(resource) ||\n (client.allowedResources && !client.allowedResources.includes(resource))\n )\n throw new OAuthServerError(\n 'invalid_request',\n 'Requested resource is not allowed.',\n );\n }\n private assertIssuer(issuer: string) {\n let url: URL;\n try {\n url = new URL(issuer);\n } catch {\n throw new TypeError('issuer must be an absolute URL.');\n }\n if (\n url.protocol !== 'https:' ||\n url.search ||\n url.hash ||\n url.username ||\n url.password\n )\n throw new TypeError(\n 'issuer must be an HTTPS origin or path without query, fragment, or credentials.',\n );\n return url;\n }\n private async revalidate(\n grant: OAuthAuthorizationCodeGrant | OAuthRefreshGrant,\n ): Promise<OAuthConsentContext> {\n const context = {\n subject: grant.subject,\n ...(grant.tenantId ? { tenantId: grant.tenantId } : {}),\n ...(grant.claims ? { claims: grant.claims } : {}),\n };\n const result = this.options.identity.revalidateConsent\n ? await this.options.identity.revalidateConsent(context, grant)\n : await this.options.identity.refreshConsent?.(\n context,\n grant as OAuthRefreshGrant,\n );\n if (!result)\n throw new OAuthServerError(\n 'invalid_grant',\n 'Authorization is no longer active.',\n );\n return result;\n }\n private applyConsent<\n T extends OAuthAuthorizationCodeGrant | OAuthRefreshGrant,\n >(grant: T, consent: OAuthConsentContext): T {\n if (\n !consent.subject ||\n consent.subject !== grant.subject ||\n consent.tenantId !== grant.tenantId\n )\n throw new OAuthServerError(\n 'invalid_grant',\n 'Live authorization changed identity or tenant.',\n );\n const scopes = [...new Set(consent.scopes ?? grant.scopes)];\n if (scopes.some((scope) => !grant.scopes.includes(scope)))\n throw new OAuthServerError(\n 'invalid_scope',\n 'Live authorization expanded scope.',\n );\n return {\n ...grant,\n subject: consent.subject,\n ...(consent.tenantId ? { tenantId: consent.tenantId } : {}),\n claims: consent.claims,\n scopes,\n };\n }\n private assertPublicRedirect(uri: string) {\n let url: URL;\n try {\n url = new URL(uri);\n } catch {\n throw new OAuthServerError('invalid_request', 'Invalid redirect URI.');\n }\n if (\n !['https:', 'http:'].includes(url.protocol) ||\n url.username ||\n url.password ||\n url.hash ||\n url.search ||\n (url.protocol === 'http:' &&\n (!this.options.allowLoopbackRedirects ||\n !['localhost', '127.0.0.1', '[::1]'].includes(url.hostname)))\n )\n throw new OAuthServerError('invalid_request', 'Invalid redirect URI.');\n return url.href;\n }\n}\n\n/** Creates a framework-independent OAuth server; callers must provide durable storage in production. */\nexport function createAuthorizationServer(\n options: OAuthAuthorizationServerOptions,\n) {\n return new OAuthAuthorizationServer(options);\n}\nfunction required(params: URLSearchParams, name: string) {\n const value = params.get(name);\n if (!value)\n throw new OAuthServerError('invalid_request', `${name} is required.`);\n return value;\n}\nasync function form(request: Request) {\n const contentType = request.headers.get('content-type') ?? '';\n if (!contentType.startsWith('application/x-www-form-urlencoded'))\n throw new OAuthServerError(\n 'invalid_request',\n 'Form-encoded request required.',\n );\n return new URLSearchParams(\n new TextDecoder().decode(await boundedBody(request)),\n );\n}\n\n/** Bound bytes while streaming before endpoint parsing or persistence. */\nasync function boundedBody(request: Request): Promise<Uint8Array> {\n const tooLarge = () =>\n new OAuthServerError(\n 'invalid_request',\n 'Request body exceeds 16384 bytes.',\n 413,\n );\n const declaredLength = request.headers.get('content-length');\n if (\n declaredLength !== null &&\n Number(declaredLength) > maxRegistrationBodyBytes\n ) {\n await request.body?.cancel().catch(() => {});\n throw tooLarge();\n }\n const reader = request.body?.getReader();\n if (!reader) return new Uint8Array();\n const chunks: Uint8Array[] = [];\n let length = 0;\n try {\n while (true) {\n const next = await reader.read();\n if (next.done) break;\n length += next.value.byteLength;\n if (length > maxRegistrationBodyBytes) {\n await reader.cancel().catch(() => {});\n throw tooLarge();\n }\n chunks.push(next.value);\n }\n } finally {\n reader.releaseLock();\n }\n const bytes = new Uint8Array(length);\n let offset = 0;\n for (const chunk of chunks) {\n bytes.set(chunk, offset);\n offset += chunk.byteLength;\n }\n return bytes;\n}\n\nasync function registrationBody(request: Request): Promise<unknown> {\n const bytes = await boundedBody(request);\n try {\n return JSON.parse(new TextDecoder('utf-8', { fatal: true }).decode(bytes));\n } catch {\n throw new OAuthServerError(\n 'invalid_request',\n 'Client metadata must be valid JSON.',\n );\n }\n}\n"],"x_google_ignoreList":[0,1,2],"mappings":"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"}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
import type { OAuthAuthorizationCodeGrant, OAuthAuthorizationStorage, OAuthClient, OAuthCodeConsumeResult, OAuthRefreshGrant, OAuthRefreshRotateResult } from './types.js';
|
|
2
|
+
/** Test-only reference store. Production callers must provide durable transactional persistence. */
|
|
3
|
+
export declare class InMemoryOAuthAuthorizationStorage implements OAuthAuthorizationStorage {
|
|
4
|
+
readonly clients: Map<string, OAuthClient>;
|
|
5
|
+
readonly codes: Map<string, OAuthAuthorizationCodeGrant>;
|
|
6
|
+
readonly refreshes: Map<string, OAuthRefreshGrant>;
|
|
7
|
+
readonly usedCodes: Set<string>;
|
|
8
|
+
readonly usedRefreshes: Set<string>;
|
|
9
|
+
readonly revokedFamilies: Set<string>;
|
|
10
|
+
readonly revokedAccess: Map<string, Date>;
|
|
11
|
+
getClient(clientId: string): Promise<OAuthClient | null>;
|
|
12
|
+
registerClient(client: OAuthClient): Promise<void>;
|
|
13
|
+
createAuthorizationCode(grant: OAuthAuthorizationCodeGrant): Promise<void>;
|
|
14
|
+
consumeAuthorizationCode(input: Parameters<OAuthAuthorizationStorage['consumeAuthorizationCode']>[0]): Promise<OAuthCodeConsumeResult>;
|
|
15
|
+
createRefreshGrant(grant: OAuthRefreshGrant): Promise<void>;
|
|
16
|
+
narrowRefreshGrant(input: {
|
|
17
|
+
readonly id: string;
|
|
18
|
+
readonly tokenHash: string;
|
|
19
|
+
readonly scopes: readonly string[];
|
|
20
|
+
readonly claims: OAuthRefreshGrant['claims'];
|
|
21
|
+
}): Promise<void>;
|
|
22
|
+
rotateRefreshGrant(input: Parameters<OAuthAuthorizationStorage['rotateRefreshGrant']>[0]): Promise<OAuthRefreshRotateResult>;
|
|
23
|
+
revokeRefreshGrant(input: {
|
|
24
|
+
readonly id: string;
|
|
25
|
+
readonly tokenHash: string;
|
|
26
|
+
readonly now: Date;
|
|
27
|
+
}): Promise<void>;
|
|
28
|
+
revokeAccessToken(input: {
|
|
29
|
+
readonly jti: string;
|
|
30
|
+
readonly expiresAt: Date;
|
|
31
|
+
}): Promise<void>;
|
|
32
|
+
isAccessTokenRevoked(jti: string, now: Date): Promise<boolean>;
|
|
33
|
+
}
|
|
34
|
+
//# sourceMappingURL=memory.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"memory.d.ts","sourceRoot":"","sources":["../../src/server/memory.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,2BAA2B,EAC3B,yBAAyB,EACzB,WAAW,EACX,sBAAsB,EACtB,iBAAiB,EACjB,wBAAwB,EACzB,MAAM,YAAY,CAAC;AAEpB,oGAAoG;AACpG,qBAAa,iCACX,YAAW,yBAAyB;IAEpC,QAAQ,CAAC,OAAO,2BAAkC;IAClD,QAAQ,CAAC,KAAK,2CAAkD;IAChE,QAAQ,CAAC,SAAS,iCAAwC;IAC1D,QAAQ,CAAC,SAAS,cAAqB;IACvC,QAAQ,CAAC,aAAa,cAAqB;IAC3C,QAAQ,CAAC,eAAe,cAAqB;IAC7C,QAAQ,CAAC,aAAa,oBAA2B;IAE3C,SAAS,CAAC,QAAQ,EAAE,MAAM;IAG1B,cAAc,CAAC,MAAM,EAAE,WAAW;IAGlC,uBAAuB,CAAC,KAAK,EAAE,2BAA2B;IAG1D,wBAAwB,CAC5B,KAAK,EAAE,UAAU,CAAC,yBAAyB,CAAC,0BAA0B,CAAC,CAAC,CAAC,CAAC,CAAC,GAC1E,OAAO,CAAC,sBAAsB,CAAC;IAe5B,kBAAkB,CAAC,KAAK,EAAE,iBAAiB;IAG3C,kBAAkB,CAAC,KAAK,EAAE;QAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,MAAM,EAAE,SAAS,MAAM,EAAE,CAAC;QACnC,QAAQ,CAAC,MAAM,EAAE,iBAAiB,CAAC,QAAQ,CAAC,CAAC;KAC9C;IAgBK,kBAAkB,CACtB,KAAK,EAAE,UAAU,CAAC,yBAAyB,CAAC,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,GACpE,OAAO,CAAC,wBAAwB,CAAC;IAmB9B,kBAAkB,CAAC,KAAK,EAAE;QAC9B,QAAQ,CAAC,EAAE,EAAE,MAAM,CAAC;QACpB,QAAQ,CAAC,SAAS,EAAE,MAAM,CAAC;QAC3B,QAAQ,CAAC,GAAG,EAAE,IAAI,CAAC;KACpB;IAKK,iBAAiB,CAAC,KAAK,EAAE;QAC7B,QAAQ,CAAC,GAAG,EAAE,MAAM,CAAC;QACrB,QAAQ,CAAC,SAAS,EAAE,IAAI,CAAC;KAC1B;IAGK,oBAAoB,CAAC,GAAG,EAAE,MAAM,EAAE,GAAG,EAAE,IAAI;CAIlD"}
|
|
@@ -0,0 +1,182 @@
|
|
|
1
|
+
import type { JWK } from 'jose';
|
|
2
|
+
/** OAuth errors safe to serialize at an endpoint or redirect to a registered callback. */
|
|
3
|
+
export declare class OAuthServerError extends Error {
|
|
4
|
+
readonly error: OAuthErrorCode;
|
|
5
|
+
readonly description: string;
|
|
6
|
+
readonly status: number;
|
|
7
|
+
constructor(error: OAuthErrorCode, description: string, status?: number);
|
|
8
|
+
}
|
|
9
|
+
/** Errors defined by OAuth 2.0 endpoints supported by this server. */
|
|
10
|
+
export type OAuthErrorCode = 'server_error' | 'access_denied' | 'invalid_client' | 'invalid_grant' | 'invalid_request' | 'invalid_request_uri' | 'invalid_scope' | 'invalid_token' | 'unsupported_grant_type' | 'unsupported_response_type';
|
|
11
|
+
/** A client registered by an operator or dynamic-client-registration endpoint. */
|
|
12
|
+
export interface OAuthClient {
|
|
13
|
+
readonly id: string;
|
|
14
|
+
readonly redirectUris: readonly string[];
|
|
15
|
+
readonly allowedScopes: readonly string[];
|
|
16
|
+
readonly tokenEndpointAuthMethod: 'none' | 'client_secret_post';
|
|
17
|
+
/** Unsalted base64url SHA-256 of the client secret (compared in constant time). Use only high-entropy generated secrets; never store the raw secret or a password-hashing (bcrypt/argon2) digest. */
|
|
18
|
+
readonly secretHash?: string;
|
|
19
|
+
readonly allowedResources?: readonly string[];
|
|
20
|
+
readonly createdAt: Date;
|
|
21
|
+
}
|
|
22
|
+
/** A subject and current application context approved by the host's authenticated session. */
|
|
23
|
+
export interface OAuthConsentContext {
|
|
24
|
+
readonly subject: string;
|
|
25
|
+
/** Optional tenant selected and authorized by trusted application state. */
|
|
26
|
+
readonly tenantId?: string;
|
|
27
|
+
/** Additional JSON-safe access-token claims supplied by the application. */
|
|
28
|
+
readonly claims?: Readonly<Record<string, string | number | boolean>>;
|
|
29
|
+
readonly scopes?: readonly string[];
|
|
30
|
+
}
|
|
31
|
+
/** Request parsed from an OAuth authorization endpoint request. */
|
|
32
|
+
export interface OAuthAuthorizationRequest {
|
|
33
|
+
readonly clientId: string;
|
|
34
|
+
readonly redirectUri: string;
|
|
35
|
+
readonly responseType: 'code';
|
|
36
|
+
readonly scopes: readonly string[];
|
|
37
|
+
readonly resource?: string;
|
|
38
|
+
readonly state?: string;
|
|
39
|
+
readonly codeChallenge: string;
|
|
40
|
+
readonly codeChallengeMethod: 'S256';
|
|
41
|
+
}
|
|
42
|
+
/** A durable authorization-code grant; codeHash must be a SHA-256 hash, not a bearer secret. */
|
|
43
|
+
export interface OAuthAuthorizationCodeGrant {
|
|
44
|
+
readonly id: string;
|
|
45
|
+
readonly codeHash: string;
|
|
46
|
+
readonly clientId: string;
|
|
47
|
+
readonly subject: string;
|
|
48
|
+
readonly tenantId?: string;
|
|
49
|
+
readonly claims?: Readonly<Record<string, string | number | boolean>>;
|
|
50
|
+
readonly redirectUri: string;
|
|
51
|
+
readonly scopes: readonly string[];
|
|
52
|
+
readonly resource?: string;
|
|
53
|
+
readonly codeChallenge: string;
|
|
54
|
+
readonly expiresAt: Date;
|
|
55
|
+
}
|
|
56
|
+
/** A durable rotating refresh-token grant; tokenHash must be a SHA-256 hash. */
|
|
57
|
+
export interface OAuthRefreshGrant {
|
|
58
|
+
readonly id: string;
|
|
59
|
+
readonly tokenHash: string;
|
|
60
|
+
readonly familyId: string;
|
|
61
|
+
readonly clientId: string;
|
|
62
|
+
readonly subject: string;
|
|
63
|
+
readonly tenantId?: string;
|
|
64
|
+
readonly claims?: Readonly<Record<string, string | number | boolean>>;
|
|
65
|
+
readonly scopes: readonly string[];
|
|
66
|
+
readonly resource?: string;
|
|
67
|
+
readonly expiresAt: Date;
|
|
68
|
+
}
|
|
69
|
+
/** Redirect response to return after an authenticated user has approved consent. */
|
|
70
|
+
export interface OAuthAuthorizationRedirect {
|
|
71
|
+
readonly redirectUri: string;
|
|
72
|
+
}
|
|
73
|
+
/** Result of an atomic code consume operation. */
|
|
74
|
+
export type OAuthCodeConsumeResult = {
|
|
75
|
+
readonly status: 'consumed';
|
|
76
|
+
readonly grant: OAuthAuthorizationCodeGrant;
|
|
77
|
+
} | {
|
|
78
|
+
readonly status: 'invalid' | 'expired' | 'replayed';
|
|
79
|
+
};
|
|
80
|
+
/** Result of an atomic refresh rotation operation. */
|
|
81
|
+
export type OAuthRefreshRotateResult = {
|
|
82
|
+
readonly status: 'rotated';
|
|
83
|
+
readonly grant: OAuthRefreshGrant;
|
|
84
|
+
} | {
|
|
85
|
+
readonly status: 'invalid' | 'expired' | 'replayed' | 'revoked';
|
|
86
|
+
};
|
|
87
|
+
/** Durable persistence boundary. Implement consume/rotate as one database transaction or compare-and-swap. */
|
|
88
|
+
export interface OAuthAuthorizationStorage {
|
|
89
|
+
getClient(clientId: string): Promise<OAuthClient | null>;
|
|
90
|
+
registerClient(client: OAuthClient): Promise<void>;
|
|
91
|
+
createAuthorizationCode(grant: OAuthAuthorizationCodeGrant): Promise<void>;
|
|
92
|
+
/** Atomically validates the exact binding and marks the code permanently consumed. */
|
|
93
|
+
consumeAuthorizationCode(input: {
|
|
94
|
+
readonly id: string;
|
|
95
|
+
readonly codeHash: string;
|
|
96
|
+
readonly clientId: string;
|
|
97
|
+
readonly redirectUri: string;
|
|
98
|
+
readonly resource?: string;
|
|
99
|
+
readonly now: Date;
|
|
100
|
+
}): Promise<OAuthCodeConsumeResult>;
|
|
101
|
+
createRefreshGrant(grant: OAuthRefreshGrant): Promise<void>;
|
|
102
|
+
/** Atomically persist refreshed scopes and claims before exposing the replacement token. Undefined claims clear prior claims. Reject missing, consumed, revoked or mismatched grants and scope expansion. Required: every refresh-token exchange persists through it. */
|
|
103
|
+
narrowRefreshGrant(input: {
|
|
104
|
+
readonly id: string;
|
|
105
|
+
readonly tokenHash: string;
|
|
106
|
+
readonly scopes: readonly string[];
|
|
107
|
+
readonly claims: OAuthRefreshGrant['claims'];
|
|
108
|
+
}): Promise<void>;
|
|
109
|
+
/** Atomically consumes a refresh token, creates replacement, and revokes its family on replay. */
|
|
110
|
+
rotateRefreshGrant(input: {
|
|
111
|
+
readonly id: string;
|
|
112
|
+
readonly tokenHash: string;
|
|
113
|
+
readonly clientId: string;
|
|
114
|
+
readonly resource?: string;
|
|
115
|
+
/** Storage derives the replacement's subject, scopes and family from the atomically consumed grant. */
|
|
116
|
+
readonly replacement: Pick<OAuthRefreshGrant, 'id' | 'tokenHash' | 'expiresAt'>;
|
|
117
|
+
readonly now: Date;
|
|
118
|
+
}): Promise<OAuthRefreshRotateResult>;
|
|
119
|
+
revokeRefreshGrant(input: {
|
|
120
|
+
readonly id: string;
|
|
121
|
+
readonly tokenHash: string;
|
|
122
|
+
readonly now: Date;
|
|
123
|
+
}): Promise<void>;
|
|
124
|
+
revokeAccessToken(input: {
|
|
125
|
+
readonly jti: string;
|
|
126
|
+
readonly expiresAt: Date;
|
|
127
|
+
}): Promise<void>;
|
|
128
|
+
isAccessTokenRevoked(jti: string, now: Date): Promise<boolean>;
|
|
129
|
+
}
|
|
130
|
+
/** Application-owned authorization checks. The server never authenticates browser sessions itself. */
|
|
131
|
+
export interface OAuthIdentityProvider {
|
|
132
|
+
/** Called before every token issue; return null when live authorization is inactive. */
|
|
133
|
+
revalidateConsent?(context: OAuthConsentContext, grant: OAuthAuthorizationCodeGrant | OAuthRefreshGrant): Promise<OAuthConsentContext | null>;
|
|
134
|
+
/** Fallback for revalidateConsent, invoked for both authorization-code exchange and refresh (the grant's familyId/tokenHash are unset for code grants); return null when the identity, tenant, or permissions are no longer active. */
|
|
135
|
+
refreshConsent?(context: OAuthConsentContext, grant: OAuthRefreshGrant): Promise<OAuthConsentContext | null>;
|
|
136
|
+
}
|
|
137
|
+
/** Signing material controlled by the host. Publish only publicJwk through JWKS. */
|
|
138
|
+
export interface OAuthSigningKey {
|
|
139
|
+
readonly privateKey: CryptoKey | Uint8Array;
|
|
140
|
+
/** Public key paired with privateKey, used only for local verification helpers. */
|
|
141
|
+
readonly publicKey: CryptoKey | Uint8Array;
|
|
142
|
+
readonly publicJwk: JWK;
|
|
143
|
+
readonly algorithm: 'RS256' | 'ES256';
|
|
144
|
+
readonly keyId: string;
|
|
145
|
+
}
|
|
146
|
+
/** Configuration for a framework-independent OAuth authorization server. */
|
|
147
|
+
export interface OAuthAuthorizationServerOptions {
|
|
148
|
+
readonly issuer: string;
|
|
149
|
+
readonly signingKey: OAuthSigningKey;
|
|
150
|
+
readonly storage: OAuthAuthorizationStorage;
|
|
151
|
+
readonly identity: OAuthIdentityProvider;
|
|
152
|
+
readonly scopes: readonly string[];
|
|
153
|
+
readonly resources?: readonly string[];
|
|
154
|
+
readonly authorizationCodeLifetimeSeconds?: number;
|
|
155
|
+
readonly accessTokenLifetimeSeconds?: number;
|
|
156
|
+
readonly refreshTokenLifetimeSeconds?: number;
|
|
157
|
+
readonly issueRefreshTokens?: boolean;
|
|
158
|
+
/** Enables RFC 7591 public-client registration. It is disabled by default. */
|
|
159
|
+
readonly dynamicClientRegistration?: boolean;
|
|
160
|
+
/** Explicit opt-in for HTTP loopback redirects used by native/development clients. HTTPS is the default. */
|
|
161
|
+
readonly allowLoopbackRedirects?: boolean;
|
|
162
|
+
}
|
|
163
|
+
/** Tokens returned by successful token endpoint grants. */
|
|
164
|
+
export interface OAuthTokenResponse {
|
|
165
|
+
readonly access_token: string;
|
|
166
|
+
readonly token_type: 'Bearer';
|
|
167
|
+
readonly expires_in: number;
|
|
168
|
+
readonly scope: string;
|
|
169
|
+
readonly refresh_token?: string;
|
|
170
|
+
}
|
|
171
|
+
/** RFC 7591 client registration response: identifiers plus the effective registered metadata. */
|
|
172
|
+
export interface OAuthRegistrationResponse {
|
|
173
|
+
readonly client_id: string;
|
|
174
|
+
readonly client_id_issued_at: number;
|
|
175
|
+
readonly redirect_uris: readonly string[];
|
|
176
|
+
readonly token_endpoint_auth_method: 'none';
|
|
177
|
+
readonly grant_types: readonly string[];
|
|
178
|
+
readonly response_types: readonly ['code'];
|
|
179
|
+
readonly scope: string;
|
|
180
|
+
readonly client_name?: string;
|
|
181
|
+
}
|
|
182
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/server/types.ts"],"names":[],"mappings":"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"}
|
package/metadata.json
CHANGED
|
@@ -7,7 +7,8 @@
|
|
|
7
7
|
},
|
|
8
8
|
"description": "Unified authentication for Keycloak, Cognito, Nostr, and local ChatGPT sessions with OAuth2/OIDC and public key identity",
|
|
9
9
|
"provides": [
|
|
10
|
-
"Unified authentication for Keycloak, Cognito, Nostr, and local ChatGPT sessions with OAuth2/OIDC and public key identity"
|
|
10
|
+
"Unified authentication for Keycloak, Cognito, Nostr, and local ChatGPT sessions with OAuth2/OIDC and public key identity",
|
|
11
|
+
"Framework-independent OAuth authorization server via @happyvertical/auth/server: S256 PKCE, rotating refresh tokens, durable storage and live consent adapters, discovery, JWKS, revocation and opt-in client registration"
|
|
11
12
|
],
|
|
12
13
|
"implements": [],
|
|
13
14
|
"requires": {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@happyvertical/auth",
|
|
3
|
-
"version": "0.103.
|
|
3
|
+
"version": "0.103.5",
|
|
4
4
|
"description": "Unified authentication for Keycloak, Cognito, Nostr, and local ChatGPT sessions with OAuth2/OIDC and public key identity",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"main": "./dist/index.js",
|
|
@@ -10,6 +10,10 @@
|
|
|
10
10
|
"import": "./dist/index.js",
|
|
11
11
|
"types": "./dist/index.d.ts"
|
|
12
12
|
},
|
|
13
|
+
"./server": {
|
|
14
|
+
"import": "./dist/server/index.js",
|
|
15
|
+
"types": "./dist/server/index.d.ts"
|
|
16
|
+
},
|
|
13
17
|
"./local": {
|
|
14
18
|
"import": "./dist/local.js",
|
|
15
19
|
"types": "./dist/local.d.ts"
|
|
@@ -40,7 +44,7 @@
|
|
|
40
44
|
"homepage": "https://github.com/happyvertical/sdk/tree/main/packages/auth#readme",
|
|
41
45
|
"license": "MIT",
|
|
42
46
|
"dependencies": {
|
|
43
|
-
"@happyvertical/utils": "0.103.
|
|
47
|
+
"@happyvertical/utils": "0.103.5",
|
|
44
48
|
"jose": "^6.2.2"
|
|
45
49
|
},
|
|
46
50
|
"optionalDependencies": {
|