@udibo/oauth2 0.1.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/LICENSE +20 -0
- package/README.md +174 -0
- package/SECURITY.md +77 -0
- package/esm/_dnt.polyfills.d.ts +17 -0
- package/esm/_dnt.polyfills.js +15 -0
- package/esm/adapters/hono/_common.d.ts +66 -0
- package/esm/adapters/hono/_common.js +108 -0
- package/esm/adapters/hono/authorization-server.d.ts +211 -0
- package/esm/adapters/hono/authorization-server.js +214 -0
- package/esm/adapters/hono/bff/auth-request-store.d.ts +164 -0
- package/esm/adapters/hono/bff/auth-request-store.js +154 -0
- package/esm/adapters/hono/bff/bff.d.ts +852 -0
- package/esm/adapters/hono/bff/bff.js +1194 -0
- package/esm/adapters/hono/bff/cookie-prefix.d.ts +72 -0
- package/esm/adapters/hono/bff/cookie-prefix.js +85 -0
- package/esm/adapters/hono/bff/mod.d.ts +19 -0
- package/esm/adapters/hono/bff/mod.js +19 -0
- package/esm/adapters/hono/bff/proxy.d.ts +108 -0
- package/esm/adapters/hono/bff/proxy.js +314 -0
- package/esm/adapters/hono/bff/session-store.d.ts +250 -0
- package/esm/adapters/hono/bff/session-store.js +216 -0
- package/esm/adapters/hono/bff/testing.d.ts +165 -0
- package/esm/adapters/hono/bff/testing.js +254 -0
- package/esm/adapters/hono/identity.d.ts +117 -0
- package/esm/adapters/hono/identity.js +215 -0
- package/esm/adapters/hono/log.d.ts +49 -0
- package/esm/adapters/hono/log.js +66 -0
- package/esm/adapters/hono/resource-server.d.ts +101 -0
- package/esm/adapters/hono/resource-server.js +108 -0
- package/esm/client/_http.d.ts +91 -0
- package/esm/client/_http.js +303 -0
- package/esm/client/base.d.ts +184 -0
- package/esm/client/base.js +93 -0
- package/esm/client/bff-client.d.ts +235 -0
- package/esm/client/bff-client.js +280 -0
- package/esm/client/browser-storage.d.ts +152 -0
- package/esm/client/browser-storage.js +246 -0
- package/esm/client/check.d.ts +114 -0
- package/esm/client/check.js +97 -0
- package/esm/client/direct-client.d.ts +707 -0
- package/esm/client/direct-client.js +1237 -0
- package/esm/client/discovery-cache.d.ts +138 -0
- package/esm/client/discovery-cache.js +124 -0
- package/esm/client/events.d.ts +54 -0
- package/esm/client/events.js +37 -0
- package/esm/client/mod.d.ts +35 -0
- package/esm/client/mod.js +33 -0
- package/esm/client/storage.d.ts +127 -0
- package/esm/client/storage.js +81 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/almost_equals.d.ts +29 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/almost_equals.js +47 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/array_includes.d.ts +28 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/array_includes.js +65 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/assert.d.ts +16 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/assert.js +23 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/assertion_error.d.ts +25 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/assertion_error.js +30 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/equal.d.ts +24 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/equal.js +193 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/equals.d.ts +36 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/equals.js +61 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/exists.d.ts +17 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/exists.js +27 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/fail.d.ts +14 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/fail.js +20 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/false.d.ts +18 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/false.js +23 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/greater.d.ts +19 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/greater.js +29 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/greater_or_equal.d.ts +19 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/greater_or_equal.js +29 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/instance_of.d.ts +22 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/instance_of.js +52 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/is_error.d.ts +24 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/is_error.js +53 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/less.d.ts +18 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/less.js +28 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/less_or_equal.d.ts +19 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/less_or_equal.js +29 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/match.d.ts +17 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/match.js +26 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/mod.d.ts +43 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/mod.js +45 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/not_equals.d.ts +26 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/not_equals.js +39 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/not_instance_of.d.ts +19 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/not_instance_of.js +29 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/not_match.d.ts +17 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/not_match.js +26 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/not_strict_equals.d.ts +22 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/not_strict_equals.js +32 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/object_match.d.ts +28 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/object_match.js +177 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/rejects.d.ts +41 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/rejects.js +53 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/strict_equals.d.ts +23 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/strict_equals.js +58 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/string_includes.d.ts +17 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/string_includes.js +26 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/throws.d.ts +44 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/throws.js +44 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/unimplemented.d.ts +14 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/unimplemented.js +20 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/unreachable.d.ts +14 -0
- package/esm/deps/jsr.io/@std/assert/1.0.19/unreachable.js +20 -0
- package/esm/deps/jsr.io/@std/async/1.5.0/delay.d.ts +44 -0
- package/esm/deps/jsr.io/@std/async/1.5.0/delay.js +84 -0
- package/esm/deps/jsr.io/@std/crypto/1.1.0/timing_safe_equal.d.ts +39 -0
- package/esm/deps/jsr.io/@std/crypto/1.1.0/timing_safe_equal.js +61 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/_common16.d.ts +22 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/_common16.js +51 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/_common32.d.ts +34 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/_common32.js +192 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/_common64.d.ts +34 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/_common64.js +113 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/_common_detach.d.ts +3 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/_common_detach.js +13 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/_types.d.ts +8 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/_types.js +2 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/_validate_binary_like.d.ts +1 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/_validate_binary_like.js +26 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/ascii85.d.ts +60 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/ascii85.js +152 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/base32.d.ts +39 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/base32.js +87 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/base58.d.ts +39 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/base58.js +131 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/base64.d.ts +39 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/base64.js +82 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/base64url.d.ts +39 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/base64url.js +72 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/hex.d.ts +38 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/hex.js +87 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/mod.d.ts +97 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/mod.js +99 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/varint.d.ts +119 -0
- package/esm/deps/jsr.io/@std/encoding/1.0.11/varint.js +209 -0
- package/esm/deps/jsr.io/@std/http/1.1.3/status.d.ts +343 -0
- package/esm/deps/jsr.io/@std/http/1.1.3/status.js +343 -0
- package/esm/deps/jsr.io/@std/internal/1.0.14/assertion_state.d.ts +159 -0
- package/esm/deps/jsr.io/@std/internal/1.0.14/assertion_state.js +223 -0
- package/esm/deps/jsr.io/@std/internal/1.0.14/build_message.d.ts +79 -0
- package/esm/deps/jsr.io/@std/internal/1.0.14/build_message.js +116 -0
- package/esm/deps/jsr.io/@std/internal/1.0.14/diff.d.ts +139 -0
- package/esm/deps/jsr.io/@std/internal/1.0.14/diff.js +277 -0
- package/esm/deps/jsr.io/@std/internal/1.0.14/diff_str.d.ts +98 -0
- package/esm/deps/jsr.io/@std/internal/1.0.14/diff_str.js +181 -0
- package/esm/deps/jsr.io/@std/internal/1.0.14/format.d.ts +29 -0
- package/esm/deps/jsr.io/@std/internal/1.0.14/format.js +68 -0
- package/esm/deps/jsr.io/@std/internal/1.0.14/styles.d.ts +158 -0
- package/esm/deps/jsr.io/@std/internal/1.0.14/styles.js +206 -0
- package/esm/deps/jsr.io/@std/internal/1.0.14/types.d.ts +24 -0
- package/esm/deps/jsr.io/@std/internal/1.0.14/types.js +3 -0
- package/esm/deps/jsr.io/@std/testing/1.0.20/_test_suite.d.ts +91 -0
- package/esm/deps/jsr.io/@std/testing/1.0.20/_test_suite.js +347 -0
- package/esm/deps/jsr.io/@std/testing/1.0.20/bdd.d.ts +382 -0
- package/esm/deps/jsr.io/@std/testing/1.0.20/bdd.js +1110 -0
- package/esm/deps/jsr.io/@udibo/http-error/0.11.1/mod.d.ts +363 -0
- package/esm/deps/jsr.io/@udibo/http-error/0.11.1/mod.js +616 -0
- package/esm/errors.d.ts +203 -0
- package/esm/errors.js +287 -0
- package/esm/identity/captcha.d.ts +147 -0
- package/esm/identity/captcha.js +64 -0
- package/esm/identity/delivery.d.ts +96 -0
- package/esm/identity/delivery.js +41 -0
- package/esm/identity/errors.d.ts +39 -0
- package/esm/identity/errors.js +46 -0
- package/esm/identity/events.d.ts +242 -0
- package/esm/identity/events.js +39 -0
- package/esm/identity/external/_shared.d.ts +86 -0
- package/esm/identity/external/_shared.js +107 -0
- package/esm/identity/external/_token-exchange.d.ts +61 -0
- package/esm/identity/external/_token-exchange.js +179 -0
- package/esm/identity/external/apple-client-secret.d.ts +82 -0
- package/esm/identity/external/apple-client-secret.js +133 -0
- package/esm/identity/external/apple.d.ts +64 -0
- package/esm/identity/external/apple.js +248 -0
- package/esm/identity/external/discord.d.ts +38 -0
- package/esm/identity/external/discord.js +62 -0
- package/esm/identity/external/errors.d.ts +48 -0
- package/esm/identity/external/errors.js +36 -0
- package/esm/identity/external/flow.d.ts +107 -0
- package/esm/identity/external/flow.js +158 -0
- package/esm/identity/external/github.d.ts +42 -0
- package/esm/identity/external/github.js +164 -0
- package/esm/identity/external/google.d.ts +52 -0
- package/esm/identity/external/google.js +38 -0
- package/esm/identity/external/mod.d.ts +63 -0
- package/esm/identity/external/mod.js +61 -0
- package/esm/identity/external/oauth2.d.ts +110 -0
- package/esm/identity/external/oauth2.js +158 -0
- package/esm/identity/external/oidc.d.ts +81 -0
- package/esm/identity/external/oidc.js +250 -0
- package/esm/identity/external/provider.d.ts +132 -0
- package/esm/identity/external/provider.js +12 -0
- package/esm/identity/hibp.d.ts +67 -0
- package/esm/identity/hibp.js +87 -0
- package/esm/identity/identifier.d.ts +44 -0
- package/esm/identity/identifier.js +47 -0
- package/esm/identity/lockout.d.ts +155 -0
- package/esm/identity/lockout.js +117 -0
- package/esm/identity/mfa/mod.d.ts +42 -0
- package/esm/identity/mfa/mod.js +42 -0
- package/esm/identity/mfa/recovery-codes.d.ts +96 -0
- package/esm/identity/mfa/recovery-codes.js +80 -0
- package/esm/identity/mfa/service.d.ts +338 -0
- package/esm/identity/mfa/service.js +351 -0
- package/esm/identity/mfa/totp.d.ts +186 -0
- package/esm/identity/mfa/totp.js +194 -0
- package/esm/identity/migration.d.ts +155 -0
- package/esm/identity/migration.js +243 -0
- package/esm/identity/mod.d.ts +65 -0
- package/esm/identity/mod.js +64 -0
- package/esm/identity/otp.d.ts +255 -0
- package/esm/identity/otp.js +245 -0
- package/esm/identity/password-policy.d.ts +45 -0
- package/esm/identity/password-policy.js +60 -0
- package/esm/identity/password.d.ts +171 -0
- package/esm/identity/password.js +160 -0
- package/esm/identity/rate-limit.d.ts +192 -0
- package/esm/identity/rate-limit.js +168 -0
- package/esm/identity/service.d.ts +579 -0
- package/esm/identity/service.js +835 -0
- package/esm/identity/session.d.ts +122 -0
- package/esm/identity/session.js +48 -0
- package/esm/identity/token-flow.d.ts +214 -0
- package/esm/identity/token-flow.js +173 -0
- package/esm/models/authentication.d.ts +24 -0
- package/esm/models/authentication.js +1 -0
- package/esm/models/authorization-code.d.ts +63 -0
- package/esm/models/authorization-code.js +1 -0
- package/esm/models/authorization.d.ts +165 -0
- package/esm/models/authorization.js +160 -0
- package/esm/models/client.d.ts +78 -0
- package/esm/models/client.js +1 -0
- package/esm/models/device-authorization.d.ts +30 -0
- package/esm/models/device-authorization.js +1 -0
- package/esm/models/responses.d.ts +93 -0
- package/esm/models/responses.js +1 -0
- package/esm/models/scope.d.ts +81 -0
- package/esm/models/scope.js +125 -0
- package/esm/models/token.d.ts +135 -0
- package/esm/models/token.js +1 -0
- package/esm/package.json +3 -0
- package/esm/react/callback.d.ts +52 -0
- package/esm/react/callback.js +71 -0
- package/esm/react/components/class-names.d.ts +91 -0
- package/esm/react/components/class-names.js +118 -0
- package/esm/react/components/internal.d.ts +62 -0
- package/esm/react/components/internal.js +102 -0
- package/esm/react/components/mfa-challenge-form.d.ts +66 -0
- package/esm/react/components/mfa-challenge-form.js +46 -0
- package/esm/react/components/mfa-enrollment-form.d.ts +83 -0
- package/esm/react/components/mfa-enrollment-form.js +41 -0
- package/esm/react/components/mod.d.ts +103 -0
- package/esm/react/components/mod.js +93 -0
- package/esm/react/components/request-password-reset-form.d.ts +61 -0
- package/esm/react/components/request-password-reset-form.js +41 -0
- package/esm/react/components/reset-password-form.d.ts +66 -0
- package/esm/react/components/reset-password-form.js +56 -0
- package/esm/react/components/sign-in-form.d.ts +74 -0
- package/esm/react/components/sign-in-form.js +43 -0
- package/esm/react/components/sign-up-form.d.ts +85 -0
- package/esm/react/components/sign-up-form.js +57 -0
- package/esm/react/components/types.d.ts +208 -0
- package/esm/react/components/types.js +14 -0
- package/esm/react/components/use-auth-form.d.ts +118 -0
- package/esm/react/components/use-auth-form.js +172 -0
- package/esm/react/components/user-menu.d.ts +79 -0
- package/esm/react/components/user-menu.js +73 -0
- package/esm/react/context.d.ts +51 -0
- package/esm/react/context.js +16 -0
- package/esm/react/mod.d.ts +26 -0
- package/esm/react/mod.js +26 -0
- package/esm/react/provider.d.ts +40 -0
- package/esm/react/provider.js +189 -0
- package/esm/react/require-auth.d.ts +31 -0
- package/esm/react/require-auth.js +37 -0
- package/esm/react/testing.d.ts +322 -0
- package/esm/react/testing.js +461 -0
- package/esm/react/use-authorization.d.ts +31 -0
- package/esm/react/use-authorization.js +36 -0
- package/esm/react/use-oauth2.d.ts +112 -0
- package/esm/react/use-oauth2.js +127 -0
- package/esm/server/authorization-server.d.ts +736 -0
- package/esm/server/authorization-server.js +1304 -0
- package/esm/server/client-authentication.d.ts +28 -0
- package/esm/server/client-authentication.js +51 -0
- package/esm/server/grants/authorization-code.d.ts +179 -0
- package/esm/server/grants/authorization-code.js +232 -0
- package/esm/server/grants/client-credentials.d.ts +52 -0
- package/esm/server/grants/client-credentials.js +53 -0
- package/esm/server/grants/device-authorization.d.ts +103 -0
- package/esm/server/grants/device-authorization.js +156 -0
- package/esm/server/grants/grant.d.ts +165 -0
- package/esm/server/grants/grant.js +173 -0
- package/esm/server/grants/password.d.ts +80 -0
- package/esm/server/grants/password.js +92 -0
- package/esm/server/grants/refresh-token.d.ts +80 -0
- package/esm/server/grants/refresh-token.js +136 -0
- package/esm/server/introspection-token-reader.d.ts +153 -0
- package/esm/server/introspection-token-reader.js +164 -0
- package/esm/server/jwks-token-reader.d.ts +263 -0
- package/esm/server/jwks-token-reader.js +508 -0
- package/esm/server/mod.d.ts +23 -0
- package/esm/server/mod.js +15 -0
- package/esm/server/public-suffix/mod.d.ts +62 -0
- package/esm/server/public-suffix/mod.js +103 -0
- package/esm/server/public-suffix/rules.d.ts +23 -0
- package/esm/server/public-suffix/rules.js +23 -0
- package/esm/server/redirect-uri.d.ts +187 -0
- package/esm/server/redirect-uri.js +331 -0
- package/esm/server/resource-server.d.ts +286 -0
- package/esm/server/resource-server.js +365 -0
- package/esm/server/services/authorization-code.d.ts +84 -0
- package/esm/server/services/authorization-code.js +35 -0
- package/esm/server/services/client.d.ts +35 -0
- package/esm/server/services/client.js +1 -0
- package/esm/server/services/device-authorization.d.ts +134 -0
- package/esm/server/services/device-authorization.js +7 -0
- package/esm/server/services/token.d.ts +242 -0
- package/esm/server/services/token.js +78 -0
- package/esm/server/services/user.d.ts +29 -0
- package/esm/server/services/user.js +7 -0
- package/esm/server/signing-keys.d.ts +201 -0
- package/esm/server/signing-keys.js +225 -0
- package/esm/server/utils/hash.d.ts +6 -0
- package/esm/server/utils/hash.js +11 -0
- package/esm/testing/contract/authorization-code.d.ts +37 -0
- package/esm/testing/contract/authorization-code.js +93 -0
- package/esm/testing/contract/client.d.ts +85 -0
- package/esm/testing/contract/client.js +126 -0
- package/esm/testing/contract/device-authorization.d.ts +37 -0
- package/esm/testing/contract/device-authorization.js +193 -0
- package/esm/testing/contract/lockout-store.d.ts +47 -0
- package/esm/testing/contract/lockout-store.js +122 -0
- package/esm/testing/contract/mfa-store.d.ts +50 -0
- package/esm/testing/contract/mfa-store.js +226 -0
- package/esm/testing/contract/mod.d.ts +39 -0
- package/esm/testing/contract/mod.js +39 -0
- package/esm/testing/contract/otp-store.d.ts +48 -0
- package/esm/testing/contract/otp-store.js +197 -0
- package/esm/testing/contract/rate-limit-store.d.ts +52 -0
- package/esm/testing/contract/rate-limit-store.js +105 -0
- package/esm/testing/contract/token-flow-store.d.ts +54 -0
- package/esm/testing/contract/token-flow-store.js +179 -0
- package/esm/testing/contract/token-reader.d.ts +77 -0
- package/esm/testing/contract/token-reader.js +78 -0
- package/esm/testing/contract/token.d.ts +61 -0
- package/esm/testing/contract/token.js +287 -0
- package/esm/testing/contract/user.d.ts +63 -0
- package/esm/testing/contract/user.js +75 -0
- package/esm/testing/mod.d.ts +34 -0
- package/esm/testing/mod.js +34 -0
- package/esm/testing/server.d.ts +197 -0
- package/esm/testing/server.js +193 -0
- package/esm/testing/services.d.ts +373 -0
- package/esm/testing/services.js +703 -0
- package/esm/utils/_buffer.d.ts +10 -0
- package/esm/utils/_buffer.js +12 -0
- package/esm/utils/_timing-safe.d.ts +13 -0
- package/esm/utils/_timing-safe.js +22 -0
- package/esm/utils/authentication-context.d.ts +3 -0
- package/esm/utils/authentication-context.js +14 -0
- package/esm/utils/basic-auth.d.ts +50 -0
- package/esm/utils/basic-auth.js +106 -0
- package/esm/utils/crypto.d.ts +97 -0
- package/esm/utils/crypto.js +162 -0
- package/esm/utils/pkce.d.ts +151 -0
- package/esm/utils/pkce.js +179 -0
- package/esm/utils/text.d.ts +24 -0
- package/esm/utils/text.js +28 -0
- package/esm/utils/url.d.ts +66 -0
- package/esm/utils/url.js +90 -0
- package/package.json +92 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hono adapter for the core {@link AuthorizationServer}.
|
|
3
|
+
*
|
|
4
|
+
* Provides Hono handler factories for each OAuth2 endpoint and a convenience
|
|
5
|
+
* `routes()` aggregator that mounts all standard endpoints at conventional
|
|
6
|
+
* paths. Also inherits resource-server-shaped helpers (`protect`,
|
|
7
|
+
* `authenticate`, `getContext`) so the same instance can protect API routes.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { Hono } from "hono";
|
|
12
|
+
* import { HonoAuthorizationServer } from "@udibo/oauth2/hono/authorization-server";
|
|
13
|
+
*
|
|
14
|
+
* const issuer = "https://auth.example.com";
|
|
15
|
+
* const authServer = new HonoAuthorizationServer({
|
|
16
|
+
* grants: { ...grants },
|
|
17
|
+
* resolve: () => ({
|
|
18
|
+
* services: { clientService, tokenService, authorizationCodeService },
|
|
19
|
+
* issuer,
|
|
20
|
+
* authorizationEndpoint: `${issuer}/oauth2/authorize`,
|
|
21
|
+
* tokenEndpoint: `${issuer}/oauth2/token`,
|
|
22
|
+
* revocationEndpoint: `${issuer}/oauth2/revoke`,
|
|
23
|
+
* introspectionEndpoint: `${issuer}/oauth2/introspect`,
|
|
24
|
+
* }),
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* const app = new Hono();
|
|
28
|
+
* app.route("/oauth2", authServer.routes({ authenticateUser }));
|
|
29
|
+
* app.use("/api/*", authServer.protect());
|
|
30
|
+
* app.get("/api/me", (c) => c.json(authServer.getContext(c).user));
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @module
|
|
34
|
+
*/
|
|
35
|
+
import "../../_dnt.polyfills.js";
|
|
36
|
+
import { Hono } from "hono";
|
|
37
|
+
import type { Context, Handler, MiddlewareHandler } from "hono";
|
|
38
|
+
import type { RequireConditions } from "../../models/authorization.js";
|
|
39
|
+
import type { AuthenticationContext } from "../../models/authentication.js";
|
|
40
|
+
import type { ClientInterface } from "../../models/client.js";
|
|
41
|
+
import type { AbstractScope, BasicScope } from "../../models/scope.js";
|
|
42
|
+
import { AuthorizationServer, type AuthorizationServerOptions } from "../../server/authorization-server.js";
|
|
43
|
+
import type { AuthenticatedContext } from "../../server/resource-server.js";
|
|
44
|
+
/**
|
|
45
|
+
* Authenticates the resource owner during an authorization request.
|
|
46
|
+
*
|
|
47
|
+
* Receives the Hono {@link Context} directly so the callback can read cookies
|
|
48
|
+
* or session variables without reconstructing a {@link Request}. Return one
|
|
49
|
+
* of:
|
|
50
|
+
*
|
|
51
|
+
* - `{ user, authorizedScope?, authenticationContext? }` — user is authenticated;
|
|
52
|
+
* the authorize flow continues. Supply only verified event claims in
|
|
53
|
+
* `authenticationContext`; the code and its tokens retain that snapshot.
|
|
54
|
+
* - `null` — explicit denial; the framework redirects to `redirect_uri` with
|
|
55
|
+
* `error=access_denied`.
|
|
56
|
+
* - A `Response` (typically `c.redirect(...)` to a login page) —
|
|
57
|
+
* short-circuits the authorize flow and is returned to the browser as-is.
|
|
58
|
+
* This is how login redirects, interstitials, etc. are wired without
|
|
59
|
+
* wrapping the framework handler.
|
|
60
|
+
*/
|
|
61
|
+
export type HonoAuthenticateUserFn<User> = (c: Context) => Promise<{
|
|
62
|
+
user: User;
|
|
63
|
+
authorizedScope?: AbstractScope;
|
|
64
|
+
authenticationContext?: AuthenticationContext;
|
|
65
|
+
} | Response | null>;
|
|
66
|
+
/**
|
|
67
|
+
* Collects consent from the resource owner for the requested scope.
|
|
68
|
+
*
|
|
69
|
+
* Receives the Hono {@link Context} so the callback can render a consent
|
|
70
|
+
* page, read form input, etc. Return one of:
|
|
71
|
+
*
|
|
72
|
+
* - `{ approved: true, scope? }` — consent granted (optionally narrowing the
|
|
73
|
+
* scope per RFC 6749 §3.3).
|
|
74
|
+
* - `{ approved: false }` — consent denied; the framework redirects to
|
|
75
|
+
* `redirect_uri` with `error=access_denied`.
|
|
76
|
+
* - A `Response` (typically `c.html(...)` rendering a consent page) —
|
|
77
|
+
* short-circuits the authorize flow and is returned to the browser as-is.
|
|
78
|
+
* The consent UI should resubmit to the authorize endpoint with a
|
|
79
|
+
* decision parameter the callback can read on the next request.
|
|
80
|
+
*/
|
|
81
|
+
export type HonoHandleConsentFn<Client extends ClientInterface, S extends AbstractScope> = (c: Context, client: Client, requestedScope: S | undefined, user: unknown) => Promise<{
|
|
82
|
+
approved: boolean;
|
|
83
|
+
scope?: S;
|
|
84
|
+
} | Response>;
|
|
85
|
+
/** Options for {@link HonoAuthorizationServer.routes}. */
|
|
86
|
+
export interface HonoRoutesOptions<Client extends ClientInterface, User, S extends AbstractScope> {
|
|
87
|
+
/** Authenticates the resource owner at the authorize endpoint. */
|
|
88
|
+
authenticateUser: HonoAuthenticateUserFn<User>;
|
|
89
|
+
/** Collects consent for the requested scope. Omit to auto-consent. */
|
|
90
|
+
handleConsent?: HonoHandleConsentFn<Client, S>;
|
|
91
|
+
}
|
|
92
|
+
/** Options for {@link HonoAuthorizationServer.authorizeHandler}. */
|
|
93
|
+
export type HonoAuthorizeHandlerOptions<Client extends ClientInterface, User, S extends AbstractScope> = HonoRoutesOptions<Client, User, S>;
|
|
94
|
+
/**
|
|
95
|
+
* Hono-specific wrapper around {@link AuthorizationServer}. Adds endpoint
|
|
96
|
+
* handler factories and the three resource-server-shaped helpers
|
|
97
|
+
* (`protect`, `authenticate`, `getContext`) against this same instance.
|
|
98
|
+
*
|
|
99
|
+
* Resource-server behavior (realm, errorFormat, throwOnError, token lookup)
|
|
100
|
+
* reads directly off the auth-server instance, so mutating those fields
|
|
101
|
+
* after construction propagates without the need to rewire any companion
|
|
102
|
+
* objects.
|
|
103
|
+
*/
|
|
104
|
+
export declare class HonoAuthorizationServer<Client extends ClientInterface, User, S extends AbstractScope = BasicScope> extends AuthorizationServer<Client, User, S> {
|
|
105
|
+
/** Forwards `options` to the core {@linkcode AuthorizationServer}. */
|
|
106
|
+
constructor(options: AuthorizationServerOptions<Client, User, S>);
|
|
107
|
+
/**
|
|
108
|
+
* Returns a Hono middleware that validates the bearer token against this
|
|
109
|
+
* server's token service. On success, sets the authenticated context at
|
|
110
|
+
* `c.get("@udibo/oauth2")`; on failure returns an RFC 6749 error response
|
|
111
|
+
* with a `WWW-Authenticate` header per RFC 6750 Section 3.
|
|
112
|
+
*/
|
|
113
|
+
protect(requiredScope?: S | string): MiddlewareHandler;
|
|
114
|
+
/**
|
|
115
|
+
* Returns a Hono middleware that asserts an **already-authenticated** request
|
|
116
|
+
* carries `requiredScope` without re-validating the token — the per-route
|
|
117
|
+
* companion to {@link protect} for mounts that need different scopes per
|
|
118
|
+
* route. See {@link HonoResourceServer.requireScope}.
|
|
119
|
+
*/
|
|
120
|
+
requireScope(requiredScope: S | string): MiddlewareHandler;
|
|
121
|
+
/**
|
|
122
|
+
* Middleware asserting the already-authenticated request satisfies every
|
|
123
|
+
* condition (scope, permission, role, organization) on this server's own
|
|
124
|
+
* protected routes. See {@link HonoResourceServer.require}.
|
|
125
|
+
*/
|
|
126
|
+
require(conditions: RequireConditions): MiddlewareHandler;
|
|
127
|
+
/**
|
|
128
|
+
* Authenticates a Hono {@link Context} or a raw {@link Request} manually.
|
|
129
|
+
* Throws on failure — pair with
|
|
130
|
+
* {@link AuthorizationServer.handleAuthError} to convert to a response.
|
|
131
|
+
*/
|
|
132
|
+
authenticate(c: Context | Request, requiredScope?: S | string): Promise<AuthenticatedContext<Client, User, S>>;
|
|
133
|
+
/** Typed accessor for the authenticated OAuth2 context. */
|
|
134
|
+
getContext(c: Context): AuthenticatedContext<Client, User, S>;
|
|
135
|
+
/**
|
|
136
|
+
* Handler for the token endpoint (RFC 6749 Section 3.2).
|
|
137
|
+
* Mount at `POST /token`.
|
|
138
|
+
*/
|
|
139
|
+
tokenHandler(): Handler;
|
|
140
|
+
/**
|
|
141
|
+
* Handler for the authorization endpoint (RFC 6749 Section 3.1).
|
|
142
|
+
* Mount at `GET /authorize`. Callbacks receive the Hono {@link Context}.
|
|
143
|
+
*/
|
|
144
|
+
authorizeHandler(options: HonoAuthorizeHandlerOptions<Client, User, S>): Handler;
|
|
145
|
+
/**
|
|
146
|
+
* Handler for the token revocation endpoint (RFC 7009).
|
|
147
|
+
* Mount at `POST /revoke`.
|
|
148
|
+
*/
|
|
149
|
+
revocationHandler(): Handler;
|
|
150
|
+
/**
|
|
151
|
+
* Handler for the token introspection endpoint (RFC 7662).
|
|
152
|
+
* Mount at `POST /introspect`.
|
|
153
|
+
*/
|
|
154
|
+
introspectionHandler(): Handler;
|
|
155
|
+
/**
|
|
156
|
+
* Handler for the authorization server metadata endpoint (RFC 8414).
|
|
157
|
+
* Mount at `GET /.well-known/oauth-authorization-server`.
|
|
158
|
+
*/
|
|
159
|
+
metadataHandler(): Handler;
|
|
160
|
+
/**
|
|
161
|
+
* Handler for the OIDC discovery endpoint.
|
|
162
|
+
* Mount at `GET /.well-known/openid-configuration`. 404s when OIDC issuance
|
|
163
|
+
* is not configured.
|
|
164
|
+
*/
|
|
165
|
+
oidcMetadataHandler(): Handler;
|
|
166
|
+
/**
|
|
167
|
+
* Handler for the JWKS endpoint (OIDC Discovery).
|
|
168
|
+
* Mount at `GET /jwks`. 404s when OIDC issuance is not configured.
|
|
169
|
+
*/
|
|
170
|
+
jwksHandler(): Handler;
|
|
171
|
+
/**
|
|
172
|
+
* Handler for the OIDC UserInfo endpoint.
|
|
173
|
+
* Mount at `GET`/`POST /userinfo`.
|
|
174
|
+
*/
|
|
175
|
+
userInfoHandler(): Handler;
|
|
176
|
+
/**
|
|
177
|
+
* Handler for the OIDC RP-Initiated Logout end-session endpoint.
|
|
178
|
+
* Mount at `GET|POST /end_session`. Answers 404 unless the server was
|
|
179
|
+
* constructed with an `endSession` callback.
|
|
180
|
+
*/
|
|
181
|
+
endSessionHandler(): Handler;
|
|
182
|
+
/**
|
|
183
|
+
* Handler for the device authorization endpoint (RFC 8628).
|
|
184
|
+
* Mount at `POST /device_authorization`.
|
|
185
|
+
*/
|
|
186
|
+
deviceAuthorizationHandler(): Handler;
|
|
187
|
+
/**
|
|
188
|
+
* Returns a Hono app with all standard OAuth2 endpoints mounted at
|
|
189
|
+
* conventional paths, relative to whatever base path the caller mounts it
|
|
190
|
+
* under.
|
|
191
|
+
*
|
|
192
|
+
* - `POST /token`
|
|
193
|
+
* - `GET /authorize`
|
|
194
|
+
* - `POST /revoke`
|
|
195
|
+
* - `POST /introspect`
|
|
196
|
+
* - `POST /device_authorization`
|
|
197
|
+
* - `GET /.well-known/oauth-authorization-server`
|
|
198
|
+
* - `GET /.well-known/openid-configuration`
|
|
199
|
+
* - `GET /jwks` and `GET`/`POST /userinfo` (live when OIDC issuance is
|
|
200
|
+
* configured via `signingKeys`)
|
|
201
|
+
*
|
|
202
|
+
* Mount with `app.route("/oauth2", server.routes({...}))`.
|
|
203
|
+
*
|
|
204
|
+
* Every path and verb above comes from
|
|
205
|
+
* {@link ENDPOINT_PATHS}/{@link ENDPOINT_METHODS}, so the mounted surface and
|
|
206
|
+
* the URLs the server advertises can never drift apart. Users who want custom
|
|
207
|
+
* paths or only a subset of endpoints should mount the individual handler
|
|
208
|
+
* factories instead.
|
|
209
|
+
*/
|
|
210
|
+
routes(options: HonoRoutesOptions<Client, User, S>): Hono;
|
|
211
|
+
}
|
|
@@ -0,0 +1,214 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Hono adapter for the core {@link AuthorizationServer}.
|
|
3
|
+
*
|
|
4
|
+
* Provides Hono handler factories for each OAuth2 endpoint and a convenience
|
|
5
|
+
* `routes()` aggregator that mounts all standard endpoints at conventional
|
|
6
|
+
* paths. Also inherits resource-server-shaped helpers (`protect`,
|
|
7
|
+
* `authenticate`, `getContext`) so the same instance can protect API routes.
|
|
8
|
+
*
|
|
9
|
+
* @example
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { Hono } from "hono";
|
|
12
|
+
* import { HonoAuthorizationServer } from "@udibo/oauth2/hono/authorization-server";
|
|
13
|
+
*
|
|
14
|
+
* const issuer = "https://auth.example.com";
|
|
15
|
+
* const authServer = new HonoAuthorizationServer({
|
|
16
|
+
* grants: { ...grants },
|
|
17
|
+
* resolve: () => ({
|
|
18
|
+
* services: { clientService, tokenService, authorizationCodeService },
|
|
19
|
+
* issuer,
|
|
20
|
+
* authorizationEndpoint: `${issuer}/oauth2/authorize`,
|
|
21
|
+
* tokenEndpoint: `${issuer}/oauth2/token`,
|
|
22
|
+
* revocationEndpoint: `${issuer}/oauth2/revoke`,
|
|
23
|
+
* introspectionEndpoint: `${issuer}/oauth2/introspect`,
|
|
24
|
+
* }),
|
|
25
|
+
* });
|
|
26
|
+
*
|
|
27
|
+
* const app = new Hono();
|
|
28
|
+
* app.route("/oauth2", authServer.routes({ authenticateUser }));
|
|
29
|
+
* app.use("/api/*", authServer.protect());
|
|
30
|
+
* app.get("/api/me", (c) => c.json(authServer.getContext(c).user));
|
|
31
|
+
* ```
|
|
32
|
+
*
|
|
33
|
+
* @module
|
|
34
|
+
*/
|
|
35
|
+
import "../../_dnt.polyfills.js";
|
|
36
|
+
import { Hono } from "hono";
|
|
37
|
+
import { AuthorizationServer, ENDPOINT_METHODS, ENDPOINT_PATHS, } from "../../server/authorization-server.js";
|
|
38
|
+
import { authenticateHonoRequest, createProtectMiddleware, createRequireMiddleware, createRequireScopeMiddleware, readContext, } from "./_common.js";
|
|
39
|
+
/**
|
|
40
|
+
* Hono-specific wrapper around {@link AuthorizationServer}. Adds endpoint
|
|
41
|
+
* handler factories and the three resource-server-shaped helpers
|
|
42
|
+
* (`protect`, `authenticate`, `getContext`) against this same instance.
|
|
43
|
+
*
|
|
44
|
+
* Resource-server behavior (realm, errorFormat, throwOnError, token lookup)
|
|
45
|
+
* reads directly off the auth-server instance, so mutating those fields
|
|
46
|
+
* after construction propagates without the need to rewire any companion
|
|
47
|
+
* objects.
|
|
48
|
+
*/
|
|
49
|
+
export class HonoAuthorizationServer extends AuthorizationServer {
|
|
50
|
+
/** Forwards `options` to the core {@linkcode AuthorizationServer}. */
|
|
51
|
+
constructor(options) {
|
|
52
|
+
super(options);
|
|
53
|
+
}
|
|
54
|
+
/**
|
|
55
|
+
* Returns a Hono middleware that validates the bearer token against this
|
|
56
|
+
* server's token service. On success, sets the authenticated context at
|
|
57
|
+
* `c.get("@udibo/oauth2")`; on failure returns an RFC 6749 error response
|
|
58
|
+
* with a `WWW-Authenticate` header per RFC 6750 Section 3.
|
|
59
|
+
*/
|
|
60
|
+
protect(requiredScope) {
|
|
61
|
+
return createProtectMiddleware(this, requiredScope);
|
|
62
|
+
}
|
|
63
|
+
/**
|
|
64
|
+
* Returns a Hono middleware that asserts an **already-authenticated** request
|
|
65
|
+
* carries `requiredScope` without re-validating the token — the per-route
|
|
66
|
+
* companion to {@link protect} for mounts that need different scopes per
|
|
67
|
+
* route. See {@link HonoResourceServer.requireScope}.
|
|
68
|
+
*/
|
|
69
|
+
requireScope(requiredScope) {
|
|
70
|
+
return createRequireScopeMiddleware(this, "HonoAuthorizationServer", requiredScope);
|
|
71
|
+
}
|
|
72
|
+
/**
|
|
73
|
+
* Middleware asserting the already-authenticated request satisfies every
|
|
74
|
+
* condition (scope, permission, role, organization) on this server's own
|
|
75
|
+
* protected routes. See {@link HonoResourceServer.require}.
|
|
76
|
+
*/
|
|
77
|
+
require(conditions) {
|
|
78
|
+
return createRequireMiddleware(this, "HonoAuthorizationServer", conditions);
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Authenticates a Hono {@link Context} or a raw {@link Request} manually.
|
|
82
|
+
* Throws on failure — pair with
|
|
83
|
+
* {@link AuthorizationServer.handleAuthError} to convert to a response.
|
|
84
|
+
*/
|
|
85
|
+
authenticate(c, requiredScope) {
|
|
86
|
+
return authenticateHonoRequest(this, c, requiredScope);
|
|
87
|
+
}
|
|
88
|
+
/** Typed accessor for the authenticated OAuth2 context. */
|
|
89
|
+
getContext(c) {
|
|
90
|
+
return readContext(c, "HonoAuthorizationServer");
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Handler for the token endpoint (RFC 6749 Section 3.2).
|
|
94
|
+
* Mount at `POST /token`.
|
|
95
|
+
*/
|
|
96
|
+
tokenHandler() {
|
|
97
|
+
return (c) => this.handleTokenRequest(c.req.raw);
|
|
98
|
+
}
|
|
99
|
+
/**
|
|
100
|
+
* Handler for the authorization endpoint (RFC 6749 Section 3.1).
|
|
101
|
+
* Mount at `GET /authorize`. Callbacks receive the Hono {@link Context}.
|
|
102
|
+
*/
|
|
103
|
+
authorizeHandler(options) {
|
|
104
|
+
const { authenticateUser, handleConsent } = options;
|
|
105
|
+
return (c) => {
|
|
106
|
+
const auth = () => authenticateUser(c);
|
|
107
|
+
const consent = handleConsent
|
|
108
|
+
? (client, requestedScope, user) => handleConsent(c, client, requestedScope, user)
|
|
109
|
+
: undefined;
|
|
110
|
+
return this.handleAuthorizeRequest(c.req.raw, auth, consent);
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
/**
|
|
114
|
+
* Handler for the token revocation endpoint (RFC 7009).
|
|
115
|
+
* Mount at `POST /revoke`.
|
|
116
|
+
*/
|
|
117
|
+
revocationHandler() {
|
|
118
|
+
return (c) => this.handleRevocationRequest(c.req.raw);
|
|
119
|
+
}
|
|
120
|
+
/**
|
|
121
|
+
* Handler for the token introspection endpoint (RFC 7662).
|
|
122
|
+
* Mount at `POST /introspect`.
|
|
123
|
+
*/
|
|
124
|
+
introspectionHandler() {
|
|
125
|
+
return (c) => this.handleIntrospectionRequest(c.req.raw);
|
|
126
|
+
}
|
|
127
|
+
/**
|
|
128
|
+
* Handler for the authorization server metadata endpoint (RFC 8414).
|
|
129
|
+
* Mount at `GET /.well-known/oauth-authorization-server`.
|
|
130
|
+
*/
|
|
131
|
+
metadataHandler() {
|
|
132
|
+
return (c) => this.handleMetadataRequest(c.req.raw);
|
|
133
|
+
}
|
|
134
|
+
/**
|
|
135
|
+
* Handler for the OIDC discovery endpoint.
|
|
136
|
+
* Mount at `GET /.well-known/openid-configuration`. 404s when OIDC issuance
|
|
137
|
+
* is not configured.
|
|
138
|
+
*/
|
|
139
|
+
oidcMetadataHandler() {
|
|
140
|
+
return (c) => this.handleOidcMetadataRequest(c.req.raw);
|
|
141
|
+
}
|
|
142
|
+
/**
|
|
143
|
+
* Handler for the JWKS endpoint (OIDC Discovery).
|
|
144
|
+
* Mount at `GET /jwks`. 404s when OIDC issuance is not configured.
|
|
145
|
+
*/
|
|
146
|
+
jwksHandler() {
|
|
147
|
+
return (c) => this.handleJwksRequest(c.req.raw);
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Handler for the OIDC UserInfo endpoint.
|
|
151
|
+
* Mount at `GET`/`POST /userinfo`.
|
|
152
|
+
*/
|
|
153
|
+
userInfoHandler() {
|
|
154
|
+
return (c) => this.handleUserInfoRequest(c.req.raw);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Handler for the OIDC RP-Initiated Logout end-session endpoint.
|
|
158
|
+
* Mount at `GET|POST /end_session`. Answers 404 unless the server was
|
|
159
|
+
* constructed with an `endSession` callback.
|
|
160
|
+
*/
|
|
161
|
+
endSessionHandler() {
|
|
162
|
+
return (c) => this.handleEndSessionRequest(c.req.raw);
|
|
163
|
+
}
|
|
164
|
+
/**
|
|
165
|
+
* Handler for the device authorization endpoint (RFC 8628).
|
|
166
|
+
* Mount at `POST /device_authorization`.
|
|
167
|
+
*/
|
|
168
|
+
deviceAuthorizationHandler() {
|
|
169
|
+
return (c) => this.handleDeviceAuthorizationRequest(c.req.raw);
|
|
170
|
+
}
|
|
171
|
+
/**
|
|
172
|
+
* Returns a Hono app with all standard OAuth2 endpoints mounted at
|
|
173
|
+
* conventional paths, relative to whatever base path the caller mounts it
|
|
174
|
+
* under.
|
|
175
|
+
*
|
|
176
|
+
* - `POST /token`
|
|
177
|
+
* - `GET /authorize`
|
|
178
|
+
* - `POST /revoke`
|
|
179
|
+
* - `POST /introspect`
|
|
180
|
+
* - `POST /device_authorization`
|
|
181
|
+
* - `GET /.well-known/oauth-authorization-server`
|
|
182
|
+
* - `GET /.well-known/openid-configuration`
|
|
183
|
+
* - `GET /jwks` and `GET`/`POST /userinfo` (live when OIDC issuance is
|
|
184
|
+
* configured via `signingKeys`)
|
|
185
|
+
*
|
|
186
|
+
* Mount with `app.route("/oauth2", server.routes({...}))`.
|
|
187
|
+
*
|
|
188
|
+
* Every path and verb above comes from
|
|
189
|
+
* {@link ENDPOINT_PATHS}/{@link ENDPOINT_METHODS}, so the mounted surface and
|
|
190
|
+
* the URLs the server advertises can never drift apart. Users who want custom
|
|
191
|
+
* paths or only a subset of endpoints should mount the individual handler
|
|
192
|
+
* factories instead.
|
|
193
|
+
*/
|
|
194
|
+
routes(options) {
|
|
195
|
+
const handlers = {
|
|
196
|
+
authorization: this.authorizeHandler(options),
|
|
197
|
+
token: this.tokenHandler(),
|
|
198
|
+
revocation: this.revocationHandler(),
|
|
199
|
+
introspection: this.introspectionHandler(),
|
|
200
|
+
deviceAuthorization: this.deviceAuthorizationHandler(),
|
|
201
|
+
jwks: this.jwksHandler(),
|
|
202
|
+
userinfo: this.userInfoHandler(),
|
|
203
|
+
endSession: this.endSessionHandler(),
|
|
204
|
+
metadata: this.metadataHandler(),
|
|
205
|
+
oidcMetadata: this.oidcMetadataHandler(),
|
|
206
|
+
};
|
|
207
|
+
const app = new Hono();
|
|
208
|
+
for (const [key, handler] of Object.entries(handlers)) {
|
|
209
|
+
const endpoint = key;
|
|
210
|
+
app.on([...ENDPOINT_METHODS[endpoint]], ENDPOINT_PATHS[endpoint], handler);
|
|
211
|
+
}
|
|
212
|
+
return app;
|
|
213
|
+
}
|
|
214
|
+
}
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Stateless {@link AuthRequestStorage} for {@link HonoBff}.
|
|
3
|
+
*
|
|
4
|
+
* The pending authorization request — the `state`, its PKCE code verifier, and
|
|
5
|
+
* where to return afterwards — has to survive the round trip to the identity
|
|
6
|
+
* provider. The client's default {@link MemoryAuthRequestStorage} keeps it in
|
|
7
|
+
* the process that started the flow, which breaks on any platform that spreads
|
|
8
|
+
* requests across isolates or instances: `/auth/login` stores the record on one
|
|
9
|
+
* and `/auth/callback` looks for it on another, so sign-in fails intermittently
|
|
10
|
+
* with `unknown state parameter`.
|
|
11
|
+
*
|
|
12
|
+
* {@link EncryptedCookieAuthRequestStorage} carries the record in an encrypted
|
|
13
|
+
* cookie instead (AES-GCM under a server-held secret, the same construction
|
|
14
|
+
* {@link EncryptedCookieSessionStore} uses), so no server-side storage is
|
|
15
|
+
* involved and any instance can complete the flow. Apps that already have a
|
|
16
|
+
* database can implement {@link AuthRequestStorage} against it instead.
|
|
17
|
+
*
|
|
18
|
+
* **Which storage you pick is a reliability decision, not a security one.**
|
|
19
|
+
* Server-side storage on its own says a `state` is pending somewhere — never
|
|
20
|
+
* that *this* browser is the one that started it, so a process-wide store like
|
|
21
|
+
* the memory default would otherwise let anyone's browser complete anyone
|
|
22
|
+
* else's pending sign-in (login CSRF). {@link HonoBff} closes that separately
|
|
23
|
+
* and unconditionally: `/auth/login` also binds the `state` to the browser in
|
|
24
|
+
* a short-lived cookie that `/auth/callback` requires, whichever storage is
|
|
25
|
+
* configured. Choose here on whether every instance can read the record back.
|
|
26
|
+
*
|
|
27
|
+
* @module
|
|
28
|
+
*/
|
|
29
|
+
import type { Context } from "hono";
|
|
30
|
+
import type { AuthRequestStorage } from "../../../client/mod.js";
|
|
31
|
+
/**
|
|
32
|
+
* Cookie attributes for the pending-authorization cookie.
|
|
33
|
+
*
|
|
34
|
+
* The **default** name is prefix-aware: it carries `__Host-` only when every
|
|
35
|
+
* attribute that prefix requires holds, and falls back to the bare name
|
|
36
|
+
* otherwise. An **explicit** {@link name} whose prefix contradicts the other
|
|
37
|
+
* attributes throws from the {@link EncryptedCookieAuthRequestStorage}
|
|
38
|
+
* constructor instead of emitting a cookie every browser silently drops.
|
|
39
|
+
*/
|
|
40
|
+
export interface AuthRequestCookieOptions {
|
|
41
|
+
/**
|
|
42
|
+
* Cookie name. Defaults to `"__Host-oauth2_auth_request"` when the other
|
|
43
|
+
* options satisfy that prefix — {@link secure} on, {@link path} `"/"`, and no
|
|
44
|
+
* {@link domain} — and to `"oauth2_auth_request"` otherwise, because a
|
|
45
|
+
* browser rejects a `__Host-` cookie that breaks any of them.
|
|
46
|
+
*
|
|
47
|
+
* Setting this explicitly to a `__Host-` or `__Secure-` prefixed name throws
|
|
48
|
+
* when the other options contradict the prefix. Prefixes are matched
|
|
49
|
+
* case-insensitively, as browsers match them.
|
|
50
|
+
*/
|
|
51
|
+
name?: string;
|
|
52
|
+
/**
|
|
53
|
+
* Cookie path. Defaults to `"/"`. Any other value drops the default
|
|
54
|
+
* `__Host-` prefix, which requires `Path=/`.
|
|
55
|
+
*/
|
|
56
|
+
path?: string;
|
|
57
|
+
/**
|
|
58
|
+
* Marks the cookie Secure. Defaults to `true`. Turning it off — as local
|
|
59
|
+
* plain-HTTP development needs — drops the default `__Host-` prefix, which
|
|
60
|
+
* requires `Secure`.
|
|
61
|
+
*/
|
|
62
|
+
secure?: boolean;
|
|
63
|
+
/**
|
|
64
|
+
* `SameSite` policy. Defaults to `"Lax"`, which is the strictest value that
|
|
65
|
+
* still survives the identity provider's redirect back to the callback —
|
|
66
|
+
* `"Strict"` withholds the cookie on that navigation and every sign-in
|
|
67
|
+
* fails.
|
|
68
|
+
*
|
|
69
|
+
* `"None"` requires {@link AuthRequestCookieOptions.secure}; the constructor
|
|
70
|
+
* throws on the combination rather than emitting a cookie every modern
|
|
71
|
+
* browser silently drops.
|
|
72
|
+
*/
|
|
73
|
+
sameSite?: "Strict" | "Lax" | "None";
|
|
74
|
+
/**
|
|
75
|
+
* Optional cookie domain. Omitting it (the default) keeps the cookie
|
|
76
|
+
* host-bound; setting it drops the default `__Host-` prefix, which forbids
|
|
77
|
+
* `Domain`.
|
|
78
|
+
*/
|
|
79
|
+
domain?: string;
|
|
80
|
+
}
|
|
81
|
+
/** Options for {@link EncryptedCookieAuthRequestStorage}. */
|
|
82
|
+
export interface EncryptedCookieAuthRequestStorageOptions {
|
|
83
|
+
/**
|
|
84
|
+
* Secret the AES-256 key is derived from; at least 32 bytes. Reuse the
|
|
85
|
+
* secret across instances so any of them can unseal a cookie another sealed.
|
|
86
|
+
*/
|
|
87
|
+
secret: string;
|
|
88
|
+
/** Cookie attribute overrides. */
|
|
89
|
+
cookie?: AuthRequestCookieOptions;
|
|
90
|
+
/**
|
|
91
|
+
* How long a pending request stays valid, in ms. Also the cookie's
|
|
92
|
+
* `Max-Age`. Defaults to 10 minutes, matching the client's
|
|
93
|
+
* `authRequestTtlMs` default.
|
|
94
|
+
*/
|
|
95
|
+
ttlMs?: number;
|
|
96
|
+
/**
|
|
97
|
+
* How many pending requests the cookie carries at once. A second sign-in
|
|
98
|
+
* started in another tab would otherwise evict the first, so its callback
|
|
99
|
+
* would fail. Defaults to 3; the oldest is dropped beyond that.
|
|
100
|
+
*/
|
|
101
|
+
maxPending?: number;
|
|
102
|
+
}
|
|
103
|
+
/**
|
|
104
|
+
* Resolves the {@link AuthRequestStorage} for a single request.
|
|
105
|
+
*
|
|
106
|
+
* {@link HonoBffOptions.authRequestStorage} takes one of these rather than a
|
|
107
|
+
* bare storage because a cookie-backed store can only read and write through
|
|
108
|
+
* the request's {@link Context}. Pass an
|
|
109
|
+
* {@link EncryptedCookieAuthRequestStorage}, or implement `forRequest` over
|
|
110
|
+
* storage of your own.
|
|
111
|
+
*/
|
|
112
|
+
export interface AuthRequestStorageFactory {
|
|
113
|
+
/** Returns the storage bound to `c`, for the duration of that request. */
|
|
114
|
+
forRequest(c: Context): AuthRequestStorage;
|
|
115
|
+
}
|
|
116
|
+
/**
|
|
117
|
+
* Stateless {@link AuthRequestStorage}: the pending authorization requests live
|
|
118
|
+
* in an AES-GCM cookie under a server-held secret, so `/auth/login` and
|
|
119
|
+
* `/auth/callback` need not be served by the same instance.
|
|
120
|
+
*
|
|
121
|
+
* Reach for it whenever the BFF runs on more than one isolate or instance —
|
|
122
|
+
* the client's default in-memory storage fails those deployments with
|
|
123
|
+
* `unknown state parameter`. The AES key is derived on first use and shared by
|
|
124
|
+
* every later request.
|
|
125
|
+
*
|
|
126
|
+
* @example
|
|
127
|
+
* ```ts
|
|
128
|
+
* const bff = new HonoBff({
|
|
129
|
+
* client,
|
|
130
|
+
* sessionStore: new EncryptedCookieSessionStore({ secret }),
|
|
131
|
+
* authRequestStorage: new EncryptedCookieAuthRequestStorage({ secret }),
|
|
132
|
+
* });
|
|
133
|
+
* ```
|
|
134
|
+
*/
|
|
135
|
+
export declare class EncryptedCookieAuthRequestStorage implements AuthRequestStorageFactory {
|
|
136
|
+
#private;
|
|
137
|
+
/**
|
|
138
|
+
* Resolves and validates the cookie name up front; the AES key is derived
|
|
139
|
+
* lazily on the first request that touches the cookie.
|
|
140
|
+
*
|
|
141
|
+
* @throws {Error} When an explicit {@link AuthRequestCookieOptions.name}
|
|
142
|
+
* carries a `__Host-`/`__Secure-` prefix the other cookie options contradict,
|
|
143
|
+
* or when {@link AuthRequestCookieOptions.sameSite} is `"None"` without
|
|
144
|
+
* {@link AuthRequestCookieOptions.secure}.
|
|
145
|
+
*/
|
|
146
|
+
constructor(options: EncryptedCookieAuthRequestStorageOptions);
|
|
147
|
+
/** Returns the storage bound to `c`, for the duration of that request. */
|
|
148
|
+
forRequest(c: Context): AuthRequestStorage;
|
|
149
|
+
}
|
|
150
|
+
/**
|
|
151
|
+
* Convenience factory for {@link EncryptedCookieAuthRequestStorage} — the same
|
|
152
|
+
* as `new EncryptedCookieAuthRequestStorage(options)`, for call sites that
|
|
153
|
+
* prefer a function to a constructor.
|
|
154
|
+
*
|
|
155
|
+
* @example
|
|
156
|
+
* ```ts
|
|
157
|
+
* import { encryptedCookieAuthRequestStorage } from "@udibo/oauth2/hono/bff";
|
|
158
|
+
*
|
|
159
|
+
* const authRequestStorage = encryptedCookieAuthRequestStorage({
|
|
160
|
+
* secret: Deno.env.get("SESSION_SECRET")!,
|
|
161
|
+
* });
|
|
162
|
+
* ```
|
|
163
|
+
*/
|
|
164
|
+
export declare function encryptedCookieAuthRequestStorage(options: EncryptedCookieAuthRequestStorageOptions): EncryptedCookieAuthRequestStorage;
|