@_mustachio/openauth 0.9.2 → 0.11.0
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/dist/esm/adapters/d1/audit-log.js +15 -0
- package/dist/esm/adapters/d1/config-store.js +45 -0
- package/dist/esm/adapters/d1/index.js +12 -0
- package/dist/esm/adapters/d1/key-store.js +116 -0
- package/dist/esm/adapters/d1/method-store.js +52 -0
- package/dist/esm/adapters/d1/migrations.js +77 -0
- package/dist/esm/adapters/d1/session-store.js +134 -0
- package/dist/esm/adapters/d1/session.js +18 -0
- package/dist/esm/adapters/d1/token-store.js +140 -0
- package/dist/esm/adapters/durable-object/index.js +3 -0
- package/dist/esm/adapters/durable-object/session-store.js +139 -0
- package/dist/esm/adapters/durable-object/types.js +0 -0
- package/dist/esm/adapters/dynamo/audit-log.js +23 -0
- package/dist/esm/adapters/dynamo/client.js +0 -0
- package/dist/esm/adapters/dynamo/config-store.js +57 -0
- package/dist/esm/adapters/dynamo/index.js +10 -0
- package/dist/esm/adapters/dynamo/key-store.js +188 -0
- package/dist/esm/adapters/dynamo/method-store.js +72 -0
- package/dist/esm/adapters/dynamo/passkey-credential-store.js +83 -0
- package/dist/esm/adapters/dynamo/sdk.js +128 -0
- package/dist/esm/adapters/dynamo/session-store.js +173 -0
- package/dist/esm/adapters/dynamo/token-store.js +178 -0
- package/dist/esm/adapters/kms/in-memory-backing.js +28 -0
- package/dist/esm/adapters/kms/index.js +5 -0
- package/dist/esm/adapters/kms/key-store.js +129 -0
- package/dist/esm/adapters/kms/sdk.js +23 -0
- package/dist/esm/adapters/kms/types.js +0 -0
- package/dist/esm/adapters/kv/audit-log.js +21 -0
- package/dist/esm/adapters/kv/config-store.js +43 -0
- package/dist/esm/adapters/kv/index.js +5 -0
- package/dist/esm/adapters/kv/method-store.js +63 -0
- package/dist/esm/adapters/kv/types.js +0 -0
- package/dist/esm/adapters/memory/audit-log.js +16 -0
- package/dist/esm/adapters/memory/clock.js +5 -0
- package/dist/esm/adapters/memory/config-store.js +31 -0
- package/dist/esm/adapters/memory/index.js +10 -0
- package/dist/esm/adapters/memory/key-store.js +78 -0
- package/dist/esm/adapters/memory/method-store.js +43 -0
- package/dist/esm/adapters/memory/passkey-credential-store.js +53 -0
- package/dist/esm/adapters/memory/session-store.js +104 -0
- package/dist/esm/adapters/memory/token-store.js +104 -0
- package/dist/esm/adapters/postgres/audit-log.js +16 -0
- package/dist/esm/adapters/postgres/config-store.js +48 -0
- package/dist/esm/adapters/postgres/executor.js +21 -0
- package/dist/esm/adapters/postgres/index.js +13 -0
- package/dist/esm/adapters/postgres/key-store.js +191 -0
- package/dist/esm/adapters/postgres/method-store.js +61 -0
- package/dist/esm/adapters/postgres/migrations.js +111 -0
- package/dist/esm/adapters/postgres/passkey-credential-store.js +80 -0
- package/dist/esm/adapters/postgres/session-store.js +135 -0
- package/dist/esm/adapters/postgres/token-store.js +151 -0
- package/dist/esm/client.js +35 -12
- package/dist/esm/domain/audit.js +13 -0
- package/dist/esm/domain/authorize.js +217 -0
- package/dist/esm/domain/callback.js +176 -0
- package/dist/esm/domain/client-auth.js +61 -0
- package/dist/esm/domain/client-credentials.js +91 -0
- package/dist/esm/domain/crypto.js +97 -0
- package/dist/esm/domain/discovery.js +83 -0
- package/dist/esm/domain/dpop.js +122 -0
- package/dist/esm/domain/id-token.js +94 -0
- package/dist/esm/domain/introspect.js +55 -0
- package/dist/esm/domain/jwt.js +71 -0
- package/dist/esm/domain/logout.js +75 -0
- package/dist/esm/domain/method-cache.js +136 -0
- package/dist/esm/domain/method-dispatch.js +36 -0
- package/dist/esm/domain/method-route.js +111 -0
- package/dist/esm/domain/par.js +51 -0
- package/dist/esm/domain/pkce.js +16 -0
- package/dist/esm/domain/refresh.js +102 -0
- package/dist/esm/domain/register.js +74 -0
- package/dist/esm/domain/revoke.js +81 -0
- package/dist/esm/domain/state-envelope.js +80 -0
- package/dist/esm/domain/token-exchange.js +102 -0
- package/dist/esm/domain/token.js +246 -0
- package/dist/esm/domain/userinfo.js +62 -0
- package/dist/esm/http/context.js +7 -0
- package/dist/esm/http/cookies.js +98 -0
- package/dist/esm/http/errors.js +71 -0
- package/dist/esm/http/handlers/authorize.js +250 -0
- package/dist/esm/http/handlers/callback.js +53 -0
- package/dist/esm/http/handlers/end-session.js +64 -0
- package/dist/esm/http/handlers/metadata.js +37 -0
- package/dist/esm/http/handlers/method-route.js +87 -0
- package/dist/esm/http/handlers/par.js +53 -0
- package/dist/esm/http/handlers/register.js +46 -0
- package/dist/esm/http/handlers/revocation.js +98 -0
- package/dist/esm/http/handlers/token.js +197 -0
- package/dist/esm/http/handlers/userinfo.js +60 -0
- package/dist/esm/http/middleware/error.js +15 -0
- package/dist/esm/http/middleware/tenant.js +102 -0
- package/dist/esm/http/resolver.js +15 -0
- package/dist/esm/http/router.js +45 -0
- package/dist/esm/http/schemas/authorize.js +30 -0
- package/dist/esm/http/schemas/end-session.js +13 -0
- package/dist/esm/http/schemas/par.js +9 -0
- package/dist/esm/http/schemas/register.js +16 -0
- package/dist/esm/http/schemas/revocation.js +18 -0
- package/dist/esm/http/schemas/token.js +57 -0
- package/dist/esm/index.js +126 -9
- package/dist/esm/methods/code.js +221 -0
- package/dist/esm/methods/m2m.js +41 -0
- package/dist/esm/methods/oauth2-factory.js +84 -0
- package/dist/esm/methods/oauth2-generic.js +196 -0
- package/dist/esm/methods/oidc-generic.js +53 -0
- package/dist/esm/methods/passkey.js +275 -0
- package/dist/esm/methods/password-hash.js +79 -0
- package/dist/esm/methods/password.js +166 -0
- package/dist/esm/methods/providers/apple.js +29 -0
- package/dist/esm/methods/providers/cognito.js +37 -0
- package/dist/esm/methods/providers/discord.js +28 -0
- package/dist/esm/methods/providers/facebook.js +42 -0
- package/dist/esm/methods/providers/github.js +29 -0
- package/dist/esm/methods/providers/google.js +29 -0
- package/dist/esm/methods/providers/index.js +17 -0
- package/dist/esm/methods/providers/jumpcloud.js +27 -0
- package/dist/esm/methods/providers/keycloak.js +32 -0
- package/dist/esm/methods/providers/linkedin.js +28 -0
- package/dist/esm/methods/providers/microsoft.js +28 -0
- package/dist/esm/methods/providers/slack.js +30 -0
- package/dist/esm/methods/providers/spotify.js +28 -0
- package/dist/esm/methods/providers/twitch.js +28 -0
- package/dist/esm/methods/providers/x.js +28 -0
- package/dist/esm/methods/providers/yahoo.js +27 -0
- package/dist/esm/pkce.js +4 -16
- package/dist/esm/ports/audit-log.js +0 -0
- package/dist/esm/ports/config-store.js +0 -0
- package/dist/esm/ports/key-store.js +0 -0
- package/dist/esm/ports/method-store.js +0 -0
- package/dist/esm/ports/session-store.js +0 -0
- package/dist/esm/ports/token-store.js +0 -0
- package/dist/esm/types/authorization.js +0 -0
- package/dist/esm/types/error.js +70 -0
- package/dist/esm/types/flow.js +0 -0
- package/dist/esm/types/idp.js +0 -0
- package/dist/esm/types/method.js +0 -0
- package/dist/esm/types/picker.js +0 -0
- package/dist/esm/types/result.js +11 -0
- package/dist/esm/types/subject.js +0 -0
- package/dist/esm/types/tenant.js +5 -0
- package/dist/esm/types/token.js +0 -0
- package/dist/esm/ui/forms.js +253 -0
- package/dist/esm/ui/index.js +8 -0
- package/dist/esm/ui/picker.js +49 -0
- package/dist/types/adapters/d1/audit-log.d.ts +19 -0
- package/dist/types/adapters/d1/audit-log.d.ts.map +1 -0
- package/dist/types/adapters/d1/config-store.d.ts +20 -0
- package/dist/types/adapters/d1/config-store.d.ts.map +1 -0
- package/dist/types/adapters/d1/index.d.ts +35 -0
- package/dist/types/adapters/d1/index.d.ts.map +1 -0
- package/dist/types/adapters/d1/key-store.d.ts +17 -0
- package/dist/types/adapters/d1/key-store.d.ts.map +1 -0
- package/dist/types/adapters/d1/method-store.d.ts +21 -0
- package/dist/types/adapters/d1/method-store.d.ts.map +1 -0
- package/dist/types/adapters/d1/migrations.d.ts +18 -0
- package/dist/types/adapters/d1/migrations.d.ts.map +1 -0
- package/dist/types/adapters/d1/session-store.d.ts +20 -0
- package/dist/types/adapters/d1/session-store.d.ts.map +1 -0
- package/dist/types/adapters/d1/session.d.ts +18 -0
- package/dist/types/adapters/d1/session.d.ts.map +1 -0
- package/dist/types/adapters/d1/token-store.d.ts +29 -0
- package/dist/types/adapters/d1/token-store.d.ts.map +1 -0
- package/dist/types/adapters/d1/types.d.ts +43 -0
- package/dist/types/adapters/d1/types.d.ts.map +1 -0
- package/dist/types/adapters/durable-object/index.d.ts +17 -0
- package/dist/types/adapters/durable-object/index.d.ts.map +1 -0
- package/dist/types/adapters/durable-object/session-store.d.ts +21 -0
- package/dist/types/adapters/durable-object/session-store.d.ts.map +1 -0
- package/dist/types/adapters/durable-object/types.d.ts +23 -0
- package/dist/types/adapters/durable-object/types.d.ts.map +1 -0
- package/dist/types/adapters/dynamo/audit-log.d.ts +19 -0
- package/dist/types/adapters/dynamo/audit-log.d.ts.map +1 -0
- package/dist/types/adapters/dynamo/client.d.ts +111 -0
- package/dist/types/adapters/dynamo/client.d.ts.map +1 -0
- package/dist/types/adapters/dynamo/config-store.d.ts +21 -0
- package/dist/types/adapters/dynamo/config-store.d.ts.map +1 -0
- package/dist/types/adapters/dynamo/index.d.ts +60 -0
- package/dist/types/adapters/dynamo/index.d.ts.map +1 -0
- package/dist/types/adapters/dynamo/key-store.d.ts +23 -0
- package/dist/types/adapters/dynamo/key-store.d.ts.map +1 -0
- package/dist/types/adapters/dynamo/method-store.d.ts +20 -0
- package/dist/types/adapters/dynamo/method-store.d.ts.map +1 -0
- package/dist/types/adapters/dynamo/passkey-credential-store.d.ts +47 -0
- package/dist/types/adapters/dynamo/passkey-credential-store.d.ts.map +1 -0
- package/dist/types/adapters/dynamo/sdk.d.ts +23 -0
- package/dist/types/adapters/dynamo/sdk.d.ts.map +1 -0
- package/dist/types/adapters/dynamo/session-store.d.ts +20 -0
- package/dist/types/adapters/dynamo/session-store.d.ts.map +1 -0
- package/dist/types/adapters/dynamo/token-store.d.ts +29 -0
- package/dist/types/adapters/dynamo/token-store.d.ts.map +1 -0
- package/dist/types/adapters/kms/in-memory-backing.d.ts +9 -0
- package/dist/types/adapters/kms/in-memory-backing.d.ts.map +1 -0
- package/dist/types/adapters/kms/index.d.ts +35 -0
- package/dist/types/adapters/kms/index.d.ts.map +1 -0
- package/dist/types/adapters/kms/key-store.d.ts +20 -0
- package/dist/types/adapters/kms/key-store.d.ts.map +1 -0
- package/dist/types/adapters/kms/sdk.d.ts +16 -0
- package/dist/types/adapters/kms/sdk.d.ts.map +1 -0
- package/dist/types/adapters/kms/types.d.ts +58 -0
- package/dist/types/adapters/kms/types.d.ts.map +1 -0
- package/dist/types/adapters/kv/audit-log.d.ts +22 -0
- package/dist/types/adapters/kv/audit-log.d.ts.map +1 -0
- package/dist/types/adapters/kv/config-store.d.ts +25 -0
- package/dist/types/adapters/kv/config-store.d.ts.map +1 -0
- package/dist/types/adapters/kv/index.d.ts +21 -0
- package/dist/types/adapters/kv/index.d.ts.map +1 -0
- package/dist/types/adapters/kv/method-store.d.ts +23 -0
- package/dist/types/adapters/kv/method-store.d.ts.map +1 -0
- package/dist/types/adapters/kv/types.d.ts +28 -0
- package/dist/types/adapters/kv/types.d.ts.map +1 -0
- package/dist/types/adapters/memory/audit-log.d.ts +18 -0
- package/dist/types/adapters/memory/audit-log.d.ts.map +1 -0
- package/dist/types/adapters/memory/clock.d.ts +7 -0
- package/dist/types/adapters/memory/clock.d.ts.map +1 -0
- package/dist/types/adapters/memory/config-store.d.ts +19 -0
- package/dist/types/adapters/memory/config-store.d.ts.map +1 -0
- package/dist/types/adapters/memory/index.d.ts +15 -0
- package/dist/types/adapters/memory/index.d.ts.map +1 -0
- package/dist/types/adapters/memory/key-store.d.ts +17 -0
- package/dist/types/adapters/memory/key-store.d.ts.map +1 -0
- package/dist/types/adapters/memory/method-store.d.ts +26 -0
- package/dist/types/adapters/memory/method-store.d.ts.map +1 -0
- package/dist/types/adapters/memory/passkey-credential-store.d.ts +43 -0
- package/dist/types/adapters/memory/passkey-credential-store.d.ts.map +1 -0
- package/dist/types/adapters/memory/session-store.d.ts +21 -0
- package/dist/types/adapters/memory/session-store.d.ts.map +1 -0
- package/dist/types/adapters/memory/token-store.d.ts +29 -0
- package/dist/types/adapters/memory/token-store.d.ts.map +1 -0
- package/dist/types/adapters/postgres/audit-log.d.ts +18 -0
- package/dist/types/adapters/postgres/audit-log.d.ts.map +1 -0
- package/dist/types/adapters/postgres/config-store.d.ts +21 -0
- package/dist/types/adapters/postgres/config-store.d.ts.map +1 -0
- package/dist/types/adapters/postgres/executor.d.ts +48 -0
- package/dist/types/adapters/postgres/executor.d.ts.map +1 -0
- package/dist/types/adapters/postgres/index.d.ts +39 -0
- package/dist/types/adapters/postgres/index.d.ts.map +1 -0
- package/dist/types/adapters/postgres/key-store.d.ts +23 -0
- package/dist/types/adapters/postgres/key-store.d.ts.map +1 -0
- package/dist/types/adapters/postgres/method-store.d.ts +21 -0
- package/dist/types/adapters/postgres/method-store.d.ts.map +1 -0
- package/dist/types/adapters/postgres/migrations.d.ts +22 -0
- package/dist/types/adapters/postgres/migrations.d.ts.map +1 -0
- package/dist/types/adapters/postgres/passkey-credential-store.d.ts +48 -0
- package/dist/types/adapters/postgres/passkey-credential-store.d.ts.map +1 -0
- package/dist/types/adapters/postgres/session-store.d.ts +20 -0
- package/dist/types/adapters/postgres/session-store.d.ts.map +1 -0
- package/dist/types/adapters/postgres/token-store.d.ts +30 -0
- package/dist/types/adapters/postgres/token-store.d.ts.map +1 -0
- package/dist/types/client.d.ts +20 -1
- package/dist/types/client.d.ts.map +1 -1
- package/dist/types/domain/audit.d.ts +17 -0
- package/dist/types/domain/audit.d.ts.map +1 -0
- package/dist/types/domain/authorize.d.ts +125 -0
- package/dist/types/domain/authorize.d.ts.map +1 -0
- package/dist/types/domain/callback.d.ts +70 -0
- package/dist/types/domain/callback.d.ts.map +1 -0
- package/dist/types/domain/client-auth.d.ts +57 -0
- package/dist/types/domain/client-auth.d.ts.map +1 -0
- package/dist/types/domain/client-credentials.d.ts +54 -0
- package/dist/types/domain/client-credentials.d.ts.map +1 -0
- package/dist/types/domain/crypto.d.ts +53 -0
- package/dist/types/domain/crypto.d.ts.map +1 -0
- package/dist/types/domain/discovery.d.ts +81 -0
- package/dist/types/domain/discovery.d.ts.map +1 -0
- package/dist/types/domain/dpop.d.ts +61 -0
- package/dist/types/domain/dpop.d.ts.map +1 -0
- package/dist/types/domain/id-token.d.ts +83 -0
- package/dist/types/domain/id-token.d.ts.map +1 -0
- package/dist/types/domain/introspect.d.ts +79 -0
- package/dist/types/domain/introspect.d.ts.map +1 -0
- package/dist/types/domain/jwt.d.ts +74 -0
- package/dist/types/domain/jwt.d.ts.map +1 -0
- package/dist/types/domain/logout.d.ts +69 -0
- package/dist/types/domain/logout.d.ts.map +1 -0
- package/dist/types/domain/method-cache.d.ts +42 -0
- package/dist/types/domain/method-cache.d.ts.map +1 -0
- package/dist/types/domain/method-dispatch.d.ts +37 -0
- package/dist/types/domain/method-dispatch.d.ts.map +1 -0
- package/dist/types/domain/method-route.d.ts +77 -0
- package/dist/types/domain/method-route.d.ts.map +1 -0
- package/dist/types/domain/par.d.ts +62 -0
- package/dist/types/domain/par.d.ts.map +1 -0
- package/dist/types/domain/pkce.d.ts +15 -0
- package/dist/types/domain/pkce.d.ts.map +1 -0
- package/dist/types/domain/refresh.d.ts +52 -0
- package/dist/types/domain/refresh.d.ts.map +1 -0
- package/dist/types/domain/register.d.ts +33 -0
- package/dist/types/domain/register.d.ts.map +1 -0
- package/dist/types/domain/revoke.d.ts +61 -0
- package/dist/types/domain/revoke.d.ts.map +1 -0
- package/dist/types/domain/state-envelope.d.ts +30 -0
- package/dist/types/domain/state-envelope.d.ts.map +1 -0
- package/dist/types/domain/token-exchange.d.ts +69 -0
- package/dist/types/domain/token-exchange.d.ts.map +1 -0
- package/dist/types/domain/token.d.ts +140 -0
- package/dist/types/domain/token.d.ts.map +1 -0
- package/dist/types/domain/userinfo.d.ts +61 -0
- package/dist/types/domain/userinfo.d.ts.map +1 -0
- package/dist/types/http/context.d.ts +66 -0
- package/dist/types/http/context.d.ts.map +1 -0
- package/dist/types/http/cookies.d.ts +45 -0
- package/dist/types/http/cookies.d.ts.map +1 -0
- package/dist/types/http/errors.d.ts +36 -0
- package/dist/types/http/errors.d.ts.map +1 -0
- package/dist/types/http/handlers/authorize.d.ts +3 -0
- package/dist/types/http/handlers/authorize.d.ts.map +1 -0
- package/dist/types/http/handlers/callback.d.ts +3 -0
- package/dist/types/http/handlers/callback.d.ts.map +1 -0
- package/dist/types/http/handlers/end-session.d.ts +3 -0
- package/dist/types/http/handlers/end-session.d.ts.map +1 -0
- package/dist/types/http/handlers/metadata.d.ts +4 -0
- package/dist/types/http/handlers/metadata.d.ts.map +1 -0
- package/dist/types/http/handlers/method-route.d.ts +3 -0
- package/dist/types/http/handlers/method-route.d.ts.map +1 -0
- package/dist/types/http/handlers/par.d.ts +3 -0
- package/dist/types/http/handlers/par.d.ts.map +1 -0
- package/dist/types/http/handlers/register.d.ts +3 -0
- package/dist/types/http/handlers/register.d.ts.map +1 -0
- package/dist/types/http/handlers/revocation.d.ts +4 -0
- package/dist/types/http/handlers/revocation.d.ts.map +1 -0
- package/dist/types/http/handlers/token.d.ts +3 -0
- package/dist/types/http/handlers/token.d.ts.map +1 -0
- package/dist/types/http/handlers/userinfo.d.ts +3 -0
- package/dist/types/http/handlers/userinfo.d.ts.map +1 -0
- package/dist/types/http/middleware/error.d.ts +9 -0
- package/dist/types/http/middleware/error.d.ts.map +1 -0
- package/dist/types/http/middleware/tenant.d.ts +30 -0
- package/dist/types/http/middleware/tenant.d.ts.map +1 -0
- package/dist/types/http/resolver.d.ts +22 -0
- package/dist/types/http/resolver.d.ts.map +1 -0
- package/dist/types/http/router.d.ts +21 -0
- package/dist/types/http/router.d.ts.map +1 -0
- package/dist/types/http/schemas/authorize.d.ts +92 -0
- package/dist/types/http/schemas/authorize.d.ts.map +1 -0
- package/dist/types/http/schemas/end-session.d.ts +31 -0
- package/dist/types/http/schemas/end-session.d.ts.map +1 -0
- package/dist/types/http/schemas/par.d.ts +20 -0
- package/dist/types/http/schemas/par.d.ts.map +1 -0
- package/dist/types/http/schemas/register.d.ts +42 -0
- package/dist/types/http/schemas/register.d.ts.map +1 -0
- package/dist/types/http/schemas/revocation.d.ts +41 -0
- package/dist/types/http/schemas/revocation.d.ts.map +1 -0
- package/dist/types/http/schemas/token.d.ts +227 -0
- package/dist/types/http/schemas/token.d.ts.map +1 -0
- package/dist/types/index.d.ts +63 -13
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/methods/code.d.ts +96 -0
- package/dist/types/methods/code.d.ts.map +1 -0
- package/dist/types/methods/m2m.d.ts +41 -0
- package/dist/types/methods/m2m.d.ts.map +1 -0
- package/dist/types/methods/oauth2-factory.d.ts +133 -0
- package/dist/types/methods/oauth2-factory.d.ts.map +1 -0
- package/dist/types/methods/oauth2-generic.d.ts +75 -0
- package/dist/types/methods/oauth2-generic.d.ts.map +1 -0
- package/dist/types/methods/oidc-generic.d.ts +26 -0
- package/dist/types/methods/oidc-generic.d.ts.map +1 -0
- package/dist/types/methods/passkey.d.ts +106 -0
- package/dist/types/methods/passkey.d.ts.map +1 -0
- package/dist/types/methods/password-hash.d.ts +25 -0
- package/dist/types/methods/password-hash.d.ts.map +1 -0
- package/dist/types/methods/password.d.ts +70 -0
- package/dist/types/methods/password.d.ts.map +1 -0
- package/dist/types/methods/providers/apple.d.ts +29 -0
- package/dist/types/methods/providers/apple.d.ts.map +1 -0
- package/dist/types/methods/providers/cognito.d.ts +36 -0
- package/dist/types/methods/providers/cognito.d.ts.map +1 -0
- package/dist/types/methods/providers/discord.d.ts +22 -0
- package/dist/types/methods/providers/discord.d.ts.map +1 -0
- package/dist/types/methods/providers/facebook.d.ts +29 -0
- package/dist/types/methods/providers/facebook.d.ts.map +1 -0
- package/dist/types/methods/providers/github.d.ts +25 -0
- package/dist/types/methods/providers/github.d.ts.map +1 -0
- package/dist/types/methods/providers/google.d.ts +28 -0
- package/dist/types/methods/providers/google.d.ts.map +1 -0
- package/dist/types/methods/providers/index.d.ts +24 -0
- package/dist/types/methods/providers/index.d.ts.map +1 -0
- package/dist/types/methods/providers/jumpcloud.d.ts +22 -0
- package/dist/types/methods/providers/jumpcloud.d.ts.map +1 -0
- package/dist/types/methods/providers/keycloak.d.ts +30 -0
- package/dist/types/methods/providers/keycloak.d.ts.map +1 -0
- package/dist/types/methods/providers/linkedin.d.ts +22 -0
- package/dist/types/methods/providers/linkedin.d.ts.map +1 -0
- package/dist/types/methods/providers/microsoft.d.ts +30 -0
- package/dist/types/methods/providers/microsoft.d.ts.map +1 -0
- package/dist/types/methods/providers/slack.d.ts +25 -0
- package/dist/types/methods/providers/slack.d.ts.map +1 -0
- package/dist/types/methods/providers/spotify.d.ts +22 -0
- package/dist/types/methods/providers/spotify.d.ts.map +1 -0
- package/dist/types/methods/providers/twitch.d.ts +23 -0
- package/dist/types/methods/providers/twitch.d.ts.map +1 -0
- package/dist/types/methods/providers/x.d.ts +25 -0
- package/dist/types/methods/providers/x.d.ts.map +1 -0
- package/dist/types/methods/providers/yahoo.d.ts +22 -0
- package/dist/types/methods/providers/yahoo.d.ts.map +1 -0
- package/dist/types/pkce.d.ts +1 -2
- package/dist/types/pkce.d.ts.map +1 -1
- package/dist/types/ports/audit-log.d.ts +166 -0
- package/dist/types/ports/audit-log.d.ts.map +1 -0
- package/dist/types/ports/config-store.d.ts +32 -0
- package/dist/types/ports/config-store.d.ts.map +1 -0
- package/dist/types/ports/key-store.d.ts +98 -0
- package/dist/types/ports/key-store.d.ts.map +1 -0
- package/dist/types/ports/method-store.d.ts +29 -0
- package/dist/types/ports/method-store.d.ts.map +1 -0
- package/dist/types/ports/session-store.d.ts +109 -0
- package/dist/types/ports/session-store.d.ts.map +1 -0
- package/dist/types/ports/token-store.d.ts +105 -0
- package/dist/types/ports/token-store.d.ts.map +1 -0
- package/dist/types/types/authorization.d.ts +75 -0
- package/dist/types/types/authorization.d.ts.map +1 -0
- package/dist/types/types/error.d.ts +101 -0
- package/dist/types/types/error.d.ts.map +1 -0
- package/dist/types/types/flow.d.ts +97 -0
- package/dist/types/types/flow.d.ts.map +1 -0
- package/dist/types/types/idp.d.ts +324 -0
- package/dist/types/types/idp.d.ts.map +1 -0
- package/dist/types/types/method.d.ts +256 -0
- package/dist/types/types/method.d.ts.map +1 -0
- package/dist/types/types/picker.d.ts +31 -0
- package/dist/types/types/picker.d.ts.map +1 -0
- package/dist/types/types/result.d.ts +29 -0
- package/dist/types/types/result.d.ts.map +1 -0
- package/dist/types/types/subject.d.ts +47 -0
- package/dist/types/types/subject.d.ts.map +1 -0
- package/dist/types/types/tenant.d.ts +276 -0
- package/dist/types/types/tenant.d.ts.map +1 -0
- package/dist/types/types/token.d.ts +231 -0
- package/dist/types/types/token.d.ts.map +1 -0
- package/dist/types/ui/forms.d.ts +35 -0
- package/dist/types/ui/forms.d.ts.map +1 -0
- package/dist/types/ui/index.d.ts +14 -0
- package/dist/types/ui/index.d.ts.map +1 -0
- package/dist/types/ui/picker.d.ts +18 -0
- package/dist/types/ui/picker.d.ts.map +1 -0
- package/package.json +41 -6
- package/src/adapters/d1/audit-log.ts +32 -0
- package/src/adapters/d1/config-store.ts +67 -0
- package/src/adapters/d1/index.ts +41 -0
- package/src/adapters/d1/key-store.ts +218 -0
- package/src/adapters/d1/method-store.ts +103 -0
- package/src/adapters/d1/migrations.ts +89 -0
- package/src/adapters/d1/session-store.ts +230 -0
- package/src/adapters/d1/session.ts +38 -0
- package/src/adapters/d1/token-store.ts +251 -0
- package/src/adapters/d1/types.ts +53 -0
- package/src/adapters/durable-object/index.ts +23 -0
- package/src/adapters/durable-object/session-store.ts +227 -0
- package/src/adapters/durable-object/types.ts +25 -0
- package/src/adapters/dynamo/audit-log.ts +35 -0
- package/src/adapters/dynamo/client.ts +118 -0
- package/src/adapters/dynamo/config-store.ts +72 -0
- package/src/adapters/dynamo/index.ts +81 -0
- package/src/adapters/dynamo/key-store.ts +267 -0
- package/src/adapters/dynamo/method-store.ts +105 -0
- package/src/adapters/dynamo/passkey-credential-store.ts +132 -0
- package/src/adapters/dynamo/sdk.ts +189 -0
- package/src/adapters/dynamo/session-store.ts +229 -0
- package/src/adapters/dynamo/token-store.ts +248 -0
- package/src/adapters/kms/in-memory-backing.ts +36 -0
- package/src/adapters/kms/index.ts +39 -0
- package/src/adapters/kms/key-store.ts +176 -0
- package/src/adapters/kms/sdk.ts +39 -0
- package/src/adapters/kms/types.ts +61 -0
- package/src/adapters/kv/audit-log.ts +40 -0
- package/src/adapters/kv/config-store.ts +63 -0
- package/src/adapters/kv/index.ts +20 -0
- package/src/adapters/kv/method-store.ts +98 -0
- package/src/adapters/kv/types.ts +26 -0
- package/src/adapters/memory/audit-log.ts +28 -0
- package/src/adapters/memory/clock.ts +7 -0
- package/src/adapters/memory/config-store.ts +41 -0
- package/src/adapters/memory/index.ts +26 -0
- package/src/adapters/memory/key-store.ts +102 -0
- package/src/adapters/memory/method-store.ts +75 -0
- package/src/adapters/memory/passkey-credential-store.ts +97 -0
- package/src/adapters/memory/session-store.ts +171 -0
- package/src/adapters/memory/token-store.ts +181 -0
- package/src/adapters/postgres/audit-log.ts +34 -0
- package/src/adapters/postgres/config-store.ts +72 -0
- package/src/adapters/postgres/executor.ts +76 -0
- package/src/adapters/postgres/index.ts +60 -0
- package/src/adapters/postgres/key-store.ts +334 -0
- package/src/adapters/postgres/method-store.ts +104 -0
- package/src/adapters/postgres/migrations.ts +131 -0
- package/src/adapters/postgres/passkey-credential-store.ts +150 -0
- package/src/adapters/postgres/session-store.ts +216 -0
- package/src/adapters/postgres/token-store.ts +263 -0
- package/src/client.ts +82 -16
- package/src/domain/audit.ts +28 -0
- package/src/domain/authorize.ts +414 -0
- package/src/domain/callback.ts +268 -0
- package/src/domain/client-auth.ts +116 -0
- package/src/domain/client-credentials.ts +180 -0
- package/src/domain/crypto.ts +168 -0
- package/src/domain/discovery.ts +161 -0
- package/src/domain/dpop.ts +293 -0
- package/src/domain/id-token.ts +213 -0
- package/src/domain/introspect.ts +155 -0
- package/src/domain/jwt.ts +185 -0
- package/src/domain/logout.ts +180 -0
- package/src/domain/method-cache.ts +220 -0
- package/src/domain/method-dispatch.ts +95 -0
- package/src/domain/method-route.ts +213 -0
- package/src/domain/par.ts +141 -0
- package/src/domain/pkce.ts +37 -0
- package/src/domain/refresh.ts +210 -0
- package/src/domain/register.ts +168 -0
- package/src/domain/revoke.ts +161 -0
- package/src/domain/state-envelope.ts +142 -0
- package/src/domain/token-exchange.ts +243 -0
- package/src/domain/token.ts +483 -0
- package/src/domain/userinfo.ts +171 -0
- package/src/http/context.ts +90 -0
- package/src/http/cookies.ts +167 -0
- package/src/http/errors.ts +98 -0
- package/src/http/handlers/authorize.ts +362 -0
- package/src/http/handlers/callback.ts +77 -0
- package/src/http/handlers/end-session.ts +106 -0
- package/src/http/handlers/metadata.ts +49 -0
- package/src/http/handlers/method-route.ts +115 -0
- package/src/http/handlers/par.ts +84 -0
- package/src/http/handlers/register.ts +70 -0
- package/src/http/handlers/revocation.ts +151 -0
- package/src/http/handlers/token.ts +300 -0
- package/src/http/handlers/userinfo.ts +90 -0
- package/src/http/middleware/error.ts +26 -0
- package/src/http/middleware/tenant.ts +165 -0
- package/src/http/resolver.ts +34 -0
- package/src/http/router.ts +85 -0
- package/src/http/schemas/authorize.ts +85 -0
- package/src/http/schemas/end-session.ts +23 -0
- package/src/http/schemas/par.ts +23 -0
- package/src/http/schemas/register.ts +29 -0
- package/src/http/schemas/revocation.ts +23 -0
- package/src/http/schemas/token.ts +85 -0
- package/src/index.ts +283 -20
- package/src/methods/code.ts +359 -0
- package/src/methods/m2m.ts +82 -0
- package/src/methods/oauth2-factory.ts +151 -0
- package/src/methods/oauth2-generic.ts +360 -0
- package/src/methods/oidc-generic.ts +109 -0
- package/src/methods/passkey.ts +419 -0
- package/src/methods/password-hash.ts +134 -0
- package/src/methods/password.ts +298 -0
- package/src/methods/providers/apple.ts +42 -0
- package/src/methods/providers/cognito.ts +55 -0
- package/src/methods/providers/discord.ts +37 -0
- package/src/methods/providers/facebook.ts +54 -0
- package/src/methods/providers/github.ts +42 -0
- package/src/methods/providers/google.ts +43 -0
- package/src/methods/providers/index.ts +23 -0
- package/src/methods/providers/jumpcloud.ts +36 -0
- package/src/methods/providers/keycloak.ts +42 -0
- package/src/methods/providers/linkedin.ts +37 -0
- package/src/methods/providers/microsoft.ts +42 -0
- package/src/methods/providers/slack.ts +42 -0
- package/src/methods/providers/spotify.ts +37 -0
- package/src/methods/providers/twitch.ts +38 -0
- package/src/methods/providers/x.ts +40 -0
- package/src/methods/providers/yahoo.ts +36 -0
- package/src/pkce.ts +20 -21
- package/src/ports/CONSISTENCY.md +119 -0
- package/src/ports/audit-log.ts +177 -0
- package/src/ports/config-store.ts +34 -0
- package/src/ports/key-store.ts +106 -0
- package/src/ports/method-store.ts +41 -0
- package/src/ports/session-store.ts +131 -0
- package/src/ports/token-store.ts +116 -0
- package/src/types/authorization.ts +78 -0
- package/src/types/error.ts +146 -0
- package/src/types/flow.ts +99 -0
- package/src/types/idp.ts +365 -0
- package/src/types/method.ts +270 -0
- package/src/types/picker.ts +32 -0
- package/src/types/result.ts +23 -0
- package/src/types/subject.ts +50 -0
- package/src/types/tenant.ts +285 -0
- package/src/types/token.ts +236 -0
- package/src/ui/forms.ts +289 -0
- package/src/ui/index.ts +14 -0
- package/src/ui/picker.ts +63 -0
- package/dist/esm/issuer.js +0 -691
- package/dist/esm/jwt.js +0 -16
- package/dist/esm/keys.js +0 -113
- package/dist/esm/provider/apple.js +0 -28
- package/dist/esm/provider/arctic.js +0 -43
- package/dist/esm/provider/code.js +0 -58
- package/dist/esm/provider/cognito.js +0 -16
- package/dist/esm/provider/discord.js +0 -15
- package/dist/esm/provider/facebook.js +0 -24
- package/dist/esm/provider/github.js +0 -15
- package/dist/esm/provider/google.js +0 -25
- package/dist/esm/provider/index.js +0 -3
- package/dist/esm/provider/jumpcloud.js +0 -15
- package/dist/esm/provider/keycloak.js +0 -15
- package/dist/esm/provider/linkedin.js +0 -15
- package/dist/esm/provider/m2m.js +0 -16
- package/dist/esm/provider/microsoft.js +0 -24
- package/dist/esm/provider/oauth2.js +0 -119
- package/dist/esm/provider/oidc.js +0 -69
- package/dist/esm/provider/passkey.js +0 -315
- package/dist/esm/provider/password.js +0 -306
- package/dist/esm/provider/provider.js +0 -10
- package/dist/esm/provider/slack.js +0 -15
- package/dist/esm/provider/spotify.js +0 -15
- package/dist/esm/provider/twitch.js +0 -15
- package/dist/esm/provider/x.js +0 -16
- package/dist/esm/provider/yahoo.js +0 -15
- package/dist/esm/random.js +0 -27
- package/dist/esm/storage/aws.js +0 -39
- package/dist/esm/storage/cloudflare.js +0 -42
- package/dist/esm/storage/dynamo.js +0 -116
- package/dist/esm/storage/memory.js +0 -88
- package/dist/esm/storage/storage.js +0 -36
- package/dist/esm/subject.js +0 -7
- package/dist/esm/ui/base.js +0 -407
- package/dist/esm/ui/code.js +0 -151
- package/dist/esm/ui/form.js +0 -43
- package/dist/esm/ui/icon.js +0 -92
- package/dist/esm/ui/passkey.js +0 -329
- package/dist/esm/ui/password.js +0 -338
- package/dist/esm/ui/select.js +0 -187
- package/dist/esm/ui/theme.js +0 -115
- package/dist/esm/util.js +0 -54
- package/dist/types/issuer.d.ts +0 -607
- package/dist/types/issuer.d.ts.map +0 -1
- package/dist/types/jwt.d.ts +0 -6
- package/dist/types/jwt.d.ts.map +0 -1
- package/dist/types/keys.d.ts +0 -18
- package/dist/types/keys.d.ts.map +0 -1
- package/dist/types/provider/apple.d.ts +0 -108
- package/dist/types/provider/apple.d.ts.map +0 -1
- package/dist/types/provider/arctic.d.ts +0 -16
- package/dist/types/provider/arctic.d.ts.map +0 -1
- package/dist/types/provider/code.d.ts +0 -74
- package/dist/types/provider/code.d.ts.map +0 -1
- package/dist/types/provider/cognito.d.ts +0 -64
- package/dist/types/provider/cognito.d.ts.map +0 -1
- package/dist/types/provider/discord.d.ts +0 -38
- package/dist/types/provider/discord.d.ts.map +0 -1
- package/dist/types/provider/facebook.d.ts +0 -74
- package/dist/types/provider/facebook.d.ts.map +0 -1
- package/dist/types/provider/github.d.ts +0 -38
- package/dist/types/provider/github.d.ts.map +0 -1
- package/dist/types/provider/google.d.ts +0 -74
- package/dist/types/provider/google.d.ts.map +0 -1
- package/dist/types/provider/index.d.ts +0 -4
- package/dist/types/provider/index.d.ts.map +0 -1
- package/dist/types/provider/jumpcloud.d.ts +0 -38
- package/dist/types/provider/jumpcloud.d.ts.map +0 -1
- package/dist/types/provider/keycloak.d.ts +0 -67
- package/dist/types/provider/keycloak.d.ts.map +0 -1
- package/dist/types/provider/linkedin.d.ts +0 -6
- package/dist/types/provider/linkedin.d.ts.map +0 -1
- package/dist/types/provider/m2m.d.ts +0 -34
- package/dist/types/provider/m2m.d.ts.map +0 -1
- package/dist/types/provider/microsoft.d.ts +0 -89
- package/dist/types/provider/microsoft.d.ts.map +0 -1
- package/dist/types/provider/oauth2.d.ts +0 -133
- package/dist/types/provider/oauth2.d.ts.map +0 -1
- package/dist/types/provider/oidc.d.ts +0 -91
- package/dist/types/provider/oidc.d.ts.map +0 -1
- package/dist/types/provider/passkey.d.ts +0 -143
- package/dist/types/provider/passkey.d.ts.map +0 -1
- package/dist/types/provider/password.d.ts +0 -210
- package/dist/types/provider/password.d.ts.map +0 -1
- package/dist/types/provider/provider.d.ts +0 -29
- package/dist/types/provider/provider.d.ts.map +0 -1
- package/dist/types/provider/slack.d.ts +0 -59
- package/dist/types/provider/slack.d.ts.map +0 -1
- package/dist/types/provider/spotify.d.ts +0 -38
- package/dist/types/provider/spotify.d.ts.map +0 -1
- package/dist/types/provider/twitch.d.ts +0 -38
- package/dist/types/provider/twitch.d.ts.map +0 -1
- package/dist/types/provider/x.d.ts +0 -38
- package/dist/types/provider/x.d.ts.map +0 -1
- package/dist/types/provider/yahoo.d.ts +0 -38
- package/dist/types/provider/yahoo.d.ts.map +0 -1
- package/dist/types/random.d.ts +0 -3
- package/dist/types/random.d.ts.map +0 -1
- package/dist/types/storage/aws.d.ts +0 -4
- package/dist/types/storage/aws.d.ts.map +0 -1
- package/dist/types/storage/cloudflare.d.ts +0 -34
- package/dist/types/storage/cloudflare.d.ts.map +0 -1
- package/dist/types/storage/dynamo.d.ts +0 -65
- package/dist/types/storage/dynamo.d.ts.map +0 -1
- package/dist/types/storage/memory.d.ts +0 -49
- package/dist/types/storage/memory.d.ts.map +0 -1
- package/dist/types/storage/storage.d.ts +0 -15
- package/dist/types/storage/storage.d.ts.map +0 -1
- package/dist/types/subject.d.ts +0 -122
- package/dist/types/subject.d.ts.map +0 -1
- package/dist/types/ui/base.d.ts +0 -5
- package/dist/types/ui/base.d.ts.map +0 -1
- package/dist/types/ui/code.d.ts +0 -104
- package/dist/types/ui/code.d.ts.map +0 -1
- package/dist/types/ui/form.d.ts +0 -6
- package/dist/types/ui/form.d.ts.map +0 -1
- package/dist/types/ui/icon.d.ts +0 -6
- package/dist/types/ui/icon.d.ts.map +0 -1
- package/dist/types/ui/passkey.d.ts +0 -5
- package/dist/types/ui/passkey.d.ts.map +0 -1
- package/dist/types/ui/password.d.ts +0 -139
- package/dist/types/ui/password.d.ts.map +0 -1
- package/dist/types/ui/select.d.ts +0 -55
- package/dist/types/ui/select.d.ts.map +0 -1
- package/dist/types/ui/theme.d.ts +0 -207
- package/dist/types/ui/theme.d.ts.map +0 -1
- package/dist/types/util.d.ts +0 -8
- package/dist/types/util.d.ts.map +0 -1
- package/src/css.d.ts +0 -4
- package/src/issuer.ts +0 -1628
- package/src/jwt.ts +0 -17
- package/src/keys.ts +0 -139
- package/src/provider/apple.ts +0 -127
- package/src/provider/arctic.ts +0 -66
- package/src/provider/code.ts +0 -227
- package/src/provider/cognito.ts +0 -74
- package/src/provider/discord.ts +0 -45
- package/src/provider/facebook.ts +0 -84
- package/src/provider/github.ts +0 -45
- package/src/provider/google.ts +0 -85
- package/src/provider/index.ts +0 -3
- package/src/provider/jumpcloud.ts +0 -45
- package/src/provider/keycloak.ts +0 -75
- package/src/provider/linkedin.ts +0 -12
- package/src/provider/m2m.ts +0 -56
- package/src/provider/microsoft.ts +0 -100
- package/src/provider/oauth2.ts +0 -297
- package/src/provider/oidc.ts +0 -179
- package/src/provider/passkey.ts +0 -655
- package/src/provider/password.ts +0 -672
- package/src/provider/provider.ts +0 -33
- package/src/provider/slack.ts +0 -67
- package/src/provider/spotify.ts +0 -45
- package/src/provider/twitch.ts +0 -45
- package/src/provider/x.ts +0 -46
- package/src/provider/yahoo.ts +0 -45
- package/src/random.ts +0 -24
- package/src/storage/aws.ts +0 -59
- package/src/storage/cloudflare.ts +0 -77
- package/src/storage/dynamo.ts +0 -193
- package/src/storage/memory.ts +0 -135
- package/src/storage/storage.ts +0 -46
- package/src/subject.ts +0 -130
- package/src/ui/base.tsx +0 -118
- package/src/ui/code.tsx +0 -215
- package/src/ui/form.tsx +0 -40
- package/src/ui/icon.tsx +0 -95
- package/src/ui/passkey.tsx +0 -321
- package/src/ui/password.tsx +0 -405
- package/src/ui/select.tsx +0 -221
- package/src/ui/theme.ts +0 -319
- package/src/ui/ui.css +0 -252
- package/src/util.ts +0 -58
- /package/dist/esm/{css.d.js → adapters/d1/types.js} +0 -0
|
@@ -0,0 +1,213 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `handleMethodRoute` — the third pipeline.
|
|
3
|
+
*
|
|
4
|
+
* `/authorize` and `/cb/:methodId` are the two pipelines that produce a
|
|
5
|
+
* flow record and consume it respectively. Credential-style methods
|
|
6
|
+
* (password, code, passkey) additionally need a way to make in-flight
|
|
7
|
+
* POSTs against the IdP — submitting a login form, asking for a one-time
|
|
8
|
+
* code, completing a WebAuthn ceremony. The HTTP layer mounts these at
|
|
9
|
+
* `/m/<methodId>/<subPath>` and delegates here.
|
|
10
|
+
*
|
|
11
|
+
* Responsibilities:
|
|
12
|
+
* 1. Read `flowId` from the framework-set HttpOnly `idp.flow` cookie.
|
|
13
|
+
* No cookie → `invalid_request` (the user lost their flow).
|
|
14
|
+
* 2. `SessionStore.readFlow(flowId)` — peek, do not consume. Methods may
|
|
15
|
+
* need multiple round trips before completing (e.g. send-code →
|
|
16
|
+
* verify-code).
|
|
17
|
+
* 3. Tenant must match the cookie's flow. If the request's tenant
|
|
18
|
+
* (resolved via `resolveTenant`) disagrees with the flow's tenant,
|
|
19
|
+
* audit `flow_tenant_mismatch` and reject. This is the same invariant
|
|
20
|
+
* the upstream-callback path enforces.
|
|
21
|
+
* 4. Dispatch the method's `<METHOD> <subPath>` route.
|
|
22
|
+
* 5. Translate `MethodResult`:
|
|
23
|
+
* - `challenge` → return response (methodState merged before send).
|
|
24
|
+
* - `success` → `consumeFlow`, snapshot into auth code, return
|
|
25
|
+
* `issue-code` for the HTTP layer to redirect.
|
|
26
|
+
* - `denied` → return reason; HTTP layer renders.
|
|
27
|
+
* - `error` → propagated.
|
|
28
|
+
*/
|
|
29
|
+
import type { AuditLog } from "../ports/audit-log"
|
|
30
|
+
import type { KeyStore } from "../ports/key-store"
|
|
31
|
+
import type { SessionStore } from "../ports/session-store"
|
|
32
|
+
import type { TokenStore } from "../ports/token-store"
|
|
33
|
+
import { authError, type AuthError } from "../types/error"
|
|
34
|
+
import type { FlowRecord } from "../types/flow"
|
|
35
|
+
import type { MethodResult, CachePolicy, SetCookie } from "../types/method"
|
|
36
|
+
import type { Result } from "../types/result"
|
|
37
|
+
import { err, isErr, ok } from "../types/result"
|
|
38
|
+
import type { TenantContext } from "../types/tenant"
|
|
39
|
+
|
|
40
|
+
import { safeAudit } from "./audit"
|
|
41
|
+
import { AUTH_CODE_TTL_MS } from "./authorize"
|
|
42
|
+
import { randomToken } from "./crypto"
|
|
43
|
+
import { MethodCache } from "./method-cache"
|
|
44
|
+
import { dispatchMethod, type RouteKey } from "./method-dispatch"
|
|
45
|
+
import { saveEncryptedCode } from "./token"
|
|
46
|
+
|
|
47
|
+
export type MethodRouteOutput =
|
|
48
|
+
| {
|
|
49
|
+
kind: "issue-code"
|
|
50
|
+
code: string
|
|
51
|
+
appRedirectUri: string
|
|
52
|
+
appState: string | null
|
|
53
|
+
}
|
|
54
|
+
| {
|
|
55
|
+
kind: "challenge"
|
|
56
|
+
response: Response
|
|
57
|
+
setCookies: SetCookie[]
|
|
58
|
+
cache?: CachePolicy
|
|
59
|
+
}
|
|
60
|
+
| { kind: "denied"; reason: string; setCookies: SetCookie[] }
|
|
61
|
+
|
|
62
|
+
export type HandleMethodRouteInput = {
|
|
63
|
+
rawRequest: Request
|
|
64
|
+
tenant: TenantContext
|
|
65
|
+
/** Tenant-local instance id (`MethodConfig.id`) parsed from the URL. */
|
|
66
|
+
methodId: string
|
|
67
|
+
/** Path within the method's mount, e.g. `"/login"`. */
|
|
68
|
+
subPath: string
|
|
69
|
+
/** HTTP method of the incoming request: `"GET"` or `"POST"`. */
|
|
70
|
+
httpMethod: "GET" | "POST"
|
|
71
|
+
/** flowId from the `idp.flow` cookie. */
|
|
72
|
+
flowId: string
|
|
73
|
+
cookies: ReadonlyMap<string, string>
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
export type HandleMethodRouteDeps = {
|
|
77
|
+
sessionStore: SessionStore
|
|
78
|
+
tokenStore: TokenStore
|
|
79
|
+
/** Needed for at-rest encryption of the code payload — see `domain/token.ts`. */
|
|
80
|
+
keyStore: KeyStore
|
|
81
|
+
auditLog?: AuditLog
|
|
82
|
+
methodCache: MethodCache
|
|
83
|
+
clock: () => number
|
|
84
|
+
newCodeId?: () => string
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
export async function handleMethodRoute(
|
|
88
|
+
input: HandleMethodRouteInput,
|
|
89
|
+
deps: HandleMethodRouteDeps,
|
|
90
|
+
): Promise<Result<MethodRouteOutput, AuthError>> {
|
|
91
|
+
// 1. Peek at the flow record.
|
|
92
|
+
const flowRes = await deps.sessionStore.readFlow(input.flowId)
|
|
93
|
+
if (isErr(flowRes)) return err(flowRes.error)
|
|
94
|
+
const flow = flowRes.value
|
|
95
|
+
|
|
96
|
+
// 2. Tenant must match.
|
|
97
|
+
if (flow.tenantId !== input.tenant.id) {
|
|
98
|
+
await safeAudit(deps, {
|
|
99
|
+
kind: "flow_tenant_mismatch",
|
|
100
|
+
stateTenantId: input.tenant.id,
|
|
101
|
+
flowTenantId: flow.tenantId,
|
|
102
|
+
flowId: flow.flowId,
|
|
103
|
+
timestamp: deps.clock(),
|
|
104
|
+
})
|
|
105
|
+
return err(authError.invalidRequest("tenant mismatch", "flow"))
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
// 3. Resolve the method.
|
|
109
|
+
if (flow.methodId !== input.methodId) {
|
|
110
|
+
return err(
|
|
111
|
+
authError.invalidRequest(
|
|
112
|
+
`method "${input.methodId}" does not own flow "${flow.flowId}" (expected "${flow.methodId}")`,
|
|
113
|
+
"methodId",
|
|
114
|
+
),
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
const methodRes = await deps.methodCache.resolve(
|
|
118
|
+
input.tenant.config,
|
|
119
|
+
input.methodId,
|
|
120
|
+
)
|
|
121
|
+
if (isErr(methodRes)) return err(methodRes.error)
|
|
122
|
+
|
|
123
|
+
// 4. Dispatch.
|
|
124
|
+
const route: RouteKey = `${input.httpMethod} ${input.subPath}`
|
|
125
|
+
const dispatched = await dispatchMethod({
|
|
126
|
+
method: methodRes.value,
|
|
127
|
+
route,
|
|
128
|
+
tenant: input.tenant,
|
|
129
|
+
request: input.rawRequest,
|
|
130
|
+
subPath: input.subPath,
|
|
131
|
+
flow,
|
|
132
|
+
cookies: input.cookies,
|
|
133
|
+
sessionStore: deps.sessionStore,
|
|
134
|
+
dispatch: null,
|
|
135
|
+
})
|
|
136
|
+
if (isErr(dispatched)) return err(dispatched.error)
|
|
137
|
+
return translate(dispatched.value, flow, deps)
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
async function translate(
|
|
141
|
+
result: MethodResult<unknown, unknown>,
|
|
142
|
+
flow: FlowRecord,
|
|
143
|
+
deps: HandleMethodRouteDeps,
|
|
144
|
+
): Promise<Result<MethodRouteOutput, AuthError>> {
|
|
145
|
+
switch (result.kind) {
|
|
146
|
+
case "success": {
|
|
147
|
+
const consumed = await deps.sessionStore.consumeFlow(flow.flowId)
|
|
148
|
+
if (isErr(consumed)) return err(consumed.error)
|
|
149
|
+
// Use the consumed record (the one we already had via readFlow may be
|
|
150
|
+
// slightly stale relative to the most recent updateFlowMethodState).
|
|
151
|
+
const final = consumed.value
|
|
152
|
+
const code = (deps.newCodeId ?? randomToken)()
|
|
153
|
+
const now = deps.clock()
|
|
154
|
+
const saved = await saveEncryptedCode(
|
|
155
|
+
code,
|
|
156
|
+
{
|
|
157
|
+
tenantId: final.tenantId,
|
|
158
|
+
clientId: final.clientId,
|
|
159
|
+
appRedirectUri: final.appRedirectUri,
|
|
160
|
+
appState: final.appState,
|
|
161
|
+
scopes: final.scopes,
|
|
162
|
+
audience: final.audience,
|
|
163
|
+
clientPkce: final.clientPkce,
|
|
164
|
+
methodId: final.methodId,
|
|
165
|
+
methodKind: final.methodKind,
|
|
166
|
+
context: final.context ?? null,
|
|
167
|
+
providerSubject: result.providerSubject,
|
|
168
|
+
properties: result.properties,
|
|
169
|
+
...(final.appNonce !== undefined ? { appNonce: final.appNonce } : {}),
|
|
170
|
+
...(final.claimsRequest !== undefined
|
|
171
|
+
? { claimsRequest: final.claimsRequest }
|
|
172
|
+
: {}),
|
|
173
|
+
authTime: Math.floor(now / 1000),
|
|
174
|
+
expiresAt: now + AUTH_CODE_TTL_MS,
|
|
175
|
+
},
|
|
176
|
+
AUTH_CODE_TTL_MS,
|
|
177
|
+
{ keyStore: deps.keyStore, tokenStore: deps.tokenStore },
|
|
178
|
+
)
|
|
179
|
+
if (isErr(saved)) return err(saved.error)
|
|
180
|
+
return ok({
|
|
181
|
+
kind: "issue-code",
|
|
182
|
+
code,
|
|
183
|
+
appRedirectUri: final.appRedirectUri,
|
|
184
|
+
appState: final.appState,
|
|
185
|
+
})
|
|
186
|
+
}
|
|
187
|
+
case "challenge":
|
|
188
|
+
return ok({
|
|
189
|
+
kind: "challenge",
|
|
190
|
+
response: result.response,
|
|
191
|
+
setCookies: result.setCookies ?? [],
|
|
192
|
+
...(result.cache !== undefined ? { cache: result.cache } : {}),
|
|
193
|
+
})
|
|
194
|
+
case "denied":
|
|
195
|
+
await safeAudit(deps, {
|
|
196
|
+
kind: "authorize_failed",
|
|
197
|
+
tenantId: flow.tenantId,
|
|
198
|
+
clientId: flow.clientId,
|
|
199
|
+
methodId: flow.methodId,
|
|
200
|
+
methodKind: flow.methodKind,
|
|
201
|
+
flowId: flow.flowId,
|
|
202
|
+
reason: result.reason,
|
|
203
|
+
timestamp: deps.clock(),
|
|
204
|
+
})
|
|
205
|
+
return ok({
|
|
206
|
+
kind: "denied",
|
|
207
|
+
reason: result.reason,
|
|
208
|
+
setCookies: result.setCookies ?? [],
|
|
209
|
+
})
|
|
210
|
+
case "error":
|
|
211
|
+
return err(result.error)
|
|
212
|
+
}
|
|
213
|
+
}
|
|
@@ -0,0 +1,141 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Pushed Authorization Requests (RFC 9126).
|
|
3
|
+
*
|
|
4
|
+
* The RP submits the full `/authorize` parameter set to `POST /par` along
|
|
5
|
+
* with its client credentials. The OP authenticates the client, stores
|
|
6
|
+
* the payload under an opaque `request_uri`, and returns it with an
|
|
7
|
+
* `expires_in`. The RP then redirects the user-agent to
|
|
8
|
+
* `GET /authorize?client_id=...&request_uri=...` and the OP rehydrates
|
|
9
|
+
* the original parameter set.
|
|
10
|
+
*
|
|
11
|
+
* Per RFC 9126 §3:
|
|
12
|
+
* - Response is HTTP 201 with `application/json` body
|
|
13
|
+
* `{request_uri, expires_in}`.
|
|
14
|
+
* - `request_uri` MUST be of the form
|
|
15
|
+
* `urn:ietf:params:oauth:request_uri:<opaque>` (§2.2).
|
|
16
|
+
* - Default TTL is 60 seconds — same as auth-code TTL.
|
|
17
|
+
*
|
|
18
|
+
* Per RFC 9126 §4:
|
|
19
|
+
* - At `/authorize`, `request_uri` is one-shot — consumed and discarded
|
|
20
|
+
* on first use.
|
|
21
|
+
* - Parameters in the PAR record take precedence; additional `/authorize`
|
|
22
|
+
* parameters MAY be merged but MUST NOT contradict (we strictly use
|
|
23
|
+
* the PAR'd set and ignore any additional ones except `client_id`).
|
|
24
|
+
*
|
|
25
|
+
* Client authentication (§2):
|
|
26
|
+
* - Public clients: `client_id` only.
|
|
27
|
+
* - Confidential clients: `client_id` + `client_secret` (Basic or form).
|
|
28
|
+
*/
|
|
29
|
+
import type { AuditLog } from "../ports/audit-log"
|
|
30
|
+
import type { ConfigStore } from "../ports/config-store"
|
|
31
|
+
import type { SessionStore } from "../ports/session-store"
|
|
32
|
+
import { authError, type AuthError } from "../types/error"
|
|
33
|
+
import type { Result } from "../types/result"
|
|
34
|
+
import { err, isErr, ok } from "../types/result"
|
|
35
|
+
import type { TenantContext } from "../types/tenant"
|
|
36
|
+
|
|
37
|
+
import { verifyClientCredentials } from "./client-auth"
|
|
38
|
+
import { randomToken } from "./crypto"
|
|
39
|
+
|
|
40
|
+
export const PAR_URI_PREFIX = "urn:ietf:params:oauth:request_uri:"
|
|
41
|
+
export const DEFAULT_PAR_TTL_MS = 60 * 1000
|
|
42
|
+
|
|
43
|
+
export type ParRequest = {
|
|
44
|
+
clientId: string
|
|
45
|
+
/** Confidential-client secret. */
|
|
46
|
+
clientSecret?: string
|
|
47
|
+
/** Raw `/authorize` parameter record, posted by the RP. */
|
|
48
|
+
params: Record<string, string>
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
export type ParResponse = {
|
|
52
|
+
request_uri: string
|
|
53
|
+
expires_in: number
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
export type ParDeps = {
|
|
57
|
+
configStore: ConfigStore
|
|
58
|
+
sessionStore: SessionStore
|
|
59
|
+
auditLog?: AuditLog
|
|
60
|
+
clock: () => number
|
|
61
|
+
/** Test override. */
|
|
62
|
+
newRequestUriSuffix?: () => string
|
|
63
|
+
ttlMs?: number
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Process a `POST /par` request. Authenticates the client, validates the
|
|
68
|
+
* `client_id` consistency, and persists the parameter set.
|
|
69
|
+
*/
|
|
70
|
+
export async function pushAuthorizationRequest(
|
|
71
|
+
req: ParRequest,
|
|
72
|
+
tenant: TenantContext,
|
|
73
|
+
deps: ParDeps,
|
|
74
|
+
): Promise<Result<ParResponse, AuthError>> {
|
|
75
|
+
if (!deps.sessionStore.savePar || !deps.sessionStore.consumePar) {
|
|
76
|
+
return err(
|
|
77
|
+
authError.invalidRequest(
|
|
78
|
+
"session adapter does not implement PAR storage",
|
|
79
|
+
),
|
|
80
|
+
)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
// 1. Client authentication. The `client_id` in the body must match the
|
|
84
|
+
// authenticating client.
|
|
85
|
+
const client = tenant.config.clients.find((c) => c.id === req.clientId)
|
|
86
|
+
if (!client) {
|
|
87
|
+
return err(authError.invalidClient(`unknown client "${req.clientId}"`))
|
|
88
|
+
}
|
|
89
|
+
if (client.type === "confidential") {
|
|
90
|
+
const authErr = await verifyClientCredentials(client, req.clientSecret)
|
|
91
|
+
if (authErr) return err(authErr)
|
|
92
|
+
} else if (req.clientSecret !== undefined) {
|
|
93
|
+
return err(
|
|
94
|
+
authError.invalidClient("public client must not present client_secret"),
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
// 2. Sanity-check the body: client_id in body must match — the RFC
|
|
99
|
+
// requires it (§2). RP shouldn't be authenticating one client and
|
|
100
|
+
// pushing params for a different one.
|
|
101
|
+
if (req.params.client_id && req.params.client_id !== req.clientId) {
|
|
102
|
+
return err(
|
|
103
|
+
authError.invalidRequest(
|
|
104
|
+
"client_id in body conflicts with authenticated client",
|
|
105
|
+
"client_id",
|
|
106
|
+
),
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
// RFC 9126 §2.1: `request_uri` MUST NOT appear in a PAR request body.
|
|
110
|
+
if ("request_uri" in req.params) {
|
|
111
|
+
return err(
|
|
112
|
+
authError.invalidRequest(
|
|
113
|
+
"request_uri MUST NOT be present in a PAR request",
|
|
114
|
+
"request_uri",
|
|
115
|
+
),
|
|
116
|
+
)
|
|
117
|
+
}
|
|
118
|
+
|
|
119
|
+
// 3. Mint request_uri + persist.
|
|
120
|
+
const suffix = (deps.newRequestUriSuffix ?? randomToken)()
|
|
121
|
+
const requestUri = PAR_URI_PREFIX + suffix
|
|
122
|
+
const ttl = deps.ttlMs ?? DEFAULT_PAR_TTL_MS
|
|
123
|
+
const now = deps.clock()
|
|
124
|
+
const saved = await deps.sessionStore.savePar(
|
|
125
|
+
requestUri,
|
|
126
|
+
{
|
|
127
|
+
requestUri,
|
|
128
|
+
params: { ...req.params, client_id: req.clientId },
|
|
129
|
+
clientId: req.clientId,
|
|
130
|
+
issuedAt: now,
|
|
131
|
+
expiresAt: now + ttl,
|
|
132
|
+
},
|
|
133
|
+
ttl,
|
|
134
|
+
)
|
|
135
|
+
if (isErr(saved)) return err(saved.error)
|
|
136
|
+
|
|
137
|
+
return ok({
|
|
138
|
+
request_uri: requestUri,
|
|
139
|
+
expires_in: Math.floor(ttl / 1000),
|
|
140
|
+
})
|
|
141
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* PKCE validation. OAuth 2.1 mandates the `S256` method; `plain` is **not**
|
|
3
|
+
* supported by this IdP.
|
|
4
|
+
*/
|
|
5
|
+
import { base64url, sha256, timingSafeEqualStr, utf8 } from "./crypto"
|
|
6
|
+
|
|
7
|
+
/**
|
|
8
|
+
* Compute the S256 challenge for a verifier. Used at `/token` to recompute
|
|
9
|
+
* the expected challenge from the supplied `code_verifier` and compare it
|
|
10
|
+
* (timing-safe) against the challenge stashed in the auth-code payload.
|
|
11
|
+
*/
|
|
12
|
+
export async function s256Challenge(verifier: string): Promise<string> {
|
|
13
|
+
return base64url.encode(await sha256(utf8.encode(verifier)))
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* Verify a `code_verifier` against a previously-stored `code_challenge`.
|
|
18
|
+
*
|
|
19
|
+
* - Returns `false` on any length / character anomaly without computing the
|
|
20
|
+
* hash — these are public-shape checks, not secret-dependent.
|
|
21
|
+
* - Uses a constant-time compare for the recomputed challenge.
|
|
22
|
+
*/
|
|
23
|
+
export async function validatePkce(
|
|
24
|
+
verifier: string,
|
|
25
|
+
challenge: string,
|
|
26
|
+
): Promise<boolean> {
|
|
27
|
+
if (
|
|
28
|
+
typeof verifier !== "string" ||
|
|
29
|
+
typeof challenge !== "string" ||
|
|
30
|
+
verifier.length < 43 ||
|
|
31
|
+
verifier.length > 128
|
|
32
|
+
) {
|
|
33
|
+
return false
|
|
34
|
+
}
|
|
35
|
+
const computed = await s256Challenge(verifier)
|
|
36
|
+
return timingSafeEqualStr(computed, challenge)
|
|
37
|
+
}
|
|
@@ -0,0 +1,210 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* `/token` endpoint logic for `grant_type=refresh_token`.
|
|
3
|
+
*
|
|
4
|
+
* Rotation semantics (plan §"Cross-cutting Decisions" + §"Port consistency
|
|
5
|
+
* contracts"):
|
|
6
|
+
*
|
|
7
|
+
* - Refresh tokens rotate on every use. The presented token is consumed
|
|
8
|
+
* (CAS); a fresh refresh token is issued, keyed by the same `family`.
|
|
9
|
+
* - If the same token is presented a second time within the reuse window
|
|
10
|
+
* (default 60 s), the family is revoked and the request is rejected
|
|
11
|
+
* with `invalid_grant`. Audit: `refresh_reuse_detected`.
|
|
12
|
+
* - Outside the reuse window the row should be GC'd; presentation
|
|
13
|
+
* returns `invalid_grant` ("unknown token").
|
|
14
|
+
*/
|
|
15
|
+
import type { AuditLog } from "../ports/audit-log"
|
|
16
|
+
import type { ConfigStore } from "../ports/config-store"
|
|
17
|
+
import type { KeyStore } from "../ports/key-store"
|
|
18
|
+
import type { TokenStore } from "../ports/token-store"
|
|
19
|
+
import { authError, type AuthError } from "../types/error"
|
|
20
|
+
import type { Result } from "../types/result"
|
|
21
|
+
import { err, isErr } from "../types/result"
|
|
22
|
+
import type { TenantContext } from "../types/tenant"
|
|
23
|
+
import type { TokenResponse } from "../types/token"
|
|
24
|
+
|
|
25
|
+
import { safeAudit } from "./audit"
|
|
26
|
+
import { verifyClientCredentials } from "./client-auth"
|
|
27
|
+
import { mintTokens } from "./token"
|
|
28
|
+
|
|
29
|
+
export type RefreshGrantRequest = {
|
|
30
|
+
grantType: "refresh_token"
|
|
31
|
+
refreshToken: string
|
|
32
|
+
/** Optional per RFC 6749 — narrow scope. If absent, original scopes are reused. */
|
|
33
|
+
scope?: string
|
|
34
|
+
/** Confidential clients authenticate at /token. */
|
|
35
|
+
clientId?: string
|
|
36
|
+
clientSecret?: string
|
|
37
|
+
/**
|
|
38
|
+
* RFC 9449 §6 — JWK thumbprint of the DPoP proof presented on this
|
|
39
|
+
* refresh request. MUST match `RefreshTokenPayload.dpopJkt` when the
|
|
40
|
+
* original grant was DPoP-bound; presence is REQUIRED for bound
|
|
41
|
+
* tokens, OPTIONAL otherwise.
|
|
42
|
+
*/
|
|
43
|
+
dpopJkt?: string
|
|
44
|
+
}
|
|
45
|
+
|
|
46
|
+
export type RefreshTokensDeps = {
|
|
47
|
+
configStore: ConfigStore
|
|
48
|
+
tokenStore: TokenStore
|
|
49
|
+
keyStore: KeyStore
|
|
50
|
+
auditLog?: AuditLog
|
|
51
|
+
issuerUrl: string
|
|
52
|
+
clock: () => number
|
|
53
|
+
/** Reuse-detection window (ms). Default 60 s. */
|
|
54
|
+
reuseWindowMs?: number
|
|
55
|
+
newRefreshToken?: () => string
|
|
56
|
+
/** See `IdPOptions.customScopeClaims`. Forwarded to `mintTokens`. */
|
|
57
|
+
customScopeClaims?: Record<string, ReadonlyArray<string>>
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export async function refreshTokens(
|
|
61
|
+
req: RefreshGrantRequest,
|
|
62
|
+
deps: RefreshTokensDeps,
|
|
63
|
+
): Promise<Result<TokenResponse, AuthError>> {
|
|
64
|
+
// Peek before consuming so we can authenticate the client without
|
|
65
|
+
// burning the token on auth failures (RFC 6749 §6).
|
|
66
|
+
const peek = await deps.tokenStore.peekRefresh(req.refreshToken)
|
|
67
|
+
if (isErr(peek)) return err(peek.error)
|
|
68
|
+
const peekedPayload = peek.value
|
|
69
|
+
|
|
70
|
+
const tenantCfg = await deps.configStore.getTenantConfig(
|
|
71
|
+
peekedPayload.tenantId,
|
|
72
|
+
)
|
|
73
|
+
if (isErr(tenantCfg)) return err(tenantCfg.error)
|
|
74
|
+
|
|
75
|
+
// Authenticate the *presenting* client first, then check ownership.
|
|
76
|
+
// Wrong-secret, wrong-client, and unknown-presenting-client all collapse
|
|
77
|
+
// to the same `invalid_grant` response so an attacker holding a stolen
|
|
78
|
+
// refresh token cannot probe candidate `client_id` values: every
|
|
79
|
+
// misroute looks identical on the wire (RFC 6749 §5.2; H4 of the
|
|
80
|
+
// post-rebuild review).
|
|
81
|
+
const INVALID_REFRESH_DESC = "refresh token is invalid"
|
|
82
|
+
const client = tenantCfg.value.clients.find(
|
|
83
|
+
(c) => c.id === peekedPayload.clientId,
|
|
84
|
+
)
|
|
85
|
+
if (!client) {
|
|
86
|
+
return err(authError.invalidGrant(INVALID_REFRESH_DESC))
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
if (req.clientId !== undefined) {
|
|
90
|
+
const presenting = tenantCfg.value.clients.find(
|
|
91
|
+
(c) => c.id === req.clientId,
|
|
92
|
+
)
|
|
93
|
+
if (!presenting) {
|
|
94
|
+
return err(authError.invalidGrant(INVALID_REFRESH_DESC))
|
|
95
|
+
}
|
|
96
|
+
const authErr = await verifyClientCredentials(presenting, req.clientSecret)
|
|
97
|
+
if (authErr) return err(authError.invalidGrant(INVALID_REFRESH_DESC))
|
|
98
|
+
if (req.clientId !== peekedPayload.clientId) {
|
|
99
|
+
return err(authError.invalidGrant(INVALID_REFRESH_DESC))
|
|
100
|
+
}
|
|
101
|
+
} else if (client.type === "confidential") {
|
|
102
|
+
return err(authError.invalidGrant(INVALID_REFRESH_DESC))
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
// RFC 9449 §5 — when the refresh token is DPoP-bound, verify the
|
|
106
|
+
// presented DPoP thumbprint matches BEFORE consuming. Consuming first
|
|
107
|
+
// would burn the token on a wrong-key probe AND trip reuse-detection
|
|
108
|
+
// on a subsequent legitimate retry with the right key.
|
|
109
|
+
if (peekedPayload.dpopJkt !== undefined) {
|
|
110
|
+
if (req.dpopJkt === undefined) {
|
|
111
|
+
return err(
|
|
112
|
+
authError.invalidDpopProof(
|
|
113
|
+
"refresh token is DPoP-bound; request is missing a DPoP proof",
|
|
114
|
+
),
|
|
115
|
+
)
|
|
116
|
+
}
|
|
117
|
+
if (req.dpopJkt !== peekedPayload.dpopJkt) {
|
|
118
|
+
return err(
|
|
119
|
+
authError.invalidDpopProof(
|
|
120
|
+
"refresh token DPoP jkt does not match the original binding",
|
|
121
|
+
),
|
|
122
|
+
)
|
|
123
|
+
}
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
const consumed = await deps.tokenStore.consumeRefresh(req.refreshToken, {
|
|
127
|
+
reuseWindowMs: deps.reuseWindowMs,
|
|
128
|
+
})
|
|
129
|
+
if (isErr(consumed)) {
|
|
130
|
+
if (consumed.error.code === "invalid_grant" && consumed.error.reuseSignal) {
|
|
131
|
+
// Reuse-detection signal arrives typed on the AuthError. tenantId /
|
|
132
|
+
// subjectId come from the signal when the adapter emits it; we fall
|
|
133
|
+
// back to the peeked payload's fields for adapters that don't
|
|
134
|
+
// (older 4th-party adapters that satisfy the port without the
|
|
135
|
+
// structured carrier). `family` always prefers the signal — it's
|
|
136
|
+
// the discriminating identifier the adapter knows.
|
|
137
|
+
const signal = consumed.error.reuseSignal
|
|
138
|
+
await safeAudit(deps, {
|
|
139
|
+
kind: "refresh_reuse_detected",
|
|
140
|
+
tenantId: peekedPayload.tenantId,
|
|
141
|
+
clientId: peekedPayload.clientId,
|
|
142
|
+
family: signal.family,
|
|
143
|
+
timestamp: deps.clock(),
|
|
144
|
+
})
|
|
145
|
+
}
|
|
146
|
+
return err(consumed.error)
|
|
147
|
+
}
|
|
148
|
+
const payload = consumed.value
|
|
149
|
+
|
|
150
|
+
// Narrow scope if requested (must be subset of original).
|
|
151
|
+
const requestedScopes = req.scope
|
|
152
|
+
? req.scope.split(" ").filter(Boolean)
|
|
153
|
+
: payload.scopes
|
|
154
|
+
for (const s of requestedScopes) {
|
|
155
|
+
if (!payload.scopes.includes(s)) {
|
|
156
|
+
return err(
|
|
157
|
+
authError.invalidScope(
|
|
158
|
+
`requested scope "${s}" not granted by original refresh token`,
|
|
159
|
+
),
|
|
160
|
+
)
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
const tenant: TenantContext = {
|
|
165
|
+
id: payload.tenantId,
|
|
166
|
+
config: tenantCfg.value,
|
|
167
|
+
request: { raw: new Request("about:blank"), custom: {} },
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
return mintTokens({
|
|
171
|
+
tenant,
|
|
172
|
+
claim: payload.claim,
|
|
173
|
+
payload: {
|
|
174
|
+
tenantId: payload.tenantId,
|
|
175
|
+
clientId: payload.clientId,
|
|
176
|
+
// Carry original method provenance forward — descendant tokens
|
|
177
|
+
// surface the method that started the chain via `mid` / `mkind`,
|
|
178
|
+
// not the grant-type literal "refresh".
|
|
179
|
+
methodId: payload.methodId,
|
|
180
|
+
methodKind: payload.methodKind,
|
|
181
|
+
scopes: requestedScopes,
|
|
182
|
+
audience: payload.audience,
|
|
183
|
+
// `auth_time` is stable across refresh rotations per OIDC Core §12;
|
|
184
|
+
// refresh does not re-authenticate the user. `nonce` is deliberately
|
|
185
|
+
// NOT carried forward — the nonce was bound to the original
|
|
186
|
+
// `/authorize` request and should not reappear on rotated id_tokens.
|
|
187
|
+
authTime: payload.authTime,
|
|
188
|
+
// Preserve DPoP binding across refresh rotation (§6.1).
|
|
189
|
+
...(payload.dpopJkt !== undefined ? { dpopJkt: payload.dpopJkt } : {}),
|
|
190
|
+
// Preserve OIDC §5.5 claims-parameter intent across refresh (§12).
|
|
191
|
+
...(payload.claimsRequest !== undefined
|
|
192
|
+
? { claimsRequest: payload.claimsRequest }
|
|
193
|
+
: {}),
|
|
194
|
+
},
|
|
195
|
+
family: payload.family,
|
|
196
|
+
deps,
|
|
197
|
+
}).then(async (result) => {
|
|
198
|
+
if (result.ok) {
|
|
199
|
+
await safeAudit(deps, {
|
|
200
|
+
kind: "token_refreshed",
|
|
201
|
+
tenantId: payload.tenantId,
|
|
202
|
+
clientId: payload.clientId,
|
|
203
|
+
subjectId: payload.subjectId,
|
|
204
|
+
family: payload.family,
|
|
205
|
+
timestamp: deps.clock(),
|
|
206
|
+
})
|
|
207
|
+
}
|
|
208
|
+
return result
|
|
209
|
+
})
|
|
210
|
+
}
|