@udibo/oauth2 0.14.1 → 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 +8 -8
- package/{esm → dist}/adapters/hono/bff/bff.js +31 -26
- 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.
|
|
@@ -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),
|
|
@@ -724,8 +726,7 @@ export class HonoBff {
|
|
|
724
726
|
if (this.#options.rpInitiatedLogout) {
|
|
725
727
|
const endSession = this.#client.endSessionEndpoint;
|
|
726
728
|
if (endSession) {
|
|
727
|
-
const origin = this.#options.resolveOrigin?.(c) ??
|
|
728
|
-
new URL(c.req.url).origin;
|
|
729
|
+
const origin = this.#options.resolveOrigin?.(c) ?? new URL(c.req.url).origin;
|
|
729
730
|
const url = new URL(endSession, origin);
|
|
730
731
|
if (idToken)
|
|
731
732
|
url.searchParams.set("id_token_hint", idToken);
|
|
@@ -880,7 +881,8 @@ export class HonoBff {
|
|
|
880
881
|
catch {
|
|
881
882
|
subject = null;
|
|
882
883
|
}
|
|
883
|
-
if (!subject ||
|
|
884
|
+
if (!subject ||
|
|
885
|
+
(subject.sub === undefined && subject.sid === undefined)) {
|
|
884
886
|
return c.json({
|
|
885
887
|
error: "invalid_request",
|
|
886
888
|
error_description: "invalid logout_token",
|
|
@@ -1089,7 +1091,9 @@ export class HonoBff {
|
|
|
1089
1091
|
try {
|
|
1090
1092
|
const inboundAuth = c.req.header("Authorization") ?? "";
|
|
1091
1093
|
const hasBearer = /^bearer\s+\S/i.test(inboundAuth);
|
|
1092
|
-
if (!hasBearer &&
|
|
1094
|
+
if (!hasBearer &&
|
|
1095
|
+
this.#csrf &&
|
|
1096
|
+
this.#hasSessionCookie(c) &&
|
|
1093
1097
|
!this.#csrfHeaderOk(c)) {
|
|
1094
1098
|
return this.#csrfReject(c);
|
|
1095
1099
|
}
|
|
@@ -1203,7 +1207,7 @@ export class HonoBff {
|
|
|
1203
1207
|
const retryOn401 = options.retryOn401 ?? true;
|
|
1204
1208
|
const mountPrefix = (options.stripPrefix ?? "").endsWith("/")
|
|
1205
1209
|
? options.stripPrefix.slice(0, -1)
|
|
1206
|
-
: options.stripPrefix ?? "";
|
|
1210
|
+
: (options.stripPrefix ?? "");
|
|
1207
1211
|
return async (c) => {
|
|
1208
1212
|
if (this.#csrf && this.#hasSessionCookie(c) && !this.#csrfHeaderOk(c)) {
|
|
1209
1213
|
return this.#csrfReject(c);
|
|
@@ -1244,8 +1248,7 @@ export class HonoBff {
|
|
|
1244
1248
|
cause,
|
|
1245
1249
|
}));
|
|
1246
1250
|
}
|
|
1247
|
-
const canRetry = retryOn401 && body === null &&
|
|
1248
|
-
entry.data.refreshToken !== undefined;
|
|
1251
|
+
const canRetry = retryOn401 && body === null && entry.data.refreshToken !== undefined;
|
|
1249
1252
|
if (canRetry && isInvalidTokenChallenge(response)) {
|
|
1250
1253
|
await response.body?.cancel();
|
|
1251
1254
|
const outcome = await this.#refreshSessionEntry(c, entry);
|
|
@@ -1273,10 +1276,12 @@ export class HonoBff {
|
|
|
1273
1276
|
mountPrefix,
|
|
1274
1277
|
}),
|
|
1275
1278
|
};
|
|
1276
|
-
return downstream === null
|
|
1277
|
-
|
|
1278
|
-
|
|
1279
|
-
|
|
1279
|
+
return downstream === null
|
|
1280
|
+
? c.body(null, init)
|
|
1281
|
+
: c.body(downstream, {
|
|
1282
|
+
...init,
|
|
1283
|
+
status: response.status,
|
|
1284
|
+
});
|
|
1280
1285
|
};
|
|
1281
1286
|
}
|
|
1282
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.
|