@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,138 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discovery-metadata cache shared across `DirectClient` instances, for
|
|
3
|
+
* servers that build a short-lived client per request.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
import type { AuthorizationServerMetadata } from "../models/responses.js";
|
|
8
|
+
/** Default entry lifetime for {@link MemoryDiscoveryCache}: one hour. */
|
|
9
|
+
export declare const DEFAULT_DISCOVERY_TTL_MS: number;
|
|
10
|
+
/** Default entry ceiling for {@link MemoryDiscoveryCache}. */
|
|
11
|
+
export declare const DEFAULT_DISCOVERY_CACHE_MAX_ENTRIES = 100;
|
|
12
|
+
/**
|
|
13
|
+
* What {@link DiscoveryCache.resolve} answers with: the metadata document plus
|
|
14
|
+
* the moment it stops being fresh.
|
|
15
|
+
*
|
|
16
|
+
* A reader holds `metadata` without calling `resolve` again until `expiresAt`,
|
|
17
|
+
* so a cache that costs a round trip is read once per entry lifetime rather
|
|
18
|
+
* than once per endpoint lookup — which is why a remote implementation needs no
|
|
19
|
+
* memo of its own.
|
|
20
|
+
*/
|
|
21
|
+
export interface DiscoveryCacheEntry {
|
|
22
|
+
/** The metadata document for the issuer. */
|
|
23
|
+
metadata: AuthorizationServerMetadata;
|
|
24
|
+
/**
|
|
25
|
+
* Epoch ms at which {@link DiscoveryCacheEntry.metadata} stops being fresh.
|
|
26
|
+
*
|
|
27
|
+
* Report the entry's own expiry, never later: a value further out pins a
|
|
28
|
+
* stale document in every reader. `Infinity` never expires; a value in the
|
|
29
|
+
* past forces a `resolve` call on every lookup.
|
|
30
|
+
*/
|
|
31
|
+
expiresAt: number;
|
|
32
|
+
}
|
|
33
|
+
/**
|
|
34
|
+
* A cache of authorization-server metadata keyed by issuer, shared by any
|
|
35
|
+
* number of `DirectClient` instances.
|
|
36
|
+
*
|
|
37
|
+
* Implement this to back discovery with something other than process memory
|
|
38
|
+
* (Redis, a file, a CDN edge cache). The single {@link DiscoveryCache.resolve}
|
|
39
|
+
* method is get-or-load rather than get/set so an implementation can also
|
|
40
|
+
* collapse concurrent misses into one `load` call — a get/set pair cannot.
|
|
41
|
+
*
|
|
42
|
+
* Metadata is issuer-scoped and public: it carries no client id, secret, or
|
|
43
|
+
* tenant data, so one cache may serve many tenants pointed at the same issuer.
|
|
44
|
+
* Do share a cache across clients that reach an issuer the same way; do not
|
|
45
|
+
* share one between a stubbed transport and live traffic.
|
|
46
|
+
*
|
|
47
|
+
* @example Backing discovery with a store of your own
|
|
48
|
+
* ```ts
|
|
49
|
+
* declare const store: Map<string, { json: string; expiresAt: number }>;
|
|
50
|
+
* const ttlMs = 60 * 60 * 1000;
|
|
51
|
+
*
|
|
52
|
+
* const discoveryCache: DiscoveryCache = {
|
|
53
|
+
* async resolve(issuer, load) {
|
|
54
|
+
* const hit = store.get(issuer);
|
|
55
|
+
* if (hit && hit.expiresAt > Date.now()) {
|
|
56
|
+
* return { metadata: JSON.parse(hit.json), expiresAt: hit.expiresAt };
|
|
57
|
+
* }
|
|
58
|
+
* const metadata = await load();
|
|
59
|
+
* const expiresAt = Date.now() + ttlMs;
|
|
60
|
+
* store.set(issuer, { json: JSON.stringify(metadata), expiresAt });
|
|
61
|
+
* return { metadata, expiresAt };
|
|
62
|
+
* },
|
|
63
|
+
* };
|
|
64
|
+
* ```
|
|
65
|
+
*/
|
|
66
|
+
export interface DiscoveryCache {
|
|
67
|
+
/**
|
|
68
|
+
* Returns the cached entry for `issuer`, or awaits `load` and caches it.
|
|
69
|
+
*
|
|
70
|
+
* `load` must not be called when a fresh entry exists, and concurrent calls
|
|
71
|
+
* for one issuer should share a single `load`. A rejected `load` must not be
|
|
72
|
+
* cached — the rejection propagates and the next call retries. The returned
|
|
73
|
+
* `expiresAt` is what lets a reader skip this call entirely while the
|
|
74
|
+
* document it already holds is still fresh, so it must not outlast the
|
|
75
|
+
* entry.
|
|
76
|
+
*/
|
|
77
|
+
resolve(issuer: string, load: () => Promise<AuthorizationServerMetadata>): Promise<DiscoveryCacheEntry>;
|
|
78
|
+
}
|
|
79
|
+
/** Options for {@link MemoryDiscoveryCache}. */
|
|
80
|
+
export interface MemoryDiscoveryCacheOptions {
|
|
81
|
+
/**
|
|
82
|
+
* How long an entry stays fresh, in ms. Defaults to
|
|
83
|
+
* {@link DEFAULT_DISCOVERY_TTL_MS}; `Infinity` never expires.
|
|
84
|
+
*/
|
|
85
|
+
ttlMs?: number;
|
|
86
|
+
/**
|
|
87
|
+
* Maximum number of issuers held. Defaults to
|
|
88
|
+
* {@link DEFAULT_DISCOVERY_CACHE_MAX_ENTRIES}. Expired entries are dropped
|
|
89
|
+
* first, then the least recently stored, so a multi-tenant server with an
|
|
90
|
+
* unbounded issuer list cannot grow without limit.
|
|
91
|
+
*/
|
|
92
|
+
maxEntries?: number;
|
|
93
|
+
}
|
|
94
|
+
/**
|
|
95
|
+
* In-memory {@link DiscoveryCache}: TTL entries plus in-flight de-duplication,
|
|
96
|
+
* so a burst of requests against a cold issuer triggers exactly one discovery
|
|
97
|
+
* fetch. Failures are never cached.
|
|
98
|
+
*
|
|
99
|
+
* Construct one per process (or per trust boundary) and hand it to every
|
|
100
|
+
* client that should share it.
|
|
101
|
+
*
|
|
102
|
+
* Because one document is handed to every client on that issuer, stored
|
|
103
|
+
* metadata is deep-frozen: a consumer that tries to patch a field it read
|
|
104
|
+
* throws rather than silently rewriting the entry every other client sees.
|
|
105
|
+
* Entries are evicted least-recently-used, so one issuer churning through the
|
|
106
|
+
* cache cannot evict a busier one.
|
|
107
|
+
*
|
|
108
|
+
* @example
|
|
109
|
+
* ```ts
|
|
110
|
+
* const discoveryCache = new MemoryDiscoveryCache();
|
|
111
|
+
*
|
|
112
|
+
* // Per request: a fresh client, but at most one discovery fetch per hour.
|
|
113
|
+
* const client = new DirectClient({
|
|
114
|
+
* clientId,
|
|
115
|
+
* clientSecret,
|
|
116
|
+
* issuer: "https://sso.example",
|
|
117
|
+
* discoveryCache,
|
|
118
|
+
* });
|
|
119
|
+
* ```
|
|
120
|
+
*/
|
|
121
|
+
export declare class MemoryDiscoveryCache implements DiscoveryCache {
|
|
122
|
+
#private;
|
|
123
|
+
/** Creates a cache with the given TTL and entry ceiling. */
|
|
124
|
+
constructor(options?: MemoryDiscoveryCacheOptions);
|
|
125
|
+
/**
|
|
126
|
+
* Returns the fresh cached entry for `issuer`, joins the in-flight `load`
|
|
127
|
+
* for it, or starts one. Trailing slashes on `issuer` are insignificant. A
|
|
128
|
+
* hit counts as a use, so a busy issuer outlives an idle one under
|
|
129
|
+
* {@link MemoryDiscoveryCacheOptions.maxEntries} pressure. The entry's
|
|
130
|
+
* `expiresAt` is when this cache would reload, so a reader holding it may
|
|
131
|
+
* skip the call until then.
|
|
132
|
+
*/
|
|
133
|
+
resolve(issuer: string, load: () => Promise<AuthorizationServerMetadata>): Promise<DiscoveryCacheEntry>;
|
|
134
|
+
/** Drops the entry for `issuer`, forcing the next resolve to re-fetch. */
|
|
135
|
+
delete(issuer: string): void;
|
|
136
|
+
/** Drops every entry. In-flight loads still settle for their callers. */
|
|
137
|
+
clear(): void;
|
|
138
|
+
}
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Discovery-metadata cache shared across `DirectClient` instances, for
|
|
3
|
+
* servers that build a short-lived client per request.
|
|
4
|
+
*
|
|
5
|
+
* @module
|
|
6
|
+
*/
|
|
7
|
+
/** Default entry lifetime for {@link MemoryDiscoveryCache}: one hour. */
|
|
8
|
+
export const DEFAULT_DISCOVERY_TTL_MS = 60 * 60 * 1000;
|
|
9
|
+
/** Default entry ceiling for {@link MemoryDiscoveryCache}. */
|
|
10
|
+
export const DEFAULT_DISCOVERY_CACHE_MAX_ENTRIES = 100;
|
|
11
|
+
/**
|
|
12
|
+
* In-memory {@link DiscoveryCache}: TTL entries plus in-flight de-duplication,
|
|
13
|
+
* so a burst of requests against a cold issuer triggers exactly one discovery
|
|
14
|
+
* fetch. Failures are never cached.
|
|
15
|
+
*
|
|
16
|
+
* Construct one per process (or per trust boundary) and hand it to every
|
|
17
|
+
* client that should share it.
|
|
18
|
+
*
|
|
19
|
+
* Because one document is handed to every client on that issuer, stored
|
|
20
|
+
* metadata is deep-frozen: a consumer that tries to patch a field it read
|
|
21
|
+
* throws rather than silently rewriting the entry every other client sees.
|
|
22
|
+
* Entries are evicted least-recently-used, so one issuer churning through the
|
|
23
|
+
* cache cannot evict a busier one.
|
|
24
|
+
*
|
|
25
|
+
* @example
|
|
26
|
+
* ```ts
|
|
27
|
+
* const discoveryCache = new MemoryDiscoveryCache();
|
|
28
|
+
*
|
|
29
|
+
* // Per request: a fresh client, but at most one discovery fetch per hour.
|
|
30
|
+
* const client = new DirectClient({
|
|
31
|
+
* clientId,
|
|
32
|
+
* clientSecret,
|
|
33
|
+
* issuer: "https://sso.example",
|
|
34
|
+
* discoveryCache,
|
|
35
|
+
* });
|
|
36
|
+
* ```
|
|
37
|
+
*/
|
|
38
|
+
export class MemoryDiscoveryCache {
|
|
39
|
+
#ttlMs;
|
|
40
|
+
#maxEntries;
|
|
41
|
+
#entries = new Map();
|
|
42
|
+
#inFlight = new Map();
|
|
43
|
+
/** Creates a cache with the given TTL and entry ceiling. */
|
|
44
|
+
constructor(options = {}) {
|
|
45
|
+
this.#ttlMs = options.ttlMs ?? DEFAULT_DISCOVERY_TTL_MS;
|
|
46
|
+
this.#maxEntries = options.maxEntries ??
|
|
47
|
+
DEFAULT_DISCOVERY_CACHE_MAX_ENTRIES;
|
|
48
|
+
}
|
|
49
|
+
/**
|
|
50
|
+
* Returns the fresh cached entry for `issuer`, joins the in-flight `load`
|
|
51
|
+
* for it, or starts one. Trailing slashes on `issuer` are insignificant. A
|
|
52
|
+
* hit counts as a use, so a busy issuer outlives an idle one under
|
|
53
|
+
* {@link MemoryDiscoveryCacheOptions.maxEntries} pressure. The entry's
|
|
54
|
+
* `expiresAt` is when this cache would reload, so a reader holding it may
|
|
55
|
+
* skip the call until then.
|
|
56
|
+
*/
|
|
57
|
+
resolve(issuer, load) {
|
|
58
|
+
const key = normalizeIssuer(issuer);
|
|
59
|
+
const entry = this.#entries.get(key);
|
|
60
|
+
if (entry) {
|
|
61
|
+
if (entry.expiresAt > Date.now()) {
|
|
62
|
+
this.#entries.delete(key);
|
|
63
|
+
this.#entries.set(key, entry);
|
|
64
|
+
return Promise.resolve({ ...entry });
|
|
65
|
+
}
|
|
66
|
+
this.#entries.delete(key);
|
|
67
|
+
}
|
|
68
|
+
const pending = this.#inFlight.get(key);
|
|
69
|
+
if (pending)
|
|
70
|
+
return pending;
|
|
71
|
+
const promise = load().then((metadata) => this.#store(key, metadata));
|
|
72
|
+
this.#inFlight.set(key, promise);
|
|
73
|
+
const settle = () => {
|
|
74
|
+
if (this.#inFlight.get(key) === promise)
|
|
75
|
+
this.#inFlight.delete(key);
|
|
76
|
+
};
|
|
77
|
+
promise.then(settle, settle);
|
|
78
|
+
return promise;
|
|
79
|
+
}
|
|
80
|
+
/** Drops the entry for `issuer`, forcing the next resolve to re-fetch. */
|
|
81
|
+
delete(issuer) {
|
|
82
|
+
this.#entries.delete(normalizeIssuer(issuer));
|
|
83
|
+
}
|
|
84
|
+
/** Drops every entry. In-flight loads still settle for their callers. */
|
|
85
|
+
clear() {
|
|
86
|
+
this.#entries.clear();
|
|
87
|
+
}
|
|
88
|
+
#store(key, metadata) {
|
|
89
|
+
const entry = {
|
|
90
|
+
metadata: deepFreeze(metadata),
|
|
91
|
+
expiresAt: Date.now() + this.#ttlMs,
|
|
92
|
+
};
|
|
93
|
+
this.#entries.delete(key);
|
|
94
|
+
this.#entries.set(key, entry);
|
|
95
|
+
this.#prune();
|
|
96
|
+
return { ...entry };
|
|
97
|
+
}
|
|
98
|
+
#prune() {
|
|
99
|
+
const now = Date.now();
|
|
100
|
+
for (const [key, entry] of this.#entries) {
|
|
101
|
+
if (entry.expiresAt <= now)
|
|
102
|
+
this.#entries.delete(key);
|
|
103
|
+
}
|
|
104
|
+
while (this.#entries.size > this.#maxEntries) {
|
|
105
|
+
const leastRecentlyUsed = this.#entries.keys().next();
|
|
106
|
+
if (leastRecentlyUsed.done)
|
|
107
|
+
return;
|
|
108
|
+
this.#entries.delete(leastRecentlyUsed.value);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
}
|
|
112
|
+
function normalizeIssuer(issuer) {
|
|
113
|
+
return issuer.replace(/\/+$/, "");
|
|
114
|
+
}
|
|
115
|
+
function deepFreeze(value) {
|
|
116
|
+
if (typeof value !== "object" || value === null || Object.isFrozen(value)) {
|
|
117
|
+
return value;
|
|
118
|
+
}
|
|
119
|
+
Object.freeze(value);
|
|
120
|
+
for (const key of Object.getOwnPropertyNames(value)) {
|
|
121
|
+
deepFreeze(value[key]);
|
|
122
|
+
}
|
|
123
|
+
return value;
|
|
124
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event types emitted by the OAuth2 clients.
|
|
3
|
+
*
|
|
4
|
+
* Framework adapters (React, Vue, etc.) subscribe to these to re-render on
|
|
5
|
+
* authentication state changes without having to poll the client for state.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
import type { TokenBundle } from "./storage.js";
|
|
10
|
+
/** The authenticated user has been resolved or has changed. */
|
|
11
|
+
export interface AuthenticatedEvent {
|
|
12
|
+
/** Discriminant tag for this event variant. */
|
|
13
|
+
type: "authenticated";
|
|
14
|
+
/** The token bundle that was just persisted for the session. */
|
|
15
|
+
tokens: TokenBundle;
|
|
16
|
+
}
|
|
17
|
+
/** The client has cleared its session and the user is no longer authenticated. */
|
|
18
|
+
export interface LoggedOutEvent {
|
|
19
|
+
/** Discriminant tag for this event variant. */
|
|
20
|
+
type: "logged_out";
|
|
21
|
+
/** Why the session ended. */
|
|
22
|
+
reason: "user" | "refresh_failed" | "invalid_grant" | "session_expired";
|
|
23
|
+
}
|
|
24
|
+
/** A refresh has just completed; the access token has rotated. */
|
|
25
|
+
export interface TokenRefreshedEvent {
|
|
26
|
+
/** Discriminant tag for this event variant. */
|
|
27
|
+
type: "token_refreshed";
|
|
28
|
+
/** The rotated token bundle now in effect. */
|
|
29
|
+
tokens: TokenBundle;
|
|
30
|
+
}
|
|
31
|
+
/** An operation failed. Subscribers can surface this to the user. */
|
|
32
|
+
export interface ErrorEvent {
|
|
33
|
+
/** Discriminant tag for this event variant. */
|
|
34
|
+
type: "error";
|
|
35
|
+
/** The thrown value; an {@linkcode OAuth2Error} when the failure was protocol-level. */
|
|
36
|
+
error: unknown;
|
|
37
|
+
}
|
|
38
|
+
/** Every event type the client emits. */
|
|
39
|
+
export type OAuth2ClientEvent = AuthenticatedEvent | LoggedOutEvent | TokenRefreshedEvent | ErrorEvent;
|
|
40
|
+
/** Subscriber callback. Return values are ignored. */
|
|
41
|
+
export type OAuth2ClientEventListener = (event: OAuth2ClientEvent) => void;
|
|
42
|
+
/** Minimal event bus for the client to avoid pulling in a dependency. */
|
|
43
|
+
export declare class EventBus {
|
|
44
|
+
#private;
|
|
45
|
+
/** Registers `listener` and returns a function that removes it. */
|
|
46
|
+
subscribe(listener: OAuth2ClientEventListener): () => void;
|
|
47
|
+
/**
|
|
48
|
+
* Delivers `event` to every subscriber. A listener that throws is isolated
|
|
49
|
+
* so delivery to the remaining subscribers still completes.
|
|
50
|
+
*/
|
|
51
|
+
emit(event: OAuth2ClientEvent): void;
|
|
52
|
+
/** Removes all subscribers. */
|
|
53
|
+
clear(): void;
|
|
54
|
+
}
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Event types emitted by the OAuth2 clients.
|
|
3
|
+
*
|
|
4
|
+
* Framework adapters (React, Vue, etc.) subscribe to these to re-render on
|
|
5
|
+
* authentication state changes without having to poll the client for state.
|
|
6
|
+
*
|
|
7
|
+
* @module
|
|
8
|
+
*/
|
|
9
|
+
/** Minimal event bus for the client to avoid pulling in a dependency. */
|
|
10
|
+
export class EventBus {
|
|
11
|
+
#listeners = new Set();
|
|
12
|
+
/** Registers `listener` and returns a function that removes it. */
|
|
13
|
+
subscribe(listener) {
|
|
14
|
+
this.#listeners.add(listener);
|
|
15
|
+
return () => {
|
|
16
|
+
this.#listeners.delete(listener);
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
/**
|
|
20
|
+
* Delivers `event` to every subscriber. A listener that throws is isolated
|
|
21
|
+
* so delivery to the remaining subscribers still completes.
|
|
22
|
+
*/
|
|
23
|
+
emit(event) {
|
|
24
|
+
for (const listener of this.#listeners) {
|
|
25
|
+
try {
|
|
26
|
+
listener(event);
|
|
27
|
+
}
|
|
28
|
+
catch {
|
|
29
|
+
// One bad subscriber must not break delivery to others.
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
/** Removes all subscribers. */
|
|
34
|
+
clear() {
|
|
35
|
+
this.#listeners.clear();
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth2 clients for browsers, CLIs, servers, and framework adapters.
|
|
3
|
+
*
|
|
4
|
+
* Pick by who holds the tokens:
|
|
5
|
+
*
|
|
6
|
+
* - {@link BffClient} — a Backend-for-Frontend holds them. The browser only
|
|
7
|
+
* talks to the BFF's `/auth/*` routes with the session cookie, and never
|
|
8
|
+
* sees a token.
|
|
9
|
+
* - {@link DirectClient} — this process holds them. Drives the standard
|
|
10
|
+
* grants (authorization code + PKCE, refresh, client credentials, device
|
|
11
|
+
* authorization, introspection, revocation) against any RFC 6749-compliant
|
|
12
|
+
* authorization server.
|
|
13
|
+
*
|
|
14
|
+
* Both extend {@link OAuth2ClientBase}, which is what code that shouldn't
|
|
15
|
+
* care — the React adapter's `<OAuth2Provider>`, a shared UI helper — should
|
|
16
|
+
* accept.
|
|
17
|
+
*
|
|
18
|
+
* Storage interfaces (token / refresh-token / auth-request) default to
|
|
19
|
+
* in-memory implementations suitable for servers and tests; browser
|
|
20
|
+
* applications should substitute the appropriate persistent variants.
|
|
21
|
+
*
|
|
22
|
+
* @module
|
|
23
|
+
*/
|
|
24
|
+
import "../_dnt.polyfills.js";
|
|
25
|
+
export { type BaseLoginOptions, type BaseOptions, type LoginRedirect, type LogoutOptions, type LogoutRedirect, OAuth2ClientBase, type SessionState, SIGNED_OUT, type UserInfoClaims, } from "./base.js";
|
|
26
|
+
export { BffClient, type BffClientOptions, type BffEndpoints, } from "./bff-client.js";
|
|
27
|
+
export { type AuthorizationCallbackResult, type AuthorizationRedirect, type AuthorizationServerEndpoints, type DeviceAuthorizationOptions, DirectClient, type DirectClientOptions, type ExchangeOptions, type ExchangeResult, type IntrospectionResult, type LoginOptions, type PollDeviceTokenOptions, } from "./direct-client.js";
|
|
28
|
+
export { DEFAULT_DISCOVERY_CACHE_MAX_ENTRIES, DEFAULT_DISCOVERY_TTL_MS, type DiscoveryCache, type DiscoveryCacheEntry, MemoryDiscoveryCache, type MemoryDiscoveryCacheOptions, } from "./discovery-cache.js";
|
|
29
|
+
export { type AuthenticatedEvent, type ErrorEvent, type LoggedOutEvent, type OAuth2ClientEvent, type OAuth2ClientEventListener, type TokenRefreshedEvent, } from "./events.js";
|
|
30
|
+
export { type AuthRequestRecord, type AuthRequestStorage, MemoryAuthRequestStorage, MemoryRefreshTokenStorage, MemoryTokenStorage, type RefreshTokenStorage, type TokenBundle, type TokenStorage, } from "./storage.js";
|
|
31
|
+
export { checkPermissions, type CheckPermissionsOptions, type CheckPermissionsResult, type CheckResource, } from "./check.js";
|
|
32
|
+
export { Authorization, authorizationFromClaims, } from "../models/authorization.js";
|
|
33
|
+
export type { OrganizationContext } from "../models/authorization.js";
|
|
34
|
+
export { isOAuth2Error, OAuth2Error } from "../errors.js";
|
|
35
|
+
export { IndexedDBRefreshTokenStorage, type IndexedDBRefreshTokenStorageOptions, SessionStorageAuthRequestStorage, type SessionStorageAuthRequestStorageOptions, } from "./browser-storage.js";
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* OAuth2 clients for browsers, CLIs, servers, and framework adapters.
|
|
3
|
+
*
|
|
4
|
+
* Pick by who holds the tokens:
|
|
5
|
+
*
|
|
6
|
+
* - {@link BffClient} — a Backend-for-Frontend holds them. The browser only
|
|
7
|
+
* talks to the BFF's `/auth/*` routes with the session cookie, and never
|
|
8
|
+
* sees a token.
|
|
9
|
+
* - {@link DirectClient} — this process holds them. Drives the standard
|
|
10
|
+
* grants (authorization code + PKCE, refresh, client credentials, device
|
|
11
|
+
* authorization, introspection, revocation) against any RFC 6749-compliant
|
|
12
|
+
* authorization server.
|
|
13
|
+
*
|
|
14
|
+
* Both extend {@link OAuth2ClientBase}, which is what code that shouldn't
|
|
15
|
+
* care — the React adapter's `<OAuth2Provider>`, a shared UI helper — should
|
|
16
|
+
* accept.
|
|
17
|
+
*
|
|
18
|
+
* Storage interfaces (token / refresh-token / auth-request) default to
|
|
19
|
+
* in-memory implementations suitable for servers and tests; browser
|
|
20
|
+
* applications should substitute the appropriate persistent variants.
|
|
21
|
+
*
|
|
22
|
+
* @module
|
|
23
|
+
*/
|
|
24
|
+
import "../_dnt.polyfills.js";
|
|
25
|
+
export { OAuth2ClientBase, SIGNED_OUT, } from "./base.js";
|
|
26
|
+
export { BffClient, } from "./bff-client.js";
|
|
27
|
+
export { DirectClient, } from "./direct-client.js";
|
|
28
|
+
export { DEFAULT_DISCOVERY_CACHE_MAX_ENTRIES, DEFAULT_DISCOVERY_TTL_MS, MemoryDiscoveryCache, } from "./discovery-cache.js";
|
|
29
|
+
export { MemoryAuthRequestStorage, MemoryRefreshTokenStorage, MemoryTokenStorage, } from "./storage.js";
|
|
30
|
+
export { checkPermissions, } from "./check.js";
|
|
31
|
+
export { Authorization, authorizationFromClaims, } from "../models/authorization.js";
|
|
32
|
+
export { isOAuth2Error, OAuth2Error } from "../errors.js";
|
|
33
|
+
export { IndexedDBRefreshTokenStorage, SessionStorageAuthRequestStorage, } from "./browser-storage.js";
|
|
@@ -0,0 +1,127 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage interfaces used by `DirectClient`. A `BffClient` holds no
|
|
3
|
+
* tokens, so none of this applies to it.
|
|
4
|
+
*
|
|
5
|
+
* The client keeps three pieces of mutable state across calls:
|
|
6
|
+
* - the current token bundle (access + refresh + expiry + id token),
|
|
7
|
+
* - the refresh token specifically (may be split into a harder-to-exfiltrate
|
|
8
|
+
* store than the access token — e.g. IndexedDB or a Web Worker),
|
|
9
|
+
* - a short-lived auth-request map (`state` → `{ codeVerifier, returnTo, … }`)
|
|
10
|
+
* used to correlate an authorize redirect with its callback.
|
|
11
|
+
*
|
|
12
|
+
* The defaults here are all in-memory and live only for the process / tab
|
|
13
|
+
* lifetime. Browser applications that need persistence across reloads should
|
|
14
|
+
* plug in the appropriate implementation — most commonly:
|
|
15
|
+
* - `MemoryTokenStorage` for access tokens (always),
|
|
16
|
+
* - an `IndexedDB`-backed `RefreshTokenStorage` for refresh tokens (so they
|
|
17
|
+
* are not readable via `document.cookie` or `localStorage`),
|
|
18
|
+
* - `sessionStorage`-backed `AuthRequestStorage` for the redirect state map.
|
|
19
|
+
*
|
|
20
|
+
* @module
|
|
21
|
+
*/
|
|
22
|
+
/** The set of fields the client persists as one logical unit. */
|
|
23
|
+
export interface TokenBundle {
|
|
24
|
+
/** The current access token. */
|
|
25
|
+
accessToken: string;
|
|
26
|
+
/** When the access token expires (epoch ms). */
|
|
27
|
+
accessTokenExpiresAt?: number;
|
|
28
|
+
/** The scope granted to this token, space-delimited. */
|
|
29
|
+
scope?: string;
|
|
30
|
+
/** Token type — always "Bearer" in this client. */
|
|
31
|
+
tokenType: "Bearer";
|
|
32
|
+
/** Optional OIDC ID token string (not verified by the client). */
|
|
33
|
+
idToken?: string;
|
|
34
|
+
}
|
|
35
|
+
/** Persists the current token bundle (access token, expiry, scope, id_token). */
|
|
36
|
+
export interface TokenStorage {
|
|
37
|
+
/** Returns the stored bundle, or `null` when none has been persisted. */
|
|
38
|
+
get(): Promise<TokenBundle | null> | TokenBundle | null;
|
|
39
|
+
/** Replaces the stored bundle with {@linkcode value}. */
|
|
40
|
+
set(value: TokenBundle): Promise<void> | void;
|
|
41
|
+
/** Discards the stored bundle. */
|
|
42
|
+
clear(): Promise<void> | void;
|
|
43
|
+
}
|
|
44
|
+
/**
|
|
45
|
+
* Persists the refresh token independently from the access token. Kept
|
|
46
|
+
* separate so applications can harden refresh-token storage (IndexedDB,
|
|
47
|
+
* Web Worker, or a server-side session cookie) without changing where
|
|
48
|
+
* short-lived access tokens live.
|
|
49
|
+
*/
|
|
50
|
+
export interface RefreshTokenStorage {
|
|
51
|
+
/** Returns the stored refresh token, or `null` when none has been persisted. */
|
|
52
|
+
get(): Promise<string | null> | string | null;
|
|
53
|
+
/** Replaces the stored refresh token with {@linkcode value}. */
|
|
54
|
+
set(value: string): Promise<void> | void;
|
|
55
|
+
/** Discards the stored refresh token. */
|
|
56
|
+
clear(): Promise<void> | void;
|
|
57
|
+
}
|
|
58
|
+
/** Correlates an authorize redirect with its callback. */
|
|
59
|
+
export interface AuthRequestRecord {
|
|
60
|
+
/** PKCE code verifier paired with the `code_challenge` sent to authorize. */
|
|
61
|
+
codeVerifier: string;
|
|
62
|
+
/** Application URL to navigate to after the callback completes. */
|
|
63
|
+
returnTo?: string;
|
|
64
|
+
/** Scope requested for this authorization, space-delimited. */
|
|
65
|
+
scope?: string;
|
|
66
|
+
/** When the request was created (epoch ms), used for TTL expiry. */
|
|
67
|
+
createdAt: number;
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Short-lived map from the authorization request `state` parameter to the
|
|
71
|
+
* PKCE verifier / `returnTo` / scope it was built with. Must survive the
|
|
72
|
+
* authorize-redirect round-trip but must not outlive the tab, and must
|
|
73
|
+
* never contain access or refresh tokens.
|
|
74
|
+
*/
|
|
75
|
+
export interface AuthRequestStorage {
|
|
76
|
+
/**
|
|
77
|
+
* Returns the record for {@linkcode state}, or `null` if absent or expired.
|
|
78
|
+
* Implementations may prune the entry when returning `null` for an expired one.
|
|
79
|
+
*/
|
|
80
|
+
get(state: string): Promise<AuthRequestRecord | null> | AuthRequestRecord | null;
|
|
81
|
+
/** Stores {@linkcode value} under {@linkcode state} before the authorize redirect. */
|
|
82
|
+
set(state: string, value: AuthRequestRecord): Promise<void> | void;
|
|
83
|
+
/** Removes one entry (called after successful callback consumption). */
|
|
84
|
+
delete(state: string): Promise<void> | void;
|
|
85
|
+
/** Removes every entry. Called on logout. */
|
|
86
|
+
clear(): Promise<void> | void;
|
|
87
|
+
}
|
|
88
|
+
/** Default in-memory {@link TokenStorage}. Data is lost when the process exits. */
|
|
89
|
+
export declare class MemoryTokenStorage implements TokenStorage {
|
|
90
|
+
#private;
|
|
91
|
+
/** Returns the in-memory bundle, or `null` if none has been set. */
|
|
92
|
+
get(): TokenBundle | null;
|
|
93
|
+
/** Replaces the in-memory bundle with {@linkcode value}. */
|
|
94
|
+
set(value: TokenBundle): void;
|
|
95
|
+
/** Discards the in-memory bundle. */
|
|
96
|
+
clear(): void;
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Default in-memory {@link RefreshTokenStorage}. Data is lost when the
|
|
100
|
+
* process exits.
|
|
101
|
+
*/
|
|
102
|
+
export declare class MemoryRefreshTokenStorage implements RefreshTokenStorage {
|
|
103
|
+
#private;
|
|
104
|
+
/** Returns the in-memory refresh token, or `null` if none has been set. */
|
|
105
|
+
get(): string | null;
|
|
106
|
+
/** Replaces the in-memory refresh token with {@linkcode value}. */
|
|
107
|
+
set(value: string): void;
|
|
108
|
+
/** Discards the in-memory refresh token. */
|
|
109
|
+
clear(): void;
|
|
110
|
+
}
|
|
111
|
+
/**
|
|
112
|
+
* Default in-memory {@link AuthRequestStorage}. Data is lost when the
|
|
113
|
+
* process exits — fine for server-side / CLI usage. Browser apps should
|
|
114
|
+
* plug in a `sessionStorage`-backed implementation so the record survives
|
|
115
|
+
* the authorize-redirect round-trip.
|
|
116
|
+
*/
|
|
117
|
+
export declare class MemoryAuthRequestStorage implements AuthRequestStorage {
|
|
118
|
+
#private;
|
|
119
|
+
/** Returns the record for {@linkcode state}, or `null` if none is stored. */
|
|
120
|
+
get(state: string): AuthRequestRecord | null;
|
|
121
|
+
/** Stores {@linkcode value} under {@linkcode state}. */
|
|
122
|
+
set(state: string, value: AuthRequestRecord): void;
|
|
123
|
+
/** Removes the record for {@linkcode state}. */
|
|
124
|
+
delete(state: string): void;
|
|
125
|
+
/** Removes every stored record. */
|
|
126
|
+
clear(): void;
|
|
127
|
+
}
|
|
@@ -0,0 +1,81 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Storage interfaces used by `DirectClient`. A `BffClient` holds no
|
|
3
|
+
* tokens, so none of this applies to it.
|
|
4
|
+
*
|
|
5
|
+
* The client keeps three pieces of mutable state across calls:
|
|
6
|
+
* - the current token bundle (access + refresh + expiry + id token),
|
|
7
|
+
* - the refresh token specifically (may be split into a harder-to-exfiltrate
|
|
8
|
+
* store than the access token — e.g. IndexedDB or a Web Worker),
|
|
9
|
+
* - a short-lived auth-request map (`state` → `{ codeVerifier, returnTo, … }`)
|
|
10
|
+
* used to correlate an authorize redirect with its callback.
|
|
11
|
+
*
|
|
12
|
+
* The defaults here are all in-memory and live only for the process / tab
|
|
13
|
+
* lifetime. Browser applications that need persistence across reloads should
|
|
14
|
+
* plug in the appropriate implementation — most commonly:
|
|
15
|
+
* - `MemoryTokenStorage` for access tokens (always),
|
|
16
|
+
* - an `IndexedDB`-backed `RefreshTokenStorage` for refresh tokens (so they
|
|
17
|
+
* are not readable via `document.cookie` or `localStorage`),
|
|
18
|
+
* - `sessionStorage`-backed `AuthRequestStorage` for the redirect state map.
|
|
19
|
+
*
|
|
20
|
+
* @module
|
|
21
|
+
*/
|
|
22
|
+
/** Default in-memory {@link TokenStorage}. Data is lost when the process exits. */
|
|
23
|
+
export class MemoryTokenStorage {
|
|
24
|
+
#bundle = null;
|
|
25
|
+
/** Returns the in-memory bundle, or `null` if none has been set. */
|
|
26
|
+
get() {
|
|
27
|
+
return this.#bundle;
|
|
28
|
+
}
|
|
29
|
+
/** Replaces the in-memory bundle with {@linkcode value}. */
|
|
30
|
+
set(value) {
|
|
31
|
+
this.#bundle = value;
|
|
32
|
+
}
|
|
33
|
+
/** Discards the in-memory bundle. */
|
|
34
|
+
clear() {
|
|
35
|
+
this.#bundle = null;
|
|
36
|
+
}
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Default in-memory {@link RefreshTokenStorage}. Data is lost when the
|
|
40
|
+
* process exits.
|
|
41
|
+
*/
|
|
42
|
+
export class MemoryRefreshTokenStorage {
|
|
43
|
+
#token = null;
|
|
44
|
+
/** Returns the in-memory refresh token, or `null` if none has been set. */
|
|
45
|
+
get() {
|
|
46
|
+
return this.#token;
|
|
47
|
+
}
|
|
48
|
+
/** Replaces the in-memory refresh token with {@linkcode value}. */
|
|
49
|
+
set(value) {
|
|
50
|
+
this.#token = value;
|
|
51
|
+
}
|
|
52
|
+
/** Discards the in-memory refresh token. */
|
|
53
|
+
clear() {
|
|
54
|
+
this.#token = null;
|
|
55
|
+
}
|
|
56
|
+
}
|
|
57
|
+
/**
|
|
58
|
+
* Default in-memory {@link AuthRequestStorage}. Data is lost when the
|
|
59
|
+
* process exits — fine for server-side / CLI usage. Browser apps should
|
|
60
|
+
* plug in a `sessionStorage`-backed implementation so the record survives
|
|
61
|
+
* the authorize-redirect round-trip.
|
|
62
|
+
*/
|
|
63
|
+
export class MemoryAuthRequestStorage {
|
|
64
|
+
#records = new Map();
|
|
65
|
+
/** Returns the record for {@linkcode state}, or `null` if none is stored. */
|
|
66
|
+
get(state) {
|
|
67
|
+
return this.#records.get(state) ?? null;
|
|
68
|
+
}
|
|
69
|
+
/** Stores {@linkcode value} under {@linkcode state}. */
|
|
70
|
+
set(state, value) {
|
|
71
|
+
this.#records.set(state, value);
|
|
72
|
+
}
|
|
73
|
+
/** Removes the record for {@linkcode state}. */
|
|
74
|
+
delete(state) {
|
|
75
|
+
this.#records.delete(state);
|
|
76
|
+
}
|
|
77
|
+
/** Removes every stored record. */
|
|
78
|
+
clear() {
|
|
79
|
+
this.#records.clear();
|
|
80
|
+
}
|
|
81
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Make an assertion that `actual` and `expected` are almost equal numbers
|
|
3
|
+
* through a given tolerance. It can be used to take into account IEEE-754
|
|
4
|
+
* double-precision floating-point representation limitations. If the values
|
|
5
|
+
* are not almost equal then throw.
|
|
6
|
+
*
|
|
7
|
+
* The default tolerance is one hundred thousandth of a percent of the
|
|
8
|
+
* expected value.
|
|
9
|
+
*
|
|
10
|
+
* @example Usage
|
|
11
|
+
* ```ts ignore
|
|
12
|
+
* import { assertAlmostEquals } from "@std/assert";
|
|
13
|
+
*
|
|
14
|
+
* assertAlmostEquals(0.01, 0.02); // Throws
|
|
15
|
+
* assertAlmostEquals(1e-8, 1e-9); // Throws
|
|
16
|
+
* assertAlmostEquals(1.000000001e-8, 1.000000002e-8); // Doesn't throw
|
|
17
|
+
* assertAlmostEquals(0.01, 0.02, 0.1); // Doesn't throw
|
|
18
|
+
* assertAlmostEquals(0.1 + 0.2, 0.3, 1e-16); // Doesn't throw
|
|
19
|
+
* assertAlmostEquals(0.1 + 0.2, 0.3, 1e-17); // Throws
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @param actual The actual value to compare.
|
|
23
|
+
* @param expected The expected value to compare.
|
|
24
|
+
* @param tolerance The tolerance to consider the values almost equal. The
|
|
25
|
+
* default is one hundred thousandth of a percent of the expected value.
|
|
26
|
+
* @param msg The optional message to include in the error.
|
|
27
|
+
* @throws {AssertionError} If the values are not almost equal.
|
|
28
|
+
*/
|
|
29
|
+
export declare function assertAlmostEquals(actual: number, expected: number, tolerance?: number, msg?: string): void;
|