@udibo/oauth2 0.14.0 → 0.15.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/README.md +45 -24
- package/{esm → dist}/adapters/hono/_common.d.ts +5 -5
- package/{esm → dist}/adapters/hono/_common.js +1 -1
- package/{esm → dist}/adapters/hono/authorization-server.d.ts +6 -7
- package/{esm → dist}/adapters/hono/authorization-server.js +0 -1
- package/{esm → dist}/adapters/hono/bff/auth-request-store.d.ts +2 -2
- package/{esm → dist}/adapters/hono/bff/auth-request-store.js +2 -2
- package/{esm → dist}/adapters/hono/bff/bff.d.ts +22 -12
- package/{esm → dist}/adapters/hono/bff/bff.js +35 -29
- package/{esm → dist}/adapters/hono/bff/cookie-prefix.js +1 -2
- package/{esm → dist}/adapters/hono/bff/mod.d.ts +5 -6
- package/{esm → dist}/adapters/hono/bff/mod.js +1 -2
- package/{esm → dist}/adapters/hono/bff/proxy.js +2 -1
- package/{esm → dist}/adapters/hono/bff/session-store.d.ts +2 -2
- package/{esm → dist}/adapters/hono/bff/session-store.js +7 -6
- package/{esm → dist}/adapters/hono/bff/testing.d.ts +7 -8
- package/{esm → dist}/adapters/hono/bff/testing.js +19 -22
- package/{esm → dist}/adapters/hono/identity.d.ts +1 -2
- package/{esm → dist}/adapters/hono/identity.js +10 -10
- package/{esm → dist}/adapters/hono/log.d.ts +0 -1
- package/{esm → dist}/adapters/hono/log.js +0 -6
- package/{esm → dist}/adapters/hono/resource-server.d.ts +5 -6
- package/{esm → dist}/adapters/hono/resource-server.js +0 -1
- package/dist/cli/bin.d.ts +2 -0
- package/dist/cli/bin.js +3 -0
- package/dist/cli/idp/config.d.ts +110 -0
- package/dist/cli/idp/config.js +269 -0
- package/dist/cli/idp/mod.d.ts +20 -0
- package/dist/cli/idp/mod.js +175 -0
- package/dist/cli/idp/pages.d.ts +56 -0
- package/dist/cli/idp/pages.js +190 -0
- package/dist/cli/idp/server.d.ts +93 -0
- package/dist/cli/idp/server.js +559 -0
- package/dist/cli/keygen.d.ts +13 -0
- package/dist/cli/keygen.js +30 -0
- package/dist/cli/mod.d.ts +34 -0
- package/dist/cli/mod.js +94 -0
- package/{esm → dist}/client/_http.d.ts +1 -1
- package/{esm → dist}/client/base.d.ts +1 -1
- package/{esm → dist}/client/bff-client.d.ts +1 -1
- package/{esm → dist}/client/bff-client.js +7 -6
- package/{esm → dist}/client/browser-storage.d.ts +1 -1
- package/{esm → dist}/client/check.js +1 -1
- package/{esm → dist}/client/direct-client.d.ts +6 -6
- package/{esm → dist}/client/direct-client.js +11 -13
- package/{esm → dist}/client/discovery-cache.d.ts +1 -1
- package/{esm → dist}/client/discovery-cache.js +2 -2
- package/{esm → dist}/client/events.d.ts +1 -1
- package/{esm → dist}/client/mod.d.ts +11 -12
- package/{esm → dist}/client/mod.js +1 -1
- package/{esm → dist}/errors.d.ts +1 -1
- package/{esm → dist}/errors.js +1 -1
- package/{esm → dist}/identity/events.d.ts +1 -1
- package/{esm → dist}/identity/external/_shared.d.ts +1 -1
- package/{esm → dist}/identity/external/_shared.js +1 -2
- package/{esm → dist}/identity/external/apple-client-secret.d.ts +1 -1
- package/{esm → dist}/identity/external/apple-client-secret.js +6 -7
- package/{esm → dist}/identity/external/apple.d.ts +5 -5
- package/{esm → dist}/identity/external/apple.js +10 -11
- package/{esm → dist}/identity/external/discord.d.ts +3 -3
- package/{esm → dist}/identity/external/discord.js +2 -2
- package/{esm → dist}/identity/external/flow.d.ts +1 -1
- package/{esm → dist}/identity/external/flow.js +2 -2
- package/{esm → dist}/identity/external/github.d.ts +3 -3
- package/{esm → dist}/identity/external/github.js +12 -17
- package/{esm → dist}/identity/external/google.d.ts +5 -5
- package/{esm → dist}/identity/external/google.js +2 -2
- package/{esm → dist}/identity/external/mod.d.ts +12 -13
- package/{esm → dist}/identity/external/mod.js +0 -1
- package/{esm → dist}/identity/external/oauth2.d.ts +1 -1
- package/{esm → dist}/identity/external/oauth2.js +8 -8
- package/{esm → dist}/identity/external/oidc.d.ts +4 -4
- package/{esm → dist}/identity/external/oidc.js +9 -8
- package/{esm → dist}/identity/hibp.d.ts +1 -1
- package/{esm → dist}/identity/hibp.js +1 -1
- package/{esm → dist}/identity/lockout.js +1 -2
- package/{esm → dist}/identity/mfa/mod.d.ts +4 -5
- package/{esm → dist}/identity/mfa/mod.js +1 -2
- package/{esm → dist}/identity/mfa/service.d.ts +3 -3
- package/{esm → dist}/identity/mfa/service.js +4 -3
- package/{esm → dist}/identity/mfa/totp.d.ts +1 -1
- package/{esm → dist}/identity/mfa/totp.js +2 -2
- package/{esm → dist}/identity/migration.d.ts +2 -3
- package/{esm → dist}/identity/migration.js +3 -4
- package/{esm → dist}/identity/mod.d.ts +14 -15
- package/{esm → dist}/identity/mod.js +0 -1
- package/{esm → dist}/identity/otp.d.ts +1 -1
- package/{esm → dist}/identity/otp.js +4 -2
- package/{esm → dist}/identity/password.js +8 -5
- package/{esm → dist}/identity/rate-limit.d.ts +1 -1
- package/{esm → dist}/identity/service.d.ts +10 -10
- package/{esm → dist}/identity/service.js +17 -18
- package/{esm → dist}/identity/session.js +2 -2
- package/{esm → dist}/identity/token-flow.js +3 -2
- package/{esm → dist}/models/authorization-code.d.ts +3 -3
- package/{esm → dist}/models/authorization.d.ts +1 -1
- package/{esm → dist}/models/authorization.js +1 -2
- package/{esm → dist}/models/device-authorization.d.ts +2 -2
- package/{esm → dist}/models/token.d.ts +3 -3
- package/{esm → dist}/react/callback.d.ts +1 -1
- package/{esm → dist}/react/callback.js +0 -1
- package/{esm → dist}/react/components/class-names.d.ts +1 -1
- package/{esm → dist}/react/components/class-names.js +3 -2
- package/{esm → dist}/react/components/internal.d.ts +2 -2
- package/{esm → dist}/react/components/internal.js +5 -11
- package/{esm → dist}/react/components/mfa-challenge-form.d.ts +2 -2
- package/{esm → dist}/react/components/mfa-challenge-form.js +4 -6
- package/{esm → dist}/react/components/mfa-enrollment-form.d.ts +2 -2
- package/{esm → dist}/react/components/mfa-enrollment-form.js +2 -6
- package/{esm → dist}/react/components/mod.d.ts +20 -21
- package/{esm → dist}/react/components/mod.js +1 -2
- package/{esm → dist}/react/components/request-password-reset-form.d.ts +2 -2
- package/{esm → dist}/react/components/request-password-reset-form.js +1 -3
- package/{esm → dist}/react/components/reset-password-form.d.ts +2 -2
- package/{esm → dist}/react/components/reset-password-form.js +2 -2
- package/{esm → dist}/react/components/sign-in-form.d.ts +2 -2
- package/{esm → dist}/react/components/sign-in-form.js +1 -5
- package/{esm → dist}/react/components/sign-up-form.d.ts +2 -2
- package/{esm → dist}/react/components/sign-up-form.js +4 -10
- package/{esm → dist}/react/components/types.d.ts +2 -2
- package/{esm → dist}/react/components/use-auth-form.d.ts +3 -3
- package/{esm → dist}/react/components/use-auth-form.js +4 -7
- package/{esm → dist}/react/components/user-menu.d.ts +2 -2
- package/{esm → dist}/react/components/user-menu.js +9 -14
- package/{esm → dist}/react/context.d.ts +1 -1
- package/{esm → dist}/react/mod.d.ts +6 -7
- package/{esm → dist}/react/mod.js +0 -1
- package/{esm → dist}/react/provider.d.ts +2 -2
- package/{esm → dist}/react/require-auth.js +1 -3
- package/{esm → dist}/react/testing.d.ts +2 -3
- package/{esm → dist}/react/testing.js +1 -2
- package/{esm → dist}/react/use-authorization.d.ts +1 -1
- package/{esm → dist}/react/use-oauth2.d.ts +8 -1
- package/{esm → dist}/react/use-oauth2.js +0 -1
- package/{esm → dist}/server/_clock-skew.js +2 -1
- package/{esm → dist}/server/authorization-server.d.ts +40 -41
- package/{esm → dist}/server/authorization-server.js +32 -42
- package/{esm → dist}/server/client-authentication.d.ts +2 -2
- package/{esm → dist}/server/grants/authorization-code.d.ts +9 -9
- package/{esm → dist}/server/grants/authorization-code.js +5 -6
- package/{esm → dist}/server/grants/client-credentials.d.ts +4 -4
- package/{esm → dist}/server/grants/device-authorization.d.ts +6 -6
- package/{esm → dist}/server/grants/device-authorization.js +4 -4
- package/{esm → dist}/server/grants/grant.d.ts +7 -7
- package/{esm → dist}/server/grants/grant.js +7 -7
- package/{esm → dist}/server/grants/password.d.ts +5 -5
- package/{esm → dist}/server/grants/refresh-token.d.ts +4 -4
- package/{esm → dist}/server/grants/refresh-token.js +5 -6
- package/{esm → dist}/server/introspection-token-reader.d.ts +5 -5
- package/{esm → dist}/server/introspection-token-reader.js +4 -4
- package/{esm → dist}/server/jwks-token-reader.d.ts +5 -5
- package/{esm → dist}/server/jwks-token-reader.js +4 -4
- package/{esm → dist}/server/mod.d.ts +12 -13
- package/{esm → dist}/server/mod.js +0 -1
- package/{esm → dist}/server/public-suffix/mod.d.ts +2 -3
- package/{esm → dist}/server/public-suffix/mod.js +1 -2
- package/{esm → dist}/server/public-suffix/rules.d.ts +1 -1
- package/{esm → dist}/server/public-suffix/rules.js +1 -1
- package/{esm → dist}/server/redirect-uri.js +5 -4
- package/{esm → dist}/server/resource-server.d.ts +11 -12
- package/{esm → dist}/server/resource-server.js +12 -14
- package/{esm → dist}/server/services/authorization-code.d.ts +5 -5
- package/{esm → dist}/server/services/client.d.ts +1 -1
- package/{esm → dist}/server/services/device-authorization.d.ts +3 -3
- package/{esm → dist}/server/services/token.d.ts +6 -6
- package/{esm → dist}/server/services/token.js +3 -1
- package/{esm → dist}/server/services/user.d.ts +1 -1
- package/{esm → dist}/server/signing-keys.d.ts +1 -1
- package/{esm → dist}/server/signing-keys.js +8 -2
- package/{esm → dist}/server/utils/hash.js +1 -1
- package/{esm → dist}/testing/contract/auth-request-storage.d.ts +1 -1
- package/{esm → dist}/testing/contract/auth-request-storage.js +24 -29
- package/{esm → dist}/testing/contract/authorization-code.d.ts +6 -6
- package/{esm → dist}/testing/contract/authorization-code.js +16 -17
- package/{esm → dist}/testing/contract/client.d.ts +4 -4
- package/{esm → dist}/testing/contract/client.js +14 -15
- package/{esm → dist}/testing/contract/device-authorization.d.ts +6 -6
- package/{esm → dist}/testing/contract/device-authorization.js +37 -39
- package/{esm → dist}/testing/contract/identity-session.d.ts +6 -1
- package/{esm → dist}/testing/contract/identity-session.js +44 -36
- package/{esm → dist}/testing/contract/identity-user-store.d.ts +8 -2
- package/{esm → dist}/testing/contract/identity-user-store.js +48 -46
- package/{esm → dist}/testing/contract/lockout-store.d.ts +1 -1
- package/{esm → dist}/testing/contract/lockout-store.js +23 -24
- package/{esm → dist}/testing/contract/mfa-store.d.ts +1 -1
- package/{esm → dist}/testing/contract/mfa-store.js +53 -54
- package/{esm → dist}/testing/contract/mod.d.ts +15 -16
- package/{esm → dist}/testing/contract/mod.js +0 -1
- package/{esm → dist}/testing/contract/otp-store.d.ts +1 -1
- package/{esm → dist}/testing/contract/otp-store.js +33 -34
- package/{esm → dist}/testing/contract/rate-limit-store.d.ts +1 -1
- package/{esm → dist}/testing/contract/rate-limit-store.js +15 -16
- package/{esm → dist}/testing/contract/tenant.js +361 -330
- package/{esm → dist}/testing/contract/token-flow-store.d.ts +1 -1
- package/{esm → dist}/testing/contract/token-flow-store.js +27 -32
- package/{esm → dist}/testing/contract/token-reader.d.ts +3 -3
- package/{esm → dist}/testing/contract/token-reader.js +6 -7
- package/{esm → dist}/testing/contract/token.d.ts +7 -7
- package/{esm → dist}/testing/contract/token.js +48 -53
- package/{esm → dist}/testing/contract/user.d.ts +2 -2
- package/{esm → dist}/testing/contract/user.js +8 -9
- package/{esm → dist}/testing/mod.d.ts +5 -6
- package/{esm → dist}/testing/mod.js +2 -3
- package/{esm → dist}/testing/server.d.ts +7 -6
- package/{esm → dist}/testing/server.js +2 -1
- package/{esm → dist}/testing/services.d.ts +11 -11
- package/{esm → dist}/testing/services.js +8 -8
- package/{esm → dist}/testing/tenant.d.ts +11 -7
- package/{esm → dist}/testing/tenant.js +109 -94
- package/dist/utils/_constant-time.d.ts +12 -0
- package/dist/utils/_constant-time.js +19 -0
- package/{esm → dist}/utils/_default-fetch.js +4 -1
- package/dist/utils/_delay.d.ts +13 -0
- package/dist/utils/_delay.js +28 -0
- package/dist/utils/_encoding.d.ts +39 -0
- package/dist/utils/_encoding.js +126 -0
- package/{esm → dist}/utils/authentication-context.d.ts +1 -1
- package/{esm → dist}/utils/crypto.d.ts +2 -3
- package/{esm → dist}/utils/crypto.js +3 -4
- package/{esm → dist}/utils/pkce.js +1 -1
- package/{esm → dist}/utils/text.js +1 -1
- package/{esm → dist}/utils/url.d.ts +0 -1
- package/{esm → dist}/utils/url.js +0 -1
- package/package.json +156 -33
- package/esm/_dnt.polyfills.d.ts +0 -31
- package/esm/_dnt.polyfills.js +0 -26
- package/esm/deps/jsr.io/@std/assert/1.0.19/almost_equals.d.ts +0 -29
- package/esm/deps/jsr.io/@std/assert/1.0.19/almost_equals.js +0 -47
- package/esm/deps/jsr.io/@std/assert/1.0.19/array_includes.d.ts +0 -28
- package/esm/deps/jsr.io/@std/assert/1.0.19/array_includes.js +0 -65
- package/esm/deps/jsr.io/@std/assert/1.0.19/assert.d.ts +0 -16
- package/esm/deps/jsr.io/@std/assert/1.0.19/assert.js +0 -23
- package/esm/deps/jsr.io/@std/assert/1.0.19/assertion_error.d.ts +0 -25
- package/esm/deps/jsr.io/@std/assert/1.0.19/assertion_error.js +0 -30
- package/esm/deps/jsr.io/@std/assert/1.0.19/equal.d.ts +0 -24
- package/esm/deps/jsr.io/@std/assert/1.0.19/equal.js +0 -193
- package/esm/deps/jsr.io/@std/assert/1.0.19/equals.d.ts +0 -36
- package/esm/deps/jsr.io/@std/assert/1.0.19/equals.js +0 -61
- package/esm/deps/jsr.io/@std/assert/1.0.19/exists.d.ts +0 -17
- package/esm/deps/jsr.io/@std/assert/1.0.19/exists.js +0 -27
- package/esm/deps/jsr.io/@std/assert/1.0.19/fail.d.ts +0 -14
- package/esm/deps/jsr.io/@std/assert/1.0.19/fail.js +0 -20
- package/esm/deps/jsr.io/@std/assert/1.0.19/false.d.ts +0 -18
- package/esm/deps/jsr.io/@std/assert/1.0.19/false.js +0 -23
- package/esm/deps/jsr.io/@std/assert/1.0.19/greater.d.ts +0 -19
- package/esm/deps/jsr.io/@std/assert/1.0.19/greater.js +0 -29
- package/esm/deps/jsr.io/@std/assert/1.0.19/greater_or_equal.d.ts +0 -19
- package/esm/deps/jsr.io/@std/assert/1.0.19/greater_or_equal.js +0 -29
- package/esm/deps/jsr.io/@std/assert/1.0.19/instance_of.d.ts +0 -22
- package/esm/deps/jsr.io/@std/assert/1.0.19/instance_of.js +0 -52
- package/esm/deps/jsr.io/@std/assert/1.0.19/is_error.d.ts +0 -24
- package/esm/deps/jsr.io/@std/assert/1.0.19/is_error.js +0 -53
- package/esm/deps/jsr.io/@std/assert/1.0.19/less.d.ts +0 -18
- package/esm/deps/jsr.io/@std/assert/1.0.19/less.js +0 -28
- package/esm/deps/jsr.io/@std/assert/1.0.19/less_or_equal.d.ts +0 -19
- package/esm/deps/jsr.io/@std/assert/1.0.19/less_or_equal.js +0 -29
- package/esm/deps/jsr.io/@std/assert/1.0.19/match.d.ts +0 -17
- package/esm/deps/jsr.io/@std/assert/1.0.19/match.js +0 -26
- package/esm/deps/jsr.io/@std/assert/1.0.19/mod.d.ts +0 -43
- package/esm/deps/jsr.io/@std/assert/1.0.19/mod.js +0 -45
- package/esm/deps/jsr.io/@std/assert/1.0.19/not_equals.d.ts +0 -26
- package/esm/deps/jsr.io/@std/assert/1.0.19/not_equals.js +0 -39
- package/esm/deps/jsr.io/@std/assert/1.0.19/not_instance_of.d.ts +0 -19
- package/esm/deps/jsr.io/@std/assert/1.0.19/not_instance_of.js +0 -29
- package/esm/deps/jsr.io/@std/assert/1.0.19/not_match.d.ts +0 -17
- package/esm/deps/jsr.io/@std/assert/1.0.19/not_match.js +0 -26
- package/esm/deps/jsr.io/@std/assert/1.0.19/not_strict_equals.d.ts +0 -22
- package/esm/deps/jsr.io/@std/assert/1.0.19/not_strict_equals.js +0 -32
- package/esm/deps/jsr.io/@std/assert/1.0.19/object_match.d.ts +0 -28
- package/esm/deps/jsr.io/@std/assert/1.0.19/object_match.js +0 -177
- package/esm/deps/jsr.io/@std/assert/1.0.19/rejects.d.ts +0 -41
- package/esm/deps/jsr.io/@std/assert/1.0.19/rejects.js +0 -53
- package/esm/deps/jsr.io/@std/assert/1.0.19/strict_equals.d.ts +0 -23
- package/esm/deps/jsr.io/@std/assert/1.0.19/strict_equals.js +0 -58
- package/esm/deps/jsr.io/@std/assert/1.0.19/string_includes.d.ts +0 -17
- package/esm/deps/jsr.io/@std/assert/1.0.19/string_includes.js +0 -26
- package/esm/deps/jsr.io/@std/assert/1.0.19/throws.d.ts +0 -44
- package/esm/deps/jsr.io/@std/assert/1.0.19/throws.js +0 -44
- package/esm/deps/jsr.io/@std/assert/1.0.19/unimplemented.d.ts +0 -14
- package/esm/deps/jsr.io/@std/assert/1.0.19/unimplemented.js +0 -20
- package/esm/deps/jsr.io/@std/assert/1.0.19/unreachable.d.ts +0 -14
- package/esm/deps/jsr.io/@std/assert/1.0.19/unreachable.js +0 -20
- package/esm/deps/jsr.io/@std/async/1.5.0/delay.d.ts +0 -44
- package/esm/deps/jsr.io/@std/async/1.5.0/delay.js +0 -84
- package/esm/deps/jsr.io/@std/crypto/1.1.0/timing_safe_equal.d.ts +0 -39
- package/esm/deps/jsr.io/@std/crypto/1.1.0/timing_safe_equal.js +0 -61
- package/esm/deps/jsr.io/@std/encoding/1.0.11/_common16.d.ts +0 -22
- package/esm/deps/jsr.io/@std/encoding/1.0.11/_common16.js +0 -51
- package/esm/deps/jsr.io/@std/encoding/1.0.11/_common32.d.ts +0 -34
- package/esm/deps/jsr.io/@std/encoding/1.0.11/_common32.js +0 -192
- package/esm/deps/jsr.io/@std/encoding/1.0.11/_common64.d.ts +0 -34
- package/esm/deps/jsr.io/@std/encoding/1.0.11/_common64.js +0 -113
- package/esm/deps/jsr.io/@std/encoding/1.0.11/_common_detach.d.ts +0 -3
- package/esm/deps/jsr.io/@std/encoding/1.0.11/_common_detach.js +0 -13
- package/esm/deps/jsr.io/@std/encoding/1.0.11/_types.d.ts +0 -8
- package/esm/deps/jsr.io/@std/encoding/1.0.11/_types.js +0 -2
- package/esm/deps/jsr.io/@std/encoding/1.0.11/_validate_binary_like.d.ts +0 -1
- package/esm/deps/jsr.io/@std/encoding/1.0.11/_validate_binary_like.js +0 -26
- package/esm/deps/jsr.io/@std/encoding/1.0.11/ascii85.d.ts +0 -60
- package/esm/deps/jsr.io/@std/encoding/1.0.11/ascii85.js +0 -152
- package/esm/deps/jsr.io/@std/encoding/1.0.11/base32.d.ts +0 -39
- package/esm/deps/jsr.io/@std/encoding/1.0.11/base32.js +0 -87
- package/esm/deps/jsr.io/@std/encoding/1.0.11/base58.d.ts +0 -39
- package/esm/deps/jsr.io/@std/encoding/1.0.11/base58.js +0 -131
- package/esm/deps/jsr.io/@std/encoding/1.0.11/base64.d.ts +0 -39
- package/esm/deps/jsr.io/@std/encoding/1.0.11/base64.js +0 -82
- package/esm/deps/jsr.io/@std/encoding/1.0.11/base64url.d.ts +0 -39
- package/esm/deps/jsr.io/@std/encoding/1.0.11/base64url.js +0 -72
- package/esm/deps/jsr.io/@std/encoding/1.0.11/hex.d.ts +0 -38
- package/esm/deps/jsr.io/@std/encoding/1.0.11/hex.js +0 -87
- package/esm/deps/jsr.io/@std/encoding/1.0.11/mod.d.ts +0 -97
- package/esm/deps/jsr.io/@std/encoding/1.0.11/mod.js +0 -99
- package/esm/deps/jsr.io/@std/encoding/1.0.11/varint.d.ts +0 -119
- package/esm/deps/jsr.io/@std/encoding/1.0.11/varint.js +0 -209
- package/esm/deps/jsr.io/@std/http/1.1.3/status.d.ts +0 -343
- package/esm/deps/jsr.io/@std/http/1.1.3/status.js +0 -343
- package/esm/deps/jsr.io/@std/internal/1.0.14/assertion_state.d.ts +0 -159
- package/esm/deps/jsr.io/@std/internal/1.0.14/assertion_state.js +0 -223
- package/esm/deps/jsr.io/@std/internal/1.0.14/build_message.d.ts +0 -79
- package/esm/deps/jsr.io/@std/internal/1.0.14/build_message.js +0 -116
- package/esm/deps/jsr.io/@std/internal/1.0.14/diff.d.ts +0 -139
- package/esm/deps/jsr.io/@std/internal/1.0.14/diff.js +0 -277
- package/esm/deps/jsr.io/@std/internal/1.0.14/diff_str.d.ts +0 -98
- package/esm/deps/jsr.io/@std/internal/1.0.14/diff_str.js +0 -181
- package/esm/deps/jsr.io/@std/internal/1.0.14/format.d.ts +0 -29
- package/esm/deps/jsr.io/@std/internal/1.0.14/format.js +0 -68
- package/esm/deps/jsr.io/@std/internal/1.0.14/styles.d.ts +0 -158
- package/esm/deps/jsr.io/@std/internal/1.0.14/styles.js +0 -206
- package/esm/deps/jsr.io/@std/internal/1.0.14/types.d.ts +0 -24
- package/esm/deps/jsr.io/@std/internal/1.0.14/types.js +0 -3
- package/esm/deps/jsr.io/@std/testing/1.0.20/_test_suite.d.ts +0 -91
- package/esm/deps/jsr.io/@std/testing/1.0.20/_test_suite.js +0 -347
- package/esm/deps/jsr.io/@std/testing/1.0.20/bdd.d.ts +0 -382
- package/esm/deps/jsr.io/@std/testing/1.0.20/bdd.js +0 -1110
- package/esm/deps/jsr.io/@udibo/http-error/0.11.1/mod.d.ts +0 -363
- package/esm/deps/jsr.io/@udibo/http-error/0.11.1/mod.js +0 -616
- package/esm/package.json +0 -3
- /package/{esm → dist}/adapters/hono/bff/cookie-prefix.d.ts +0 -0
- /package/{esm → dist}/adapters/hono/bff/proxy.d.ts +0 -0
- /package/{esm → dist}/client/_http.js +0 -0
- /package/{esm → dist}/client/base.js +0 -0
- /package/{esm → dist}/client/browser-storage.js +0 -0
- /package/{esm → dist}/client/check.d.ts +0 -0
- /package/{esm → dist}/client/events.js +0 -0
- /package/{esm → dist}/client/storage.d.ts +0 -0
- /package/{esm → dist}/client/storage.js +0 -0
- /package/{esm → dist}/identity/captcha.d.ts +0 -0
- /package/{esm → dist}/identity/captcha.js +0 -0
- /package/{esm → dist}/identity/delivery.d.ts +0 -0
- /package/{esm → dist}/identity/delivery.js +0 -0
- /package/{esm → dist}/identity/errors.d.ts +0 -0
- /package/{esm → dist}/identity/errors.js +0 -0
- /package/{esm → dist}/identity/events.js +0 -0
- /package/{esm → dist}/identity/external/_token-exchange.d.ts +0 -0
- /package/{esm → dist}/identity/external/_token-exchange.js +0 -0
- /package/{esm → dist}/identity/external/errors.d.ts +0 -0
- /package/{esm → dist}/identity/external/errors.js +0 -0
- /package/{esm → dist}/identity/external/provider.d.ts +0 -0
- /package/{esm → dist}/identity/external/provider.js +0 -0
- /package/{esm → dist}/identity/identifier.d.ts +0 -0
- /package/{esm → dist}/identity/identifier.js +0 -0
- /package/{esm → dist}/identity/lockout.d.ts +0 -0
- /package/{esm → dist}/identity/mfa/recovery-codes.d.ts +0 -0
- /package/{esm → dist}/identity/mfa/recovery-codes.js +0 -0
- /package/{esm → dist}/identity/password-policy.d.ts +0 -0
- /package/{esm → dist}/identity/password-policy.js +0 -0
- /package/{esm → dist}/identity/password.d.ts +0 -0
- /package/{esm → dist}/identity/rate-limit.js +0 -0
- /package/{esm → dist}/identity/session.d.ts +0 -0
- /package/{esm → dist}/identity/token-flow.d.ts +0 -0
- /package/{esm → dist}/models/authentication.d.ts +0 -0
- /package/{esm → dist}/models/authentication.js +0 -0
- /package/{esm → dist}/models/authorization-code.js +0 -0
- /package/{esm → dist}/models/client.d.ts +0 -0
- /package/{esm → dist}/models/client.js +0 -0
- /package/{esm → dist}/models/device-authorization.js +0 -0
- /package/{esm → dist}/models/responses.d.ts +0 -0
- /package/{esm → dist}/models/responses.js +0 -0
- /package/{esm → dist}/models/scope.d.ts +0 -0
- /package/{esm → dist}/models/scope.js +0 -0
- /package/{esm → dist}/models/token.js +0 -0
- /package/{esm → dist}/react/components/types.js +0 -0
- /package/{esm → dist}/react/context.js +0 -0
- /package/{esm → dist}/react/provider.js +0 -0
- /package/{esm → dist}/react/require-auth.d.ts +0 -0
- /package/{esm → dist}/react/use-authorization.js +0 -0
- /package/{esm → dist}/server/_clock-skew.d.ts +0 -0
- /package/{esm → dist}/server/client-authentication.js +0 -0
- /package/{esm → dist}/server/grants/client-credentials.js +0 -0
- /package/{esm → dist}/server/grants/password.js +0 -0
- /package/{esm → dist}/server/redirect-uri.d.ts +0 -0
- /package/{esm → dist}/server/services/authorization-code.js +0 -0
- /package/{esm → dist}/server/services/client.js +0 -0
- /package/{esm → dist}/server/services/device-authorization.js +0 -0
- /package/{esm → dist}/server/services/user.js +0 -0
- /package/{esm → dist}/server/utils/hash.d.ts +0 -0
- /package/{esm → dist}/testing/contract/_race.d.ts +0 -0
- /package/{esm → dist}/testing/contract/_race.js +0 -0
- /package/{esm → dist}/testing/contract/tenant.d.ts +0 -0
- /package/{esm → dist}/utils/_body.d.ts +0 -0
- /package/{esm → dist}/utils/_body.js +0 -0
- /package/{esm → dist}/utils/_buffer.d.ts +0 -0
- /package/{esm → dist}/utils/_buffer.js +0 -0
- /package/{esm → dist}/utils/_default-fetch.d.ts +0 -0
- /package/{esm → dist}/utils/_timing-safe.d.ts +0 -0
- /package/{esm → dist}/utils/_timing-safe.js +0 -0
- /package/{esm → dist}/utils/authentication-context.js +0 -0
- /package/{esm → dist}/utils/basic-auth.d.ts +0 -0
- /package/{esm → dist}/utils/basic-auth.js +0 -0
- /package/{esm → dist}/utils/pkce.d.ts +0 -0
- /package/{esm → dist}/utils/text.d.ts +0 -0
package/README.md
CHANGED
|
@@ -16,7 +16,7 @@ run locally without a hosted account.
|
|
|
16
16
|
| Udibo to handle sign-in | [Use Udibo's identity service](docs/guides/use-udibo.md) — requires a Udibo account |
|
|
17
17
|
| Its own login and authorization server | [Run the quickstart](docs/quickstart.md), then [host authorization for your app](docs/guides/become-an-oauth-provider.md) |
|
|
18
18
|
| An API that accepts access tokens | [Protect an API](docs/guides/protect-an-api.md) |
|
|
19
|
-
| A React application with server-held tokens | [
|
|
19
|
+
| A React application with server-held tokens | [React Router starter](templates/react-router/README.md) |
|
|
20
20
|
|
|
21
21
|
[Documentation index](docs/index.md) ·
|
|
22
22
|
[API reference](https://jsr.io/@udibo/oauth2/doc) · [Examples](#examples) ·
|
|
@@ -24,12 +24,29 @@ run locally without a hosted account.
|
|
|
24
24
|
|
|
25
25
|
## Install
|
|
26
26
|
|
|
27
|
-
|
|
27
|
+
The package supports Node.js 22 and later and ships ESM with type declarations.
|
|
28
|
+
Install it from npm:
|
|
28
29
|
|
|
29
30
|
```sh
|
|
31
|
+
npm install @udibo/oauth2
|
|
32
|
+
# or
|
|
33
|
+
pnpm add @udibo/oauth2
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
It is also published to [JSR](https://jsr.io/@udibo/oauth2) as TypeScript
|
|
37
|
+
source:
|
|
38
|
+
|
|
39
|
+
```sh
|
|
40
|
+
npx jsr add @udibo/oauth2
|
|
41
|
+
# or, with Deno
|
|
30
42
|
deno add jsr:@udibo/oauth2
|
|
31
43
|
```
|
|
32
44
|
|
|
45
|
+
`hono`, `react`, and `react-dom` are optional peer dependencies. Install the
|
|
46
|
+
ones for the entrypoints you import: `hono` for the `/hono/*` adapters, `react`
|
|
47
|
+
and `react-dom` for `/react` and `/react/components`. `vitest` is an optional
|
|
48
|
+
peer dependency of the testing helpers.
|
|
49
|
+
|
|
33
50
|
Import the part you use; there is no root barrel or default export:
|
|
34
51
|
|
|
35
52
|
```ts
|
|
@@ -83,11 +100,12 @@ package does not include a challenge provider; see the
|
|
|
83
100
|
|
|
84
101
|
## Examples
|
|
85
102
|
|
|
86
|
-
From a checkout of this repository:
|
|
103
|
+
From a checkout of this repository, with Node.js 24.2 or later and pnpm:
|
|
87
104
|
|
|
88
105
|
```sh
|
|
89
|
-
|
|
90
|
-
|
|
106
|
+
pnpm install
|
|
107
|
+
pnpm build
|
|
108
|
+
pnpm --filter example-app-with-own-auth start
|
|
91
109
|
```
|
|
92
110
|
|
|
93
111
|
Open <http://localhost:8001/> and sign in as `user` / `password`. The
|
|
@@ -95,13 +113,11 @@ Open <http://localhost:8001/> and sign in as `user` / `password`. The
|
|
|
95
113
|
All demo credentials, in-memory stores, and local HTTP settings are for
|
|
96
114
|
development.
|
|
97
115
|
|
|
98
|
-
| Example
|
|
99
|
-
|
|
|
100
|
-
| [Hono with own auth](examples/hono/app-with-own-auth/README.md)
|
|
101
|
-
| [Hono with external auth](examples/hono/app-with-external-auth/README.md)
|
|
102
|
-
| [Standalone API](examples/hono/api-service/README.md)
|
|
103
|
-
| [Juniper with own auth](examples/juniper/app-with-own-auth/README.md) | Server-rendered React with application-owned login |
|
|
104
|
-
| [Juniper with external auth](examples/juniper/app-with-external-auth/README.md) | Server-rendered React with delegated sign-in |
|
|
116
|
+
| Example | Demonstrates |
|
|
117
|
+
| ------------------------------------------------------------------------- | --------------------------------------------------------------- |
|
|
118
|
+
| [Hono with own auth](examples/hono/app-with-own-auth/README.md) | App login, OAuth2 server, BFF, and protected API in one process |
|
|
119
|
+
| [Hono with external auth](examples/hono/app-with-external-auth/README.md) | Delegated sign-in, token introspection, and a BFF proxy |
|
|
120
|
+
| [Standalone API](examples/hono/api-service/README.md) | Bearer-token validation without a frontend |
|
|
105
121
|
|
|
106
122
|
## Package entrypoints
|
|
107
123
|
|
|
@@ -128,7 +144,6 @@ and examples in the [reference](https://jsr.io/@udibo/oauth2/doc).
|
|
|
128
144
|
| `/react/components` | Optional forms for login, signup, password reset, and MFA |
|
|
129
145
|
| `/crypto` | Random tokens, hashing, encoding, authenticated encryption |
|
|
130
146
|
| `/url` | Safe return paths and login continuation |
|
|
131
|
-
| `/cli` | Local test identity provider and OIDC signing-key generation |
|
|
132
147
|
| `/testing` | In-memory fixtures and authorization-server test helpers |
|
|
133
148
|
| `/testing/contract` | Tests for app-owned service and storage implementations |
|
|
134
149
|
| `/hono/bff/testing` | BFF session fixtures and session-store contract tests |
|
|
@@ -136,17 +151,23 @@ and examples in the [reference](https://jsr.io/@udibo/oauth2/doc).
|
|
|
136
151
|
|
|
137
152
|
## Runtime support
|
|
138
153
|
|
|
139
|
-
The library uses Web APIs
|
|
140
|
-
|
|
141
|
-
|
|
154
|
+
The library uses Web APIs and runs on Node.js 22 and later. CI runs the
|
|
155
|
+
complete suite on Node 22, 24, and 26 on Linux, and on Node 26 on Windows and
|
|
156
|
+
macOS. It also packs the npm tarball, installs it into an empty project, type
|
|
157
|
+
checks a consumer of every entrypoint, and imports each one on Node.
|
|
158
|
+
|
|
159
|
+
| Surface | Node 22+ | Browser | Deno, Bun |
|
|
160
|
+
| ---------------------------------------------------------------------- | --------------------- | ------------------------------------------- | ------------- |
|
|
161
|
+
| `/client`, `/react`, `/react/components` | Tested, including SSR | Intended for client code; no secrets | Not verified |
|
|
162
|
+
| `/server/*`, `/identity/*`, `/hono/*`, `/crypto`, `/url` | Tested | Server functionality belongs on the backend | Not verified |
|
|
163
|
+
| `/testing`, `/testing/contract`, `/hono/bff/testing`, `/react/testing` | Tested; need Vitest | Not supported | Not verified |
|
|
164
|
+
| `udibo-oauth2` command (`bin`) | Tested | Not supported | Not supported |
|
|
142
165
|
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
| `/testing`, `/testing/contract` | Tested | Not verified | Not supported | Not verified |
|
|
149
|
-
| `/cli` | Deno only | Not supported | Not supported | Not supported |
|
|
166
|
+
The `udibo-oauth2` command is a development tool: `udibo-oauth2 oidc keygen`
|
|
167
|
+
prints an OIDC signing key, and `udibo-oauth2 idp dev` runs a local identity
|
|
168
|
+
provider. Run it with `npx udibo-oauth2` once the package is installed; the
|
|
169
|
+
[local identity provider guide](docs/guides/run-a-local-identity-provider.md)
|
|
170
|
+
covers its options. Nothing on the library path imports it.
|
|
150
171
|
|
|
151
172
|
See [stability](docs/stability.md#runtime-support) for the support boundary.
|
|
152
173
|
|
|
@@ -173,7 +194,7 @@ implementing a custom store or callback.
|
|
|
173
194
|
|
|
174
195
|
## Contributing and security
|
|
175
196
|
|
|
176
|
-
Run `
|
|
197
|
+
Run `pnpm check` and `pnpm test` before proposing changes. See
|
|
177
198
|
[CONTRIBUTING.md](CONTRIBUTING.md) for development conventions,
|
|
178
199
|
[SECURITY.md](SECURITY.md) for private vulnerability reports, and
|
|
179
200
|
[CHANGELOG.md](CHANGELOG.md) for release history.
|
|
@@ -8,11 +8,11 @@
|
|
|
8
8
|
* @module
|
|
9
9
|
*/
|
|
10
10
|
import type { Context, MiddlewareHandler } from "hono";
|
|
11
|
-
import type { ClientInterface } from "../../models/client.
|
|
12
|
-
import type { RequireConditions } from "../../models/authorization.
|
|
13
|
-
import type { AbstractScope, BasicScope } from "../../models/scope.
|
|
14
|
-
import type { AuthenticatedContext } from "../../server/resource-server.
|
|
15
|
-
import { ResourceServer } from "../../server/resource-server.
|
|
11
|
+
import type { ClientInterface } from "../../models/client.ts";
|
|
12
|
+
import type { RequireConditions } from "../../models/authorization.ts";
|
|
13
|
+
import type { AbstractScope, BasicScope } from "../../models/scope.ts";
|
|
14
|
+
import type { AuthenticatedContext } from "../../server/resource-server.ts";
|
|
15
|
+
import { ResourceServer } from "../../server/resource-server.ts";
|
|
16
16
|
/**
|
|
17
17
|
* Key under which the authenticated OAuth2 context is stored on the Hono
|
|
18
18
|
* context. Namespaced to avoid collisions with other middleware.
|
|
@@ -79,7 +79,7 @@ export function authenticateHonoRequest(server, c, requiredScope) {
|
|
|
79
79
|
}
|
|
80
80
|
// Base method on purpose: the Hono subclasses' override would recurse.
|
|
81
81
|
function baseAuthenticate(server, request, requiredScope) {
|
|
82
|
-
//
|
|
82
|
+
// oxlint-disable-next-line typescript/no-explicit-any
|
|
83
83
|
const base = ResourceServer.prototype;
|
|
84
84
|
return base.authenticate.call(server, request, requiredScope);
|
|
85
85
|
}
|
|
@@ -32,15 +32,14 @@
|
|
|
32
32
|
*
|
|
33
33
|
* @module
|
|
34
34
|
*/
|
|
35
|
-
import "../../_dnt.polyfills.js";
|
|
36
35
|
import { Hono } from "hono";
|
|
37
36
|
import type { Context, Handler, MiddlewareHandler } from "hono";
|
|
38
|
-
import type { RequireConditions } from "../../models/authorization.
|
|
39
|
-
import type { AuthenticationContext } from "../../models/authentication.
|
|
40
|
-
import type { ClientInterface } from "../../models/client.
|
|
41
|
-
import type { AbstractScope, BasicScope } from "../../models/scope.
|
|
42
|
-
import { AuthorizationServer, type AuthorizationServerOptions } from "../../server/authorization-server.
|
|
43
|
-
import type { AuthenticatedContext } from "../../server/resource-server.
|
|
37
|
+
import type { RequireConditions } from "../../models/authorization.ts";
|
|
38
|
+
import type { AuthenticationContext } from "../../models/authentication.ts";
|
|
39
|
+
import type { ClientInterface } from "../../models/client.ts";
|
|
40
|
+
import type { AbstractScope, BasicScope } from "../../models/scope.ts";
|
|
41
|
+
import { AuthorizationServer, type AuthorizationServerOptions } from "../../server/authorization-server.ts";
|
|
42
|
+
import type { AuthenticatedContext } from "../../server/resource-server.ts";
|
|
44
43
|
/**
|
|
45
44
|
* Authenticates the resource owner during an authorization request.
|
|
46
45
|
*
|
|
@@ -32,7 +32,6 @@
|
|
|
32
32
|
*
|
|
33
33
|
* @module
|
|
34
34
|
*/
|
|
35
|
-
import "../../_dnt.polyfills.js";
|
|
36
35
|
import { Hono } from "hono";
|
|
37
36
|
import { AuthorizationServer, ENDPOINT_METHODS, ENDPOINT_PATHS, } from "../../server/authorization-server.js";
|
|
38
37
|
import { authenticateHonoRequest, createProtectMiddleware, createRequireMiddleware, createRequireScopeMiddleware, readContext, } from "./_common.js";
|
|
@@ -27,7 +27,7 @@
|
|
|
27
27
|
* @module
|
|
28
28
|
*/
|
|
29
29
|
import type { Context } from "hono";
|
|
30
|
-
import type { AuthRequestStorage } from "../../../client/mod.
|
|
30
|
+
import type { AuthRequestStorage } from "../../../client/mod.ts";
|
|
31
31
|
/**
|
|
32
32
|
* Cookie attributes for the pending-authorization cookie.
|
|
33
33
|
*
|
|
@@ -161,7 +161,7 @@ export declare class EncryptedCookieAuthRequestStorage implements AuthRequestSto
|
|
|
161
161
|
* import { encryptedCookieAuthRequestStorage } from "@udibo/oauth2/hono/bff";
|
|
162
162
|
*
|
|
163
163
|
* const authRequestStorage = encryptedCookieAuthRequestStorage({
|
|
164
|
-
* secret:
|
|
164
|
+
* secret: process.env.SESSION_SECRET!,
|
|
165
165
|
* });
|
|
166
166
|
* ```
|
|
167
167
|
*/
|
|
@@ -96,7 +96,7 @@ export class EncryptedCookieAuthRequestStorage {
|
|
|
96
96
|
this.#maxPending = options.maxPending ?? DEFAULT_MAX_PENDING;
|
|
97
97
|
}
|
|
98
98
|
#key() {
|
|
99
|
-
return this.#keyPromise ??= deriveAesKey(this.#secret);
|
|
99
|
+
return (this.#keyPromise ??= deriveAesKey(this.#secret));
|
|
100
100
|
}
|
|
101
101
|
async #read(c) {
|
|
102
102
|
const cookieValue = getCookie(c, this.#name);
|
|
@@ -149,7 +149,7 @@ export class EncryptedCookieAuthRequestStorage {
|
|
|
149
149
|
* import { encryptedCookieAuthRequestStorage } from "@udibo/oauth2/hono/bff";
|
|
150
150
|
*
|
|
151
151
|
* const authRequestStorage = encryptedCookieAuthRequestStorage({
|
|
152
|
-
* secret:
|
|
152
|
+
* secret: process.env.SESSION_SECRET!,
|
|
153
153
|
* });
|
|
154
154
|
* ```
|
|
155
155
|
*/
|
|
@@ -49,14 +49,14 @@
|
|
|
49
49
|
*/
|
|
50
50
|
import { Hono } from "hono";
|
|
51
51
|
import type { Context, Handler, MiddlewareHandler } from "hono";
|
|
52
|
-
import type { DirectClient, SessionState, TokenBundle, UserInfoClaims } from "../../../client/mod.
|
|
53
|
-
import type { ClientInterface } from "../../../models/client.
|
|
54
|
-
import type { AbstractScope, BasicScope } from "../../../models/scope.
|
|
55
|
-
import type { HonoAuthorizationServer } from "../authorization-server.
|
|
56
|
-
import type { HonoResourceServer } from "../resource-server.
|
|
57
|
-
import type { AuthRequestStorageFactory } from "./auth-request-store.
|
|
58
|
-
import { type SessionStore } from "./session-store.
|
|
59
|
-
import { type HonoBffProxyOptions } from "./proxy.
|
|
52
|
+
import type { DirectClient, SessionState, TokenBundle, UserInfoClaims } from "../../../client/mod.ts";
|
|
53
|
+
import type { ClientInterface } from "../../../models/client.ts";
|
|
54
|
+
import type { AbstractScope, BasicScope } from "../../../models/scope.ts";
|
|
55
|
+
import type { HonoAuthorizationServer } from "../authorization-server.ts";
|
|
56
|
+
import type { HonoResourceServer } from "../resource-server.ts";
|
|
57
|
+
import type { AuthRequestStorageFactory } from "./auth-request-store.ts";
|
|
58
|
+
import { type SessionStore } from "./session-store.ts";
|
|
59
|
+
import { type HonoBffProxyOptions } from "./proxy.ts";
|
|
60
60
|
/**
|
|
61
61
|
* A resource server the BFF can compose with `attachToken()` to expose a
|
|
62
62
|
* single `bff.protect()` middleware.
|
|
@@ -374,10 +374,20 @@ export interface HonoBffOptions {
|
|
|
374
374
|
* Who owns the BFF's session record. Defaults to `"own"`.
|
|
375
375
|
*
|
|
376
376
|
* - `"own"` (default): the BFF creates and owns its session at
|
|
377
|
-
* `/auth/callback` — it always mints a fresh id (`sessionStore.create`)
|
|
378
|
-
*
|
|
379
|
-
*
|
|
380
|
-
*
|
|
377
|
+
* `/auth/callback` — it always mints a fresh id (`sessionStore.create`).
|
|
378
|
+
* A session the inbound cookie names is replaced: once the code exchange
|
|
379
|
+
* and `resolveUser` succeed, the BFF destroys it (`sessionStore.destroy`)
|
|
380
|
+
* before creating the new one, so signing in again in the same browser —
|
|
381
|
+
* switching organization, a step-up — never leaves the earlier session
|
|
382
|
+
* readable beside the new one. Its refresh token is not revoked: an
|
|
383
|
+
* authorization server may extend a revocation to other tokens of the
|
|
384
|
+
* same grant or sign-in (RFC 7009 §2.1), the new ones included.
|
|
385
|
+
* A callback the authorization server refuses, or whose state check,
|
|
386
|
+
* code exchange or `resolveUser` fails, leaves the existing session as
|
|
387
|
+
* it was; a store failure while creating the replacement leaves the
|
|
388
|
+
* browser signed out. Use when the app has no session here until the
|
|
389
|
+
* OAuth flow completes: standalone BFFs, or apps whose login lives on a
|
|
390
|
+
* separate / external IDP.
|
|
381
391
|
* - `"shared"`: the app already created the session at its own login step,
|
|
382
392
|
* and the BFF **attaches** tokens to that existing session at
|
|
383
393
|
* `/auth/callback` (via `sessionStore.update`) instead of creating its
|
|
@@ -84,8 +84,7 @@ function resolvePaths(paths = {}, options) {
|
|
|
84
84
|
};
|
|
85
85
|
if (basePath === "")
|
|
86
86
|
return resolved;
|
|
87
|
-
const stray = BFF_PATH_KEYS
|
|
88
|
-
.filter((key) => key !== "backchannel" || options.backchannelMounted)
|
|
87
|
+
const stray = BFF_PATH_KEYS.filter((key) => key !== "backchannel" || options.backchannelMounted)
|
|
89
88
|
.filter((key) => !resolved[key].startsWith(`${basePath}/`))
|
|
90
89
|
.map((key) => `${key} ("${resolved[key]}")`);
|
|
91
90
|
if (stray.length > 0) {
|
|
@@ -325,8 +324,8 @@ export class HonoBff {
|
|
|
325
324
|
});
|
|
326
325
|
this.#cookieName = sessionCookieName(options.cookie);
|
|
327
326
|
this.#loginStateCookieName = loginStateCookieName(options.cookie);
|
|
328
|
-
this.#loginStateTtlMs =
|
|
329
|
-
DEFAULT_LOGIN_STATE_TTL_MS;
|
|
327
|
+
this.#loginStateTtlMs =
|
|
328
|
+
options.loginStateTtlMs ?? DEFAULT_LOGIN_STATE_TTL_MS;
|
|
330
329
|
this.#sessionMode = options.sessionMode ?? "own";
|
|
331
330
|
this.#csrf = resolveCsrf(options.csrf);
|
|
332
331
|
this.#extraAuthorizeParams = resolveExtraAuthorizeParams(options);
|
|
@@ -334,16 +333,17 @@ export class HonoBff {
|
|
|
334
333
|
this.#sessionMaxAgeMs = sessionMaxAgeMs;
|
|
335
334
|
if (this.#sessionMode === "shared") {
|
|
336
335
|
const maxAge = options.cookie?.maxAge;
|
|
337
|
-
this.#cookieMaxAgeSeconds =
|
|
338
|
-
|
|
339
|
-
|
|
336
|
+
this.#cookieMaxAgeSeconds =
|
|
337
|
+
maxAge === undefined || maxAge === "session"
|
|
338
|
+
? undefined
|
|
339
|
+
: positiveSeconds(maxAge, "cookie.maxAge");
|
|
340
340
|
}
|
|
341
341
|
else {
|
|
342
|
-
const configuredMaxAge = options.cookie?.maxAge ??
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
|
|
346
|
-
|
|
342
|
+
const configuredMaxAge = options.cookie?.maxAge ?? Math.ceil(sessionMaxAgeMs / 1000);
|
|
343
|
+
this.#cookieMaxAgeSeconds =
|
|
344
|
+
configuredMaxAge === "session"
|
|
345
|
+
? undefined
|
|
346
|
+
: positiveSeconds(configuredMaxAge, "cookie.maxAge");
|
|
347
347
|
if (this.#cookieMaxAgeSeconds !== undefined) {
|
|
348
348
|
const storeMaxAgeMs = sessionStoreMaxAgeMs(this.#store);
|
|
349
349
|
const sessionSeconds = Math.ceil(Math.max(sessionMaxAgeMs, storeMaxAgeMs ?? 0) / 1000);
|
|
@@ -611,7 +611,10 @@ export class HonoBff {
|
|
|
611
611
|
const params = new URL(c.req.url).searchParams;
|
|
612
612
|
const fail = (error) => this.#options.onCallbackError
|
|
613
613
|
? this.#options.onCallbackError(c, error)
|
|
614
|
-
: c.json({
|
|
614
|
+
: c.json({
|
|
615
|
+
error: error.error,
|
|
616
|
+
error_description: error.error_description,
|
|
617
|
+
}, 400);
|
|
615
618
|
if (params.get("error")) {
|
|
616
619
|
return await fail({
|
|
617
620
|
error: params.get("error"),
|
|
@@ -637,8 +640,7 @@ export class HonoBff {
|
|
|
637
640
|
this.#writeLoginStateHashes(c, pendingStates.filter((_, index) => index !== matched));
|
|
638
641
|
try {
|
|
639
642
|
const origin = this.#options.resolveOrigin?.(c);
|
|
640
|
-
const { tokens, refreshToken, returnTo, raw } = await this.#client
|
|
641
|
-
.exchangeAuthorizationCode(code, state, {
|
|
643
|
+
const { tokens, refreshToken, returnTo, raw } = await this.#client.exchangeAuthorizationCode(code, state, {
|
|
642
644
|
origin,
|
|
643
645
|
redirectUri: this.#derivedRedirectUri(c, origin),
|
|
644
646
|
authRequestStorage: this.#options.authRequestStorage?.forRequest(c),
|
|
@@ -670,9 +672,10 @@ export class HonoBff {
|
|
|
670
672
|
createdAt: now,
|
|
671
673
|
updatedAt: now,
|
|
672
674
|
};
|
|
673
|
-
const
|
|
674
|
-
|
|
675
|
-
|
|
675
|
+
const inbound = getCookie(c, this.#cookieName);
|
|
676
|
+
const existing = this.#sessionMode === "shared" ? inbound : undefined;
|
|
677
|
+
if (inbound && !existing)
|
|
678
|
+
await this.#store.destroy(inbound);
|
|
676
679
|
const cookieValue = existing
|
|
677
680
|
? await this.#store.update(existing, data)
|
|
678
681
|
: await this.#store.create(data);
|
|
@@ -723,8 +726,7 @@ export class HonoBff {
|
|
|
723
726
|
if (this.#options.rpInitiatedLogout) {
|
|
724
727
|
const endSession = this.#client.endSessionEndpoint;
|
|
725
728
|
if (endSession) {
|
|
726
|
-
const origin = this.#options.resolveOrigin?.(c) ??
|
|
727
|
-
new URL(c.req.url).origin;
|
|
729
|
+
const origin = this.#options.resolveOrigin?.(c) ?? new URL(c.req.url).origin;
|
|
728
730
|
const url = new URL(endSession, origin);
|
|
729
731
|
if (idToken)
|
|
730
732
|
url.searchParams.set("id_token_hint", idToken);
|
|
@@ -879,7 +881,8 @@ export class HonoBff {
|
|
|
879
881
|
catch {
|
|
880
882
|
subject = null;
|
|
881
883
|
}
|
|
882
|
-
if (!subject ||
|
|
884
|
+
if (!subject ||
|
|
885
|
+
(subject.sub === undefined && subject.sid === undefined)) {
|
|
883
886
|
return c.json({
|
|
884
887
|
error: "invalid_request",
|
|
885
888
|
error_description: "invalid logout_token",
|
|
@@ -1088,7 +1091,9 @@ export class HonoBff {
|
|
|
1088
1091
|
try {
|
|
1089
1092
|
const inboundAuth = c.req.header("Authorization") ?? "";
|
|
1090
1093
|
const hasBearer = /^bearer\s+\S/i.test(inboundAuth);
|
|
1091
|
-
if (!hasBearer &&
|
|
1094
|
+
if (!hasBearer &&
|
|
1095
|
+
this.#csrf &&
|
|
1096
|
+
this.#hasSessionCookie(c) &&
|
|
1092
1097
|
!this.#csrfHeaderOk(c)) {
|
|
1093
1098
|
return this.#csrfReject(c);
|
|
1094
1099
|
}
|
|
@@ -1202,7 +1207,7 @@ export class HonoBff {
|
|
|
1202
1207
|
const retryOn401 = options.retryOn401 ?? true;
|
|
1203
1208
|
const mountPrefix = (options.stripPrefix ?? "").endsWith("/")
|
|
1204
1209
|
? options.stripPrefix.slice(0, -1)
|
|
1205
|
-
: options.stripPrefix ?? "";
|
|
1210
|
+
: (options.stripPrefix ?? "");
|
|
1206
1211
|
return async (c) => {
|
|
1207
1212
|
if (this.#csrf && this.#hasSessionCookie(c) && !this.#csrfHeaderOk(c)) {
|
|
1208
1213
|
return this.#csrfReject(c);
|
|
@@ -1243,8 +1248,7 @@ export class HonoBff {
|
|
|
1243
1248
|
cause,
|
|
1244
1249
|
}));
|
|
1245
1250
|
}
|
|
1246
|
-
const canRetry = retryOn401 && body === null &&
|
|
1247
|
-
entry.data.refreshToken !== undefined;
|
|
1251
|
+
const canRetry = retryOn401 && body === null && entry.data.refreshToken !== undefined;
|
|
1248
1252
|
if (canRetry && isInvalidTokenChallenge(response)) {
|
|
1249
1253
|
await response.body?.cancel();
|
|
1250
1254
|
const outcome = await this.#refreshSessionEntry(c, entry);
|
|
@@ -1272,10 +1276,12 @@ export class HonoBff {
|
|
|
1272
1276
|
mountPrefix,
|
|
1273
1277
|
}),
|
|
1274
1278
|
};
|
|
1275
|
-
return downstream === null
|
|
1276
|
-
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
+
return downstream === null
|
|
1280
|
+
? c.body(null, init)
|
|
1281
|
+
: c.body(downstream, {
|
|
1282
|
+
...init,
|
|
1283
|
+
status: response.status,
|
|
1284
|
+
});
|
|
1279
1285
|
};
|
|
1280
1286
|
}
|
|
1281
1287
|
}
|
|
@@ -79,7 +79,6 @@ export function resolveCookieName(resolution) {
|
|
|
79
79
|
assertCookiePrefixSatisfiable(name, attributes, consequence);
|
|
80
80
|
return name;
|
|
81
81
|
}
|
|
82
|
-
const hostPrefixOk = attributes.secure && attributes.path === "/" &&
|
|
83
|
-
!attributes.domain;
|
|
82
|
+
const hostPrefixOk = attributes.secure && attributes.path === "/" && !attributes.domain;
|
|
84
83
|
return hostPrefixOk ? `__Host-${base}` : base;
|
|
85
84
|
}
|
|
@@ -6,14 +6,13 @@
|
|
|
6
6
|
* {@link SessionStore} contract and two ready-to-use implementations
|
|
7
7
|
* ({@link MemorySessionStore}, {@link EncryptedCookieSessionStore}).
|
|
8
8
|
*
|
|
9
|
-
* Need a server-side store (Postgres, Redis,
|
|
9
|
+
* Need a server-side store (Postgres, Redis, …)? Implement the
|
|
10
10
|
* {@link SessionStore} interface and verify it with
|
|
11
11
|
* `runSessionStoreContractTests` from `@udibo/oauth2/hono/bff/testing`.
|
|
12
12
|
*
|
|
13
13
|
* @module
|
|
14
14
|
*/
|
|
15
|
-
|
|
16
|
-
export { type
|
|
17
|
-
export {
|
|
18
|
-
export {
|
|
19
|
-
export { type BackchannelLogoutStore, type BoundedSessionStore, DEFAULT_SESSION_MAX_AGE_MS, EncryptedCookieSessionStore, type EncryptedCookieSessionStoreOptions, MemorySessionStore, type SessionData, type SessionStore, sessionStoreMaxAgeMs, supportsBackchannelLogout, } from "./session-store.js";
|
|
15
|
+
export { type BackchannelLogoutSubject, type BffCallbackError, HonoBff, type HonoBffBackchannelOptions, type HonoBffCookieOptions, type HonoBffCsrfOptions, type HonoBffOptions, type HonoBffPaths, type HonoBffResourceServer, } from "./bff.ts";
|
|
16
|
+
export { type AuthRequestCookieOptions, type AuthRequestStorageFactory, EncryptedCookieAuthRequestStorage, encryptedCookieAuthRequestStorage, type EncryptedCookieAuthRequestStorageOptions, } from "./auth-request-store.ts";
|
|
17
|
+
export { DEFAULT_PROXY_FORWARD_HEADERS, type HonoBffProxyOptions, } from "./proxy.ts";
|
|
18
|
+
export { type BackchannelLogoutStore, type BoundedSessionStore, DEFAULT_SESSION_MAX_AGE_MS, EncryptedCookieSessionStore, type EncryptedCookieSessionStoreOptions, MemorySessionStore, type SessionData, type SessionStore, sessionStoreMaxAgeMs, supportsBackchannelLogout, } from "./session-store.ts";
|
|
@@ -6,13 +6,12 @@
|
|
|
6
6
|
* {@link SessionStore} contract and two ready-to-use implementations
|
|
7
7
|
* ({@link MemorySessionStore}, {@link EncryptedCookieSessionStore}).
|
|
8
8
|
*
|
|
9
|
-
* Need a server-side store (Postgres, Redis,
|
|
9
|
+
* Need a server-side store (Postgres, Redis, …)? Implement the
|
|
10
10
|
* {@link SessionStore} interface and verify it with
|
|
11
11
|
* `runSessionStoreContractTests` from `@udibo/oauth2/hono/bff/testing`.
|
|
12
12
|
*
|
|
13
13
|
* @module
|
|
14
14
|
*/
|
|
15
|
-
import "../../../_dnt.polyfills.js";
|
|
16
15
|
export { HonoBff, } from "./bff.js";
|
|
17
16
|
export { EncryptedCookieAuthRequestStorage, encryptedCookieAuthRequestStorage, } from "./auth-request-store.js";
|
|
18
17
|
export { DEFAULT_PROXY_FORWARD_HEADERS, } from "./proxy.js";
|
|
@@ -151,7 +151,8 @@ function forcePrivateCache(headers) {
|
|
|
151
151
|
const directives = existing
|
|
152
152
|
.split(",")
|
|
153
153
|
.map((directive) => directive.trim().toLowerCase());
|
|
154
|
-
if (directives.some((directive) => directive === "private" ||
|
|
154
|
+
if (directives.some((directive) => directive === "private" ||
|
|
155
|
+
directive === "no-store" ||
|
|
155
156
|
directive.startsWith("private="))) {
|
|
156
157
|
return;
|
|
157
158
|
}
|
|
@@ -23,7 +23,7 @@
|
|
|
23
23
|
*
|
|
24
24
|
* @module
|
|
25
25
|
*/
|
|
26
|
-
import type { TokenBundle, UserInfoClaims } from "../../../client/mod.
|
|
26
|
+
import type { TokenBundle, UserInfoClaims } from "../../../client/mod.ts";
|
|
27
27
|
/** The data a BFF persists per session. */
|
|
28
28
|
export interface SessionData {
|
|
29
29
|
/** The current token bundle (access token + expiry + scope + id_token). */
|
|
@@ -211,7 +211,7 @@ export interface EncryptedCookieSessionStoreOptions {
|
|
|
211
211
|
* // Deploy with the new secret first, the old one second: new cookies seal
|
|
212
212
|
* // under NEW, cookies still sealed under OLD keep unsealing until you drop it.
|
|
213
213
|
* const store = new EncryptedCookieSessionStore({
|
|
214
|
-
* secret: [
|
|
214
|
+
* secret: [process.env.SESSION_SECRET!, process.env.SESSION_SECRET_OLD!],
|
|
215
215
|
* maxAgeMs: 7 * 24 * 60 * 60 * 1000,
|
|
216
216
|
* });
|
|
217
217
|
* ```
|
|
@@ -27,8 +27,8 @@ import { InvalidGrantError } from "../../../errors.js";
|
|
|
27
27
|
import { deriveAesKey, sealJson, unsealJson } from "../../../utils/crypto.js";
|
|
28
28
|
/** Whether a store implements the {@link BackchannelLogoutStore} capability. */
|
|
29
29
|
export function supportsBackchannelLogout(store) {
|
|
30
|
-
return typeof store.destroyByLogout ===
|
|
31
|
-
"function";
|
|
30
|
+
return (typeof store.destroyByLogout ===
|
|
31
|
+
"function");
|
|
32
32
|
}
|
|
33
33
|
/**
|
|
34
34
|
* Default session lifetime — 14 days — shared by
|
|
@@ -102,10 +102,11 @@ export class MemorySessionStore {
|
|
|
102
102
|
}
|
|
103
103
|
}
|
|
104
104
|
function isSealedSession(value) {
|
|
105
|
-
return typeof value === "object" &&
|
|
105
|
+
return (typeof value === "object" &&
|
|
106
|
+
value !== null &&
|
|
106
107
|
typeof value.issuedAt === "number" &&
|
|
107
108
|
typeof value.data === "object" &&
|
|
108
|
-
value.data !== null;
|
|
109
|
+
value.data !== null);
|
|
109
110
|
}
|
|
110
111
|
/**
|
|
111
112
|
* Stateless session store. The cookie value is the AES-GCM-encrypted
|
|
@@ -131,7 +132,7 @@ function isSealedSession(value) {
|
|
|
131
132
|
* // Deploy with the new secret first, the old one second: new cookies seal
|
|
132
133
|
* // under NEW, cookies still sealed under OLD keep unsealing until you drop it.
|
|
133
134
|
* const store = new EncryptedCookieSessionStore({
|
|
134
|
-
* secret: [
|
|
135
|
+
* secret: [process.env.SESSION_SECRET!, process.env.SESSION_SECRET_OLD!],
|
|
135
136
|
* maxAgeMs: 7 * 24 * 60 * 60 * 1000,
|
|
136
137
|
* });
|
|
137
138
|
* ```
|
|
@@ -175,7 +176,7 @@ export class EncryptedCookieSessionStore {
|
|
|
175
176
|
return this.#maxAgeMs;
|
|
176
177
|
}
|
|
177
178
|
#key(index) {
|
|
178
|
-
return this.#keyPromises[index] ??= deriveAesKey(this.#secrets[index]);
|
|
179
|
+
return (this.#keyPromises[index] ??= deriveAesKey(this.#secrets[index]));
|
|
179
180
|
}
|
|
180
181
|
/** Encrypts the session into the cookie value under the current secret; there is no server-side record. */
|
|
181
182
|
async create(data) {
|
|
@@ -14,13 +14,12 @@
|
|
|
14
14
|
*
|
|
15
15
|
* @module
|
|
16
16
|
*/
|
|
17
|
-
import "../../../
|
|
18
|
-
import type {
|
|
19
|
-
import type {
|
|
20
|
-
import type {
|
|
21
|
-
import type {
|
|
22
|
-
import type
|
|
23
|
-
import { type SessionData, type SessionStore } from "./session-store.js";
|
|
17
|
+
import type { ClientInterface } from "../../../models/client.ts";
|
|
18
|
+
import type { AbstractScope } from "../../../models/scope.ts";
|
|
19
|
+
import type { TokenServiceInterface } from "../../../server/services/token.ts";
|
|
20
|
+
import type { TokenBundle, UserInfoClaims } from "../../../client/mod.ts";
|
|
21
|
+
import type { HonoBff } from "./bff.ts";
|
|
22
|
+
import { type SessionData, type SessionStore } from "./session-store.ts";
|
|
24
23
|
/** Options for {@link createTestSession}. */
|
|
25
24
|
export interface CreateTestSessionOptions {
|
|
26
25
|
/**
|
|
@@ -168,7 +167,7 @@ export interface SessionStoreContractOptions {
|
|
|
168
167
|
}
|
|
169
168
|
/**
|
|
170
169
|
* Contract test suite for {@link SessionStore} implementations. Registers
|
|
171
|
-
* `describe`/`it` blocks from
|
|
170
|
+
* `describe`/`it` blocks from Vitest, so call it at a test
|
|
172
171
|
* module's top level. It does not check that a stateful store's `update`
|
|
173
172
|
* rejects a missing or destroyed session, which {@link SessionStore.update}
|
|
174
173
|
* requires — test that yourself.
|