@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,179 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract test suite for {@link TokenFlowStore} implementations — the storage
|
|
3
|
+
* behind verification links, password-reset links, and magic links.
|
|
4
|
+
*
|
|
5
|
+
* The load-bearing method is `markConsumed`: it is what makes a link
|
|
6
|
+
* single-use, and only a conditional write survives two requests redeeming one
|
|
7
|
+
* link at the same time. This suite issues those two requests.
|
|
8
|
+
*
|
|
9
|
+
* @example Verify a database-backed store
|
|
10
|
+
* ```ts
|
|
11
|
+
* import { runTokenFlowStoreContractTests } from "@udibo/oauth2/testing/contract";
|
|
12
|
+
* import type { TokenFlowStore } from "@udibo/oauth2/identity";
|
|
13
|
+
*
|
|
14
|
+
* declare function freshTokenFlowStore(): Promise<TokenFlowStore>;
|
|
15
|
+
*
|
|
16
|
+
* runTokenFlowStoreContractTests({
|
|
17
|
+
* describeName: "DrizzleTokenFlowStore satisfies TokenFlowStore contract",
|
|
18
|
+
* makeStore: freshTokenFlowStore,
|
|
19
|
+
* });
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* @module
|
|
23
|
+
*/
|
|
24
|
+
import { assert, assertEquals, assertStrictEquals } from "../../deps/jsr.io/@std/assert/1.0.19/mod.js";
|
|
25
|
+
import { beforeEach, describe, it } from "../../deps/jsr.io/@std/testing/1.0.20/bdd.js";
|
|
26
|
+
const PURPOSE = "password-reset";
|
|
27
|
+
const OTHER_PURPOSE = "email-verification";
|
|
28
|
+
const SUBJECT = "user-1";
|
|
29
|
+
const OTHER_SUBJECT = "user-2";
|
|
30
|
+
function countTrue(results) {
|
|
31
|
+
return results.filter((result) => result).length;
|
|
32
|
+
}
|
|
33
|
+
function record(overrides) {
|
|
34
|
+
const now = Date.now();
|
|
35
|
+
return {
|
|
36
|
+
purpose: PURPOSE,
|
|
37
|
+
subject: SUBJECT,
|
|
38
|
+
expiresAt: now + 60_000,
|
|
39
|
+
createdAt: now,
|
|
40
|
+
...overrides,
|
|
41
|
+
};
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Runs the {@link TokenFlowStore} contract suite. Call it from your own test
|
|
45
|
+
* file — it registers `describe` / `it` blocks the test runner picks up.
|
|
46
|
+
*
|
|
47
|
+
* The concurrency cases redeem one token from two callers at once; a store that
|
|
48
|
+
* reads, awaits, then writes hands the token to both and fails them.
|
|
49
|
+
*/
|
|
50
|
+
export function runTokenFlowStoreContractTests(options) {
|
|
51
|
+
const expectDeleteBySubject = options.deleteBySubject ?? true;
|
|
52
|
+
describe(options.describeName ?? "TokenFlowStore contract", () => {
|
|
53
|
+
let store;
|
|
54
|
+
beforeEach(async () => {
|
|
55
|
+
store = await options.makeStore();
|
|
56
|
+
});
|
|
57
|
+
describe("save / get", () => {
|
|
58
|
+
it("returns null for an unknown token hash", async () => {
|
|
59
|
+
assertStrictEquals(await store.get("no-such-hash"), null);
|
|
60
|
+
});
|
|
61
|
+
it("round-trips every field of a saved record", async () => {
|
|
62
|
+
const saved = record({
|
|
63
|
+
tokenHash: "hash-1",
|
|
64
|
+
data: { email: "user@example.com" },
|
|
65
|
+
});
|
|
66
|
+
await store.save(saved);
|
|
67
|
+
const fetched = await store.get("hash-1");
|
|
68
|
+
assert(fetched !== null, "a saved record must be readable back");
|
|
69
|
+
assertEquals(fetched.purpose, saved.purpose);
|
|
70
|
+
assertEquals(fetched.subject, saved.subject);
|
|
71
|
+
assertEquals(fetched.data, saved.data);
|
|
72
|
+
assertStrictEquals(fetched.expiresAt, saved.expiresAt);
|
|
73
|
+
assertStrictEquals(fetched.createdAt, saved.createdAt);
|
|
74
|
+
assertStrictEquals(fetched.consumedAt, undefined);
|
|
75
|
+
});
|
|
76
|
+
it("returns an expired record rather than hiding it", async () => {
|
|
77
|
+
await store.save(record({ tokenHash: "hash-expired", expiresAt: Date.now() - 1000 }));
|
|
78
|
+
const fetched = await store.get("hash-expired");
|
|
79
|
+
assert(fetched !== null, "expiry is the service's call — it reports `expired` distinctly " +
|
|
80
|
+
"from `invalid`, which it cannot do if the store swallows the row");
|
|
81
|
+
});
|
|
82
|
+
it("keeps records with different hashes independent", async () => {
|
|
83
|
+
await store.save(record({ tokenHash: "hash-1" }));
|
|
84
|
+
await store.save(record({ tokenHash: "hash-2" }));
|
|
85
|
+
assertStrictEquals((await store.get("hash-1"))?.tokenHash, "hash-1");
|
|
86
|
+
assertStrictEquals((await store.get("hash-2"))?.tokenHash, "hash-2");
|
|
87
|
+
});
|
|
88
|
+
});
|
|
89
|
+
describe("markConsumed", () => {
|
|
90
|
+
it("claims a live record and stamps it", async () => {
|
|
91
|
+
await store.save(record({ tokenHash: "hash-1" }));
|
|
92
|
+
const consumedAt = Date.now();
|
|
93
|
+
assertStrictEquals(await store.markConsumed("hash-1", consumedAt), true);
|
|
94
|
+
assertStrictEquals((await store.get("hash-1"))?.consumedAt, consumedAt);
|
|
95
|
+
});
|
|
96
|
+
it("refuses a record already consumed, keeping the first stamp", async () => {
|
|
97
|
+
await store.save(record({ tokenHash: "hash-1" }));
|
|
98
|
+
const first = Date.now();
|
|
99
|
+
await store.markConsumed("hash-1", first);
|
|
100
|
+
assertStrictEquals(await store.markConsumed("hash-1", first + 5_000), false);
|
|
101
|
+
assertStrictEquals((await store.get("hash-1"))?.consumedAt, first, "a losing claim must not overwrite the winner's record");
|
|
102
|
+
});
|
|
103
|
+
it("refuses an unknown token hash", async () => {
|
|
104
|
+
assertStrictEquals(await store.markConsumed("no-such-hash", Date.now()), false);
|
|
105
|
+
});
|
|
106
|
+
it("claims a token for exactly one of two concurrent redemptions", async () => {
|
|
107
|
+
await store.save(record({ tokenHash: "hash-1" }));
|
|
108
|
+
const now = Date.now();
|
|
109
|
+
const results = await Promise.all([
|
|
110
|
+
store.markConsumed("hash-1", now),
|
|
111
|
+
store.markConsumed("hash-1", now + 1),
|
|
112
|
+
]);
|
|
113
|
+
assertStrictEquals(countTrue(results), 1, "a link is single-use — two requests racing one link must not both " +
|
|
114
|
+
"be told they claimed it");
|
|
115
|
+
});
|
|
116
|
+
it("claims both tokens when two different ones are redeemed concurrently", async () => {
|
|
117
|
+
await store.save(record({ tokenHash: "hash-1" }));
|
|
118
|
+
await store.save(record({ tokenHash: "hash-2" }));
|
|
119
|
+
const now = Date.now();
|
|
120
|
+
const results = await Promise.all([
|
|
121
|
+
store.markConsumed("hash-1", now),
|
|
122
|
+
store.markConsumed("hash-2", now),
|
|
123
|
+
]);
|
|
124
|
+
assertStrictEquals(countTrue(results), 2);
|
|
125
|
+
assert((await store.get("hash-1"))?.consumedAt !== undefined &&
|
|
126
|
+
(await store.get("hash-2"))?.consumedAt !== undefined, "neither stamp may be lost to the other's stale read");
|
|
127
|
+
});
|
|
128
|
+
});
|
|
129
|
+
if (expectDeleteBySubject) {
|
|
130
|
+
describe("deleteBySubject", () => {
|
|
131
|
+
it("is implemented", () => {
|
|
132
|
+
assert(typeof store.deleteBySubject === "function", "deleteBySubject is optional, but without it " +
|
|
133
|
+
"`TokenFlowService.invalidate` returns false and outstanding " +
|
|
134
|
+
"links stay redeemable until they expire. Implement it, or pass " +
|
|
135
|
+
"`deleteBySubject: false` to record the gap.");
|
|
136
|
+
});
|
|
137
|
+
it("drops the pending tokens for one (purpose, subject)", async () => {
|
|
138
|
+
await store.save(record({ tokenHash: "hash-1" }));
|
|
139
|
+
await store.save(record({ tokenHash: "hash-2" }));
|
|
140
|
+
await store.deleteBySubject(PURPOSE, SUBJECT);
|
|
141
|
+
assertStrictEquals(await store.get("hash-1"), null);
|
|
142
|
+
assertStrictEquals(await store.get("hash-2"), null);
|
|
143
|
+
});
|
|
144
|
+
it("leaves other subjects and other purposes alone", async () => {
|
|
145
|
+
await store.save(record({ tokenHash: "hash-mine" }));
|
|
146
|
+
await store.save(record({ tokenHash: "hash-other-subject", subject: OTHER_SUBJECT }));
|
|
147
|
+
await store.save(record({ tokenHash: "hash-other-purpose", purpose: OTHER_PURPOSE }));
|
|
148
|
+
await store.deleteBySubject(PURPOSE, SUBJECT);
|
|
149
|
+
assertStrictEquals(await store.get("hash-mine"), null);
|
|
150
|
+
assert(await store.get("hash-other-subject") !== null, "another subject's token must survive");
|
|
151
|
+
assert(await store.get("hash-other-purpose") !== null, "the same subject's token for another purpose must survive");
|
|
152
|
+
});
|
|
153
|
+
it("is a no-op when the pair has no tokens", async () => {
|
|
154
|
+
await store.save(record({ tokenHash: "hash-1" }));
|
|
155
|
+
await store.deleteBySubject(PURPOSE, OTHER_SUBJECT);
|
|
156
|
+
assert(await store.get("hash-1") !== null);
|
|
157
|
+
});
|
|
158
|
+
it("keeps an already-consumed record so it still reads as consumed", async () => {
|
|
159
|
+
await store.save(record({ tokenHash: "hash-used" }));
|
|
160
|
+
await store.save(record({ tokenHash: "hash-pending" }));
|
|
161
|
+
assertStrictEquals(await store.markConsumed("hash-used", Date.now()), true);
|
|
162
|
+
await store.deleteBySubject(PURPOSE, SUBJECT);
|
|
163
|
+
assertStrictEquals(await store.get("hash-pending"), null, "the pending token must be dropped");
|
|
164
|
+
const used = await store.get("hash-used");
|
|
165
|
+
assert(used !== null, "a consumed record must survive so inspect() can answer " +
|
|
166
|
+
"`consumed` rather than the generic `invalid`");
|
|
167
|
+
assert(used.consumedAt !== undefined, "the surviving record must still carry its consumedAt stamp");
|
|
168
|
+
});
|
|
169
|
+
});
|
|
170
|
+
}
|
|
171
|
+
else {
|
|
172
|
+
it({
|
|
173
|
+
name: "deleteBySubject is not implemented — outstanding links stay redeemable until they expire (deleteBySubject: false)",
|
|
174
|
+
ignore: true,
|
|
175
|
+
fn: () => { },
|
|
176
|
+
});
|
|
177
|
+
}
|
|
178
|
+
});
|
|
179
|
+
}
|
|
@@ -0,0 +1,77 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract test suite for {@link TokenReaderInterface} implementations.
|
|
3
|
+
*
|
|
4
|
+
* A resource server only ever calls `getToken`, so the contract is small
|
|
5
|
+
* and strict: an accepted token comes back with the same access-token
|
|
6
|
+
* string and a projected client, and anything the reader cannot validate
|
|
7
|
+
* resolves to `undefined` rather than throwing — `undefined` is what the
|
|
8
|
+
* resource server turns into `invalid_token`. Thrown errors are reserved
|
|
9
|
+
* for transport and misconfiguration.
|
|
10
|
+
*
|
|
11
|
+
* Run it against the shipped readers, or against your own reader when your
|
|
12
|
+
* API validates tokens out of a shared database.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* import { runTokenReaderContractTests } from "@udibo/oauth2/testing/contract";
|
|
17
|
+
* import type { ClientInterface, TokenReaderInterface } from "@udibo/oauth2/server";
|
|
18
|
+
*
|
|
19
|
+
* interface AppUser {
|
|
20
|
+
* id: string;
|
|
21
|
+
* username: string;
|
|
22
|
+
* }
|
|
23
|
+
* declare function freshTokenReader(): Promise<
|
|
24
|
+
* TokenReaderInterface<ClientInterface, AppUser>
|
|
25
|
+
* >;
|
|
26
|
+
*
|
|
27
|
+
* runTokenReaderContractTests<ClientInterface, AppUser>({
|
|
28
|
+
* setup: async () => ({
|
|
29
|
+
* reader: await freshTokenReader(),
|
|
30
|
+
* validAccessToken: "seeded-token",
|
|
31
|
+
* expected: { clientId: "my-client", userId: "u1", scope: "read" },
|
|
32
|
+
* invalidAccessTokens: ["unknown-token", "revoked-token"],
|
|
33
|
+
* }),
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @module
|
|
38
|
+
*/
|
|
39
|
+
import type { ClientInterface } from "../../models/client.js";
|
|
40
|
+
import type { AbstractScope, BasicScope } from "../../models/scope.js";
|
|
41
|
+
import type { TokenReaderInterface } from "../../server/services/token.js";
|
|
42
|
+
/** The reader under test plus the tokens the suite exercises it with. */
|
|
43
|
+
export interface TokenReaderContractFixture<C extends ClientInterface, U, S extends AbstractScope = BasicScope> {
|
|
44
|
+
/** The reader under test. */
|
|
45
|
+
reader: TokenReaderInterface<C, U, S>;
|
|
46
|
+
/** An access token the reader must accept. */
|
|
47
|
+
validAccessToken: string;
|
|
48
|
+
/** What the accepted token must project. */
|
|
49
|
+
expected: {
|
|
50
|
+
/** `client.id` the reader must report for {@linkcode validAccessToken}. */
|
|
51
|
+
clientId: string;
|
|
52
|
+
/** `user.id` the reader must report, when the token represents a user. */
|
|
53
|
+
userId?: string;
|
|
54
|
+
/** Granted scope, as its string form, when the token carries one. */
|
|
55
|
+
scope?: string;
|
|
56
|
+
};
|
|
57
|
+
/**
|
|
58
|
+
* Access tokens the reader must reject with `undefined` — at minimum one
|
|
59
|
+
* it has never seen. Add the rejection paths specific to your reader
|
|
60
|
+
* (revoked, expired, wrong audience) to widen the coverage.
|
|
61
|
+
*/
|
|
62
|
+
invalidAccessTokens: string[];
|
|
63
|
+
/** Releases anything `setup` allocated (a mock server, a database). */
|
|
64
|
+
cleanup?(): Promise<void> | void;
|
|
65
|
+
}
|
|
66
|
+
/** Options for {@link runTokenReaderContractTests}. */
|
|
67
|
+
export interface TokenReaderContractOptions<C extends ClientInterface, U, S extends AbstractScope = BasicScope> {
|
|
68
|
+
/**
|
|
69
|
+
* Builds a fresh fixture for each test. Must be isolated — one test
|
|
70
|
+
* leaking state into another defeats the contract guarantees.
|
|
71
|
+
*/
|
|
72
|
+
setup(): Promise<TokenReaderContractFixture<C, U, S>> | TokenReaderContractFixture<C, U, S>;
|
|
73
|
+
/** Overrides the name passed to the outer `describe` block. */
|
|
74
|
+
describeName?: string;
|
|
75
|
+
}
|
|
76
|
+
/** Runs the {@link TokenReaderInterface} contract suite. */
|
|
77
|
+
export declare function runTokenReaderContractTests<C extends ClientInterface, U, S extends AbstractScope = BasicScope>(options: TokenReaderContractOptions<C, U, S>): void;
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract test suite for {@link TokenReaderInterface} implementations.
|
|
3
|
+
*
|
|
4
|
+
* A resource server only ever calls `getToken`, so the contract is small
|
|
5
|
+
* and strict: an accepted token comes back with the same access-token
|
|
6
|
+
* string and a projected client, and anything the reader cannot validate
|
|
7
|
+
* resolves to `undefined` rather than throwing — `undefined` is what the
|
|
8
|
+
* resource server turns into `invalid_token`. Thrown errors are reserved
|
|
9
|
+
* for transport and misconfiguration.
|
|
10
|
+
*
|
|
11
|
+
* Run it against the shipped readers, or against your own reader when your
|
|
12
|
+
* API validates tokens out of a shared database.
|
|
13
|
+
*
|
|
14
|
+
* @example
|
|
15
|
+
* ```ts
|
|
16
|
+
* import { runTokenReaderContractTests } from "@udibo/oauth2/testing/contract";
|
|
17
|
+
* import type { ClientInterface, TokenReaderInterface } from "@udibo/oauth2/server";
|
|
18
|
+
*
|
|
19
|
+
* interface AppUser {
|
|
20
|
+
* id: string;
|
|
21
|
+
* username: string;
|
|
22
|
+
* }
|
|
23
|
+
* declare function freshTokenReader(): Promise<
|
|
24
|
+
* TokenReaderInterface<ClientInterface, AppUser>
|
|
25
|
+
* >;
|
|
26
|
+
*
|
|
27
|
+
* runTokenReaderContractTests<ClientInterface, AppUser>({
|
|
28
|
+
* setup: async () => ({
|
|
29
|
+
* reader: await freshTokenReader(),
|
|
30
|
+
* validAccessToken: "seeded-token",
|
|
31
|
+
* expected: { clientId: "my-client", userId: "u1", scope: "read" },
|
|
32
|
+
* invalidAccessTokens: ["unknown-token", "revoked-token"],
|
|
33
|
+
* }),
|
|
34
|
+
* });
|
|
35
|
+
* ```
|
|
36
|
+
*
|
|
37
|
+
* @module
|
|
38
|
+
*/
|
|
39
|
+
import { assert, assertStrictEquals } from "../../deps/jsr.io/@std/assert/1.0.19/mod.js";
|
|
40
|
+
import { afterEach, beforeEach, describe, it } from "../../deps/jsr.io/@std/testing/1.0.20/bdd.js";
|
|
41
|
+
/** Runs the {@link TokenReaderInterface} contract suite. */
|
|
42
|
+
export function runTokenReaderContractTests(options) {
|
|
43
|
+
describe(options.describeName ?? "TokenReaderInterface contract", () => {
|
|
44
|
+
let fixture;
|
|
45
|
+
beforeEach(async () => {
|
|
46
|
+
fixture = await options.setup();
|
|
47
|
+
});
|
|
48
|
+
afterEach(async () => {
|
|
49
|
+
await fixture.cleanup?.();
|
|
50
|
+
});
|
|
51
|
+
it("echoes back the access token it was given", async () => {
|
|
52
|
+
const token = await fixture.reader.getToken(fixture.validAccessToken);
|
|
53
|
+
assertStrictEquals(token?.accessToken, fixture.validAccessToken);
|
|
54
|
+
});
|
|
55
|
+
it("projects the client the token was issued to", async () => {
|
|
56
|
+
const token = await fixture.reader.getToken(fixture.validAccessToken);
|
|
57
|
+
assertStrictEquals(token?.client.id, fixture.expected.clientId);
|
|
58
|
+
});
|
|
59
|
+
it("projects the user the token was issued for", async () => {
|
|
60
|
+
const token = await fixture.reader.getToken(fixture.validAccessToken);
|
|
61
|
+
assertStrictEquals(token?.user?.id, fixture.expected.userId);
|
|
62
|
+
});
|
|
63
|
+
it("exposes the granted scope", async () => {
|
|
64
|
+
const token = await fixture.reader.getToken(fixture.validAccessToken);
|
|
65
|
+
assertStrictEquals(token?.scope?.toString(), fixture.expected.scope);
|
|
66
|
+
});
|
|
67
|
+
it("exposes an expiry as a Date when the token carries one", async () => {
|
|
68
|
+
const token = await fixture.reader.getToken(fixture.validAccessToken);
|
|
69
|
+
assert(token?.accessTokenExpiresAt === undefined ||
|
|
70
|
+
token.accessTokenExpiresAt instanceof Date);
|
|
71
|
+
});
|
|
72
|
+
it("resolves undefined for tokens it cannot validate", async () => {
|
|
73
|
+
for (const accessToken of fixture.invalidAccessTokens) {
|
|
74
|
+
assertStrictEquals(await fixture.reader.getToken(accessToken), undefined, `expected ${accessToken} to be rejected with undefined`);
|
|
75
|
+
}
|
|
76
|
+
});
|
|
77
|
+
});
|
|
78
|
+
}
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Contract test suite for {@link TokenServiceInterface} implementations.
|
|
3
|
+
*
|
|
4
|
+
* Verifies the methods the framework actually calls during the OAuth2
|
|
5
|
+
* flows: token persistence, refresh-token lookup, revocation by token
|
|
6
|
+
* value or by authorization code, and per-(client, user) lifetime/scope
|
|
7
|
+
* generation.
|
|
8
|
+
*
|
|
9
|
+
* Both a token with a user and a token without one are exercised. The client
|
|
10
|
+
* credentials grant (RFC 6749 §4.4) has no resource owner, so the framework
|
|
11
|
+
* calls `acceptedScope`, `generateAccessToken`, and `accessTokenExpiresAt`
|
|
12
|
+
* with `user: undefined` and persists a token whose `user` is unset — a store
|
|
13
|
+
* that requires a user cannot hold a machine token.
|
|
14
|
+
*
|
|
15
|
+
* @module
|
|
16
|
+
*/
|
|
17
|
+
import type { ClientInterface } from "../../models/client.js";
|
|
18
|
+
import { BasicScope } from "../../models/scope.js";
|
|
19
|
+
import type { AbstractScope } from "../../models/scope.js";
|
|
20
|
+
import type { ClientServiceInterface } from "../../server/services/client.js";
|
|
21
|
+
import type { TokenServiceInterface } from "../../server/services/token.js";
|
|
22
|
+
import type { UserServiceInterface } from "../../server/services/user.js";
|
|
23
|
+
import type { MemoryUserShape } from "../services.js";
|
|
24
|
+
/** Options for {@link runTokenServiceContractTests}. */
|
|
25
|
+
export interface TokenServiceContractOptions<C extends ClientInterface, U extends MemoryUserShape, S extends AbstractScope = BasicScope> {
|
|
26
|
+
/** Returns fresh services for each test. */
|
|
27
|
+
makeServices(): Promise<{
|
|
28
|
+
userService: UserServiceInterface<U>;
|
|
29
|
+
clientService: ClientServiceInterface<C, U>;
|
|
30
|
+
tokenService: TokenServiceInterface<C, U, S>;
|
|
31
|
+
}> | {
|
|
32
|
+
userService: UserServiceInterface<U>;
|
|
33
|
+
clientService: ClientServiceInterface<C, U>;
|
|
34
|
+
tokenService: TokenServiceInterface<C, U, S>;
|
|
35
|
+
};
|
|
36
|
+
/** Persists a user with the given password into the user service under test. */
|
|
37
|
+
addUser(service: UserServiceInterface<U>, user: U, password: string): Promise<void>;
|
|
38
|
+
/** Persists a client (optionally with a secret and owning user) into the client service under test. */
|
|
39
|
+
addClient(service: ClientServiceInterface<C, U>, client: C, secret?: string, ownerUserId?: string): Promise<void>;
|
|
40
|
+
/** Builds a distinct user fixture for the given sequence number. Defaults to a minimal `{ id, username }` shape. */
|
|
41
|
+
makeUser?(seq: number): U;
|
|
42
|
+
/** Builds a distinct client fixture for the given sequence number. Defaults to a client granting `authorization_code` and `refresh_token`. */
|
|
43
|
+
makeClient?(seq: number): C;
|
|
44
|
+
/** Builds a scope from its string value. Defaults to a {@linkcode BasicScope}. */
|
|
45
|
+
makeScope?(value: string): S;
|
|
46
|
+
/**
|
|
47
|
+
* Set to `false` when the service deliberately omits the optional
|
|
48
|
+
* reuse-detection pair, {@linkcode TokenServiceInterface.getRevokedRefreshToken}
|
|
49
|
+
* and {@linkcode TokenServiceInterface.revokeFamily}. The suite then
|
|
50
|
+
* registers an ignored case naming what is not covered — a replayed
|
|
51
|
+
* rotated-out refresh token cannot be detected, so a stolen token keeps
|
|
52
|
+
* working alongside the victim's — instead of passing in silence. Defaults to
|
|
53
|
+
* `true`, so a service that meant to implement the pair and does not fails
|
|
54
|
+
* loudly rather than losing reuse detection quietly.
|
|
55
|
+
*/
|
|
56
|
+
refreshTokenReuseDetection?: boolean;
|
|
57
|
+
/** Overrides the name passed to the outer `describe` block. */
|
|
58
|
+
describeName?: string;
|
|
59
|
+
}
|
|
60
|
+
/** Runs the {@link TokenServiceInterface} contract suite. */
|
|
61
|
+
export declare function runTokenServiceContractTests<C extends ClientInterface, U extends MemoryUserShape, S extends AbstractScope = BasicScope>(options: TokenServiceContractOptions<C, U, S>): void;
|