@_mustachio/openauth 0.9.2 → 0.11.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/dist/esm/adapters/d1/audit-log.js +15 -0
- package/dist/esm/adapters/d1/config-store.js +45 -0
- package/dist/esm/adapters/d1/index.js +12 -0
- package/dist/esm/adapters/d1/key-store.js +116 -0
- package/dist/esm/adapters/d1/method-store.js +52 -0
- package/dist/esm/adapters/d1/migrations.js +77 -0
- package/dist/esm/adapters/d1/session-store.js +134 -0
- package/dist/esm/adapters/d1/session.js +18 -0
- package/dist/esm/adapters/d1/token-store.js +140 -0
- package/dist/esm/adapters/durable-object/index.js +3 -0
- package/dist/esm/adapters/durable-object/session-store.js +139 -0
- package/dist/esm/adapters/durable-object/types.js +0 -0
- package/dist/esm/adapters/dynamo/audit-log.js +23 -0
- package/dist/esm/adapters/dynamo/client.js +0 -0
- package/dist/esm/adapters/dynamo/config-store.js +57 -0
- package/dist/esm/adapters/dynamo/index.js +10 -0
- package/dist/esm/adapters/dynamo/key-store.js +188 -0
- package/dist/esm/adapters/dynamo/method-store.js +72 -0
- package/dist/esm/adapters/dynamo/passkey-credential-store.js +83 -0
- package/dist/esm/adapters/dynamo/sdk.js +128 -0
- package/dist/esm/adapters/dynamo/session-store.js +173 -0
- package/dist/esm/adapters/dynamo/token-store.js +178 -0
- package/dist/esm/adapters/kms/in-memory-backing.js +28 -0
- package/dist/esm/adapters/kms/index.js +5 -0
- package/dist/esm/adapters/kms/key-store.js +129 -0
- package/dist/esm/adapters/kms/sdk.js +23 -0
- package/dist/esm/adapters/kms/types.js +0 -0
- package/dist/esm/adapters/kv/audit-log.js +21 -0
- package/dist/esm/adapters/kv/config-store.js +43 -0
- package/dist/esm/adapters/kv/index.js +5 -0
- package/dist/esm/adapters/kv/method-store.js +63 -0
- package/dist/esm/adapters/kv/types.js +0 -0
- package/dist/esm/adapters/memory/audit-log.js +16 -0
- package/dist/esm/adapters/memory/clock.js +5 -0
- package/dist/esm/adapters/memory/config-store.js +31 -0
- package/dist/esm/adapters/memory/index.js +10 -0
- package/dist/esm/adapters/memory/key-store.js +78 -0
- package/dist/esm/adapters/memory/method-store.js +43 -0
- package/dist/esm/adapters/memory/passkey-credential-store.js +53 -0
- package/dist/esm/adapters/memory/session-store.js +104 -0
- package/dist/esm/adapters/memory/token-store.js +104 -0
- package/dist/esm/adapters/postgres/audit-log.js +16 -0
- package/dist/esm/adapters/postgres/config-store.js +48 -0
- package/dist/esm/adapters/postgres/executor.js +21 -0
- package/dist/esm/adapters/postgres/index.js +13 -0
- package/dist/esm/adapters/postgres/key-store.js +191 -0
- package/dist/esm/adapters/postgres/method-store.js +61 -0
- package/dist/esm/adapters/postgres/migrations.js +111 -0
- package/dist/esm/adapters/postgres/passkey-credential-store.js +80 -0
- package/dist/esm/adapters/postgres/session-store.js +135 -0
- package/dist/esm/adapters/postgres/token-store.js +151 -0
- package/dist/esm/client.js +35 -12
- package/dist/esm/domain/audit.js +13 -0
- package/dist/esm/domain/authorize.js +217 -0
- package/dist/esm/domain/callback.js +176 -0
- package/dist/esm/domain/client-auth.js +61 -0
- package/dist/esm/domain/client-credentials.js +91 -0
- package/dist/esm/domain/crypto.js +97 -0
- package/dist/esm/domain/discovery.js +83 -0
- package/dist/esm/domain/dpop.js +122 -0
- package/dist/esm/domain/id-token.js +94 -0
- package/dist/esm/domain/introspect.js +55 -0
- package/dist/esm/domain/jwt.js +71 -0
- package/dist/esm/domain/logout.js +75 -0
- package/dist/esm/domain/method-cache.js +136 -0
- package/dist/esm/domain/method-dispatch.js +36 -0
- package/dist/esm/domain/method-route.js +111 -0
- package/dist/esm/domain/par.js +51 -0
- package/dist/esm/domain/pkce.js +16 -0
- package/dist/esm/domain/refresh.js +102 -0
- package/dist/esm/domain/register.js +74 -0
- package/dist/esm/domain/revoke.js +81 -0
- package/dist/esm/domain/state-envelope.js +80 -0
- package/dist/esm/domain/token-exchange.js +102 -0
- package/dist/esm/domain/token.js +246 -0
- package/dist/esm/domain/userinfo.js +62 -0
- package/dist/esm/http/context.js +7 -0
- package/dist/esm/http/cookies.js +98 -0
- package/dist/esm/http/errors.js +71 -0
- package/dist/esm/http/handlers/authorize.js +250 -0
- package/dist/esm/http/handlers/callback.js +53 -0
- package/dist/esm/http/handlers/end-session.js +64 -0
- package/dist/esm/http/handlers/metadata.js +37 -0
- package/dist/esm/http/handlers/method-route.js +87 -0
- package/dist/esm/http/handlers/par.js +53 -0
- package/dist/esm/http/handlers/register.js +46 -0
- package/dist/esm/http/handlers/revocation.js +98 -0
- package/dist/esm/http/handlers/token.js +197 -0
- package/dist/esm/http/handlers/userinfo.js +60 -0
- package/dist/esm/http/middleware/error.js +15 -0
- package/dist/esm/http/middleware/tenant.js +102 -0
- package/dist/esm/http/resolver.js +15 -0
- package/dist/esm/http/router.js +45 -0
- package/dist/esm/http/schemas/authorize.js +30 -0
- package/dist/esm/http/schemas/end-session.js +13 -0
- package/dist/esm/http/schemas/par.js +9 -0
- package/dist/esm/http/schemas/register.js +16 -0
- package/dist/esm/http/schemas/revocation.js +18 -0
- package/dist/esm/http/schemas/token.js +57 -0
- package/dist/esm/index.js +126 -9
- package/dist/esm/methods/code.js +221 -0
- package/dist/esm/methods/m2m.js +41 -0
- package/dist/esm/methods/oauth2-factory.js +84 -0
- package/dist/esm/methods/oauth2-generic.js +196 -0
- package/dist/esm/methods/oidc-generic.js +53 -0
- package/dist/esm/methods/passkey.js +275 -0
- package/dist/esm/methods/password-hash.js +79 -0
- package/dist/esm/methods/password.js +166 -0
- package/dist/esm/methods/providers/apple.js +29 -0
- package/dist/esm/methods/providers/cognito.js +37 -0
- package/dist/esm/methods/providers/discord.js +28 -0
- package/dist/esm/methods/providers/facebook.js +42 -0
- package/dist/esm/methods/providers/github.js +29 -0
- package/dist/esm/methods/providers/google.js +29 -0
- package/dist/esm/methods/providers/index.js +17 -0
- package/dist/esm/methods/providers/jumpcloud.js +27 -0
- package/dist/esm/methods/providers/keycloak.js +32 -0
- package/dist/esm/methods/providers/linkedin.js +28 -0
- package/dist/esm/methods/providers/microsoft.js +28 -0
- package/dist/esm/methods/providers/slack.js +30 -0
- package/dist/esm/methods/providers/spotify.js +28 -0
- package/dist/esm/methods/providers/twitch.js +28 -0
- package/dist/esm/methods/providers/x.js +28 -0
- package/dist/esm/methods/providers/yahoo.js +27 -0
- package/dist/esm/pkce.js +4 -16
- package/dist/esm/ports/audit-log.js +0 -0
- package/dist/esm/ports/config-store.js +0 -0
- package/dist/esm/ports/key-store.js +0 -0
- package/dist/esm/ports/method-store.js +0 -0
- package/dist/esm/ports/session-store.js +0 -0
- package/dist/esm/ports/token-store.js +0 -0
- package/dist/esm/types/authorization.js +0 -0
- package/dist/esm/types/error.js +70 -0
- package/dist/esm/types/flow.js +0 -0
- package/dist/esm/types/idp.js +0 -0
- package/dist/esm/types/method.js +0 -0
- package/dist/esm/types/picker.js +0 -0
- package/dist/esm/types/result.js +11 -0
- package/dist/esm/types/subject.js +0 -0
- package/dist/esm/types/tenant.js +5 -0
- package/dist/esm/types/token.js +0 -0
- package/dist/esm/ui/forms.js +253 -0
- package/dist/esm/ui/index.js +8 -0
- package/dist/esm/ui/picker.js +49 -0
- package/dist/types/adapters/d1/audit-log.d.ts +19 -0
- package/dist/types/adapters/d1/audit-log.d.ts.map +1 -0
- package/dist/types/adapters/d1/config-store.d.ts +20 -0
- package/dist/types/adapters/d1/config-store.d.ts.map +1 -0
- package/dist/types/adapters/d1/index.d.ts +35 -0
- package/dist/types/adapters/d1/index.d.ts.map +1 -0
- package/dist/types/adapters/d1/key-store.d.ts +17 -0
- package/dist/types/adapters/d1/key-store.d.ts.map +1 -0
- package/dist/types/adapters/d1/method-store.d.ts +21 -0
- package/dist/types/adapters/d1/method-store.d.ts.map +1 -0
- package/dist/types/adapters/d1/migrations.d.ts +18 -0
- package/dist/types/adapters/d1/migrations.d.ts.map +1 -0
- package/dist/types/adapters/d1/session-store.d.ts +20 -0
- package/dist/types/adapters/d1/session-store.d.ts.map +1 -0
- package/dist/types/adapters/d1/session.d.ts +18 -0
- package/dist/types/adapters/d1/session.d.ts.map +1 -0
- package/dist/types/adapters/d1/token-store.d.ts +29 -0
- package/dist/types/adapters/d1/token-store.d.ts.map +1 -0
- package/dist/types/adapters/d1/types.d.ts +43 -0
- package/dist/types/adapters/d1/types.d.ts.map +1 -0
- package/dist/types/adapters/durable-object/index.d.ts +17 -0
- package/dist/types/adapters/durable-object/index.d.ts.map +1 -0
- package/dist/types/adapters/durable-object/session-store.d.ts +21 -0
- package/dist/types/adapters/durable-object/session-store.d.ts.map +1 -0
- package/dist/types/adapters/durable-object/types.d.ts +23 -0
- package/dist/types/adapters/durable-object/types.d.ts.map +1 -0
- package/dist/types/adapters/dynamo/audit-log.d.ts +19 -0
- package/dist/types/adapters/dynamo/audit-log.d.ts.map +1 -0
- package/dist/types/adapters/dynamo/client.d.ts +111 -0
- package/dist/types/adapters/dynamo/client.d.ts.map +1 -0
- package/dist/types/adapters/dynamo/config-store.d.ts +21 -0
- package/dist/types/adapters/dynamo/config-store.d.ts.map +1 -0
- package/dist/types/adapters/dynamo/index.d.ts +60 -0
- package/dist/types/adapters/dynamo/index.d.ts.map +1 -0
- package/dist/types/adapters/dynamo/key-store.d.ts +23 -0
- package/dist/types/adapters/dynamo/key-store.d.ts.map +1 -0
- package/dist/types/adapters/dynamo/method-store.d.ts +20 -0
- package/dist/types/adapters/dynamo/method-store.d.ts.map +1 -0
- package/dist/types/adapters/dynamo/passkey-credential-store.d.ts +47 -0
- package/dist/types/adapters/dynamo/passkey-credential-store.d.ts.map +1 -0
- package/dist/types/adapters/dynamo/sdk.d.ts +23 -0
- package/dist/types/adapters/dynamo/sdk.d.ts.map +1 -0
- package/dist/types/adapters/dynamo/session-store.d.ts +20 -0
- package/dist/types/adapters/dynamo/session-store.d.ts.map +1 -0
- package/dist/types/adapters/dynamo/token-store.d.ts +29 -0
- package/dist/types/adapters/dynamo/token-store.d.ts.map +1 -0
- package/dist/types/adapters/kms/in-memory-backing.d.ts +9 -0
- package/dist/types/adapters/kms/in-memory-backing.d.ts.map +1 -0
- package/dist/types/adapters/kms/index.d.ts +35 -0
- package/dist/types/adapters/kms/index.d.ts.map +1 -0
- package/dist/types/adapters/kms/key-store.d.ts +20 -0
- package/dist/types/adapters/kms/key-store.d.ts.map +1 -0
- package/dist/types/adapters/kms/sdk.d.ts +16 -0
- package/dist/types/adapters/kms/sdk.d.ts.map +1 -0
- package/dist/types/adapters/kms/types.d.ts +58 -0
- package/dist/types/adapters/kms/types.d.ts.map +1 -0
- package/dist/types/adapters/kv/audit-log.d.ts +22 -0
- package/dist/types/adapters/kv/audit-log.d.ts.map +1 -0
- package/dist/types/adapters/kv/config-store.d.ts +25 -0
- package/dist/types/adapters/kv/config-store.d.ts.map +1 -0
- package/dist/types/adapters/kv/index.d.ts +21 -0
- package/dist/types/adapters/kv/index.d.ts.map +1 -0
- package/dist/types/adapters/kv/method-store.d.ts +23 -0
- package/dist/types/adapters/kv/method-store.d.ts.map +1 -0
- package/dist/types/adapters/kv/types.d.ts +28 -0
- package/dist/types/adapters/kv/types.d.ts.map +1 -0
- package/dist/types/adapters/memory/audit-log.d.ts +18 -0
- package/dist/types/adapters/memory/audit-log.d.ts.map +1 -0
- package/dist/types/adapters/memory/clock.d.ts +7 -0
- package/dist/types/adapters/memory/clock.d.ts.map +1 -0
- package/dist/types/adapters/memory/config-store.d.ts +19 -0
- package/dist/types/adapters/memory/config-store.d.ts.map +1 -0
- package/dist/types/adapters/memory/index.d.ts +15 -0
- package/dist/types/adapters/memory/index.d.ts.map +1 -0
- package/dist/types/adapters/memory/key-store.d.ts +17 -0
- package/dist/types/adapters/memory/key-store.d.ts.map +1 -0
- package/dist/types/adapters/memory/method-store.d.ts +26 -0
- package/dist/types/adapters/memory/method-store.d.ts.map +1 -0
- package/dist/types/adapters/memory/passkey-credential-store.d.ts +43 -0
- package/dist/types/adapters/memory/passkey-credential-store.d.ts.map +1 -0
- package/dist/types/adapters/memory/session-store.d.ts +21 -0
- package/dist/types/adapters/memory/session-store.d.ts.map +1 -0
- package/dist/types/adapters/memory/token-store.d.ts +29 -0
- package/dist/types/adapters/memory/token-store.d.ts.map +1 -0
- package/dist/types/adapters/postgres/audit-log.d.ts +18 -0
- package/dist/types/adapters/postgres/audit-log.d.ts.map +1 -0
- package/dist/types/adapters/postgres/config-store.d.ts +21 -0
- package/dist/types/adapters/postgres/config-store.d.ts.map +1 -0
- package/dist/types/adapters/postgres/executor.d.ts +48 -0
- package/dist/types/adapters/postgres/executor.d.ts.map +1 -0
- package/dist/types/adapters/postgres/index.d.ts +39 -0
- package/dist/types/adapters/postgres/index.d.ts.map +1 -0
- package/dist/types/adapters/postgres/key-store.d.ts +23 -0
- package/dist/types/adapters/postgres/key-store.d.ts.map +1 -0
- package/dist/types/adapters/postgres/method-store.d.ts +21 -0
- package/dist/types/adapters/postgres/method-store.d.ts.map +1 -0
- package/dist/types/adapters/postgres/migrations.d.ts +22 -0
- package/dist/types/adapters/postgres/migrations.d.ts.map +1 -0
- package/dist/types/adapters/postgres/passkey-credential-store.d.ts +48 -0
- package/dist/types/adapters/postgres/passkey-credential-store.d.ts.map +1 -0
- package/dist/types/adapters/postgres/session-store.d.ts +20 -0
- package/dist/types/adapters/postgres/session-store.d.ts.map +1 -0
- package/dist/types/adapters/postgres/token-store.d.ts +30 -0
- package/dist/types/adapters/postgres/token-store.d.ts.map +1 -0
- package/dist/types/client.d.ts +20 -1
- package/dist/types/client.d.ts.map +1 -1
- package/dist/types/domain/audit.d.ts +17 -0
- package/dist/types/domain/audit.d.ts.map +1 -0
- package/dist/types/domain/authorize.d.ts +125 -0
- package/dist/types/domain/authorize.d.ts.map +1 -0
- package/dist/types/domain/callback.d.ts +70 -0
- package/dist/types/domain/callback.d.ts.map +1 -0
- package/dist/types/domain/client-auth.d.ts +57 -0
- package/dist/types/domain/client-auth.d.ts.map +1 -0
- package/dist/types/domain/client-credentials.d.ts +54 -0
- package/dist/types/domain/client-credentials.d.ts.map +1 -0
- package/dist/types/domain/crypto.d.ts +53 -0
- package/dist/types/domain/crypto.d.ts.map +1 -0
- package/dist/types/domain/discovery.d.ts +81 -0
- package/dist/types/domain/discovery.d.ts.map +1 -0
- package/dist/types/domain/dpop.d.ts +61 -0
- package/dist/types/domain/dpop.d.ts.map +1 -0
- package/dist/types/domain/id-token.d.ts +83 -0
- package/dist/types/domain/id-token.d.ts.map +1 -0
- package/dist/types/domain/introspect.d.ts +79 -0
- package/dist/types/domain/introspect.d.ts.map +1 -0
- package/dist/types/domain/jwt.d.ts +74 -0
- package/dist/types/domain/jwt.d.ts.map +1 -0
- package/dist/types/domain/logout.d.ts +69 -0
- package/dist/types/domain/logout.d.ts.map +1 -0
- package/dist/types/domain/method-cache.d.ts +42 -0
- package/dist/types/domain/method-cache.d.ts.map +1 -0
- package/dist/types/domain/method-dispatch.d.ts +37 -0
- package/dist/types/domain/method-dispatch.d.ts.map +1 -0
- package/dist/types/domain/method-route.d.ts +77 -0
- package/dist/types/domain/method-route.d.ts.map +1 -0
- package/dist/types/domain/par.d.ts +62 -0
- package/dist/types/domain/par.d.ts.map +1 -0
- package/dist/types/domain/pkce.d.ts +15 -0
- package/dist/types/domain/pkce.d.ts.map +1 -0
- package/dist/types/domain/refresh.d.ts +52 -0
- package/dist/types/domain/refresh.d.ts.map +1 -0
- package/dist/types/domain/register.d.ts +33 -0
- package/dist/types/domain/register.d.ts.map +1 -0
- package/dist/types/domain/revoke.d.ts +61 -0
- package/dist/types/domain/revoke.d.ts.map +1 -0
- package/dist/types/domain/state-envelope.d.ts +30 -0
- package/dist/types/domain/state-envelope.d.ts.map +1 -0
- package/dist/types/domain/token-exchange.d.ts +69 -0
- package/dist/types/domain/token-exchange.d.ts.map +1 -0
- package/dist/types/domain/token.d.ts +140 -0
- package/dist/types/domain/token.d.ts.map +1 -0
- package/dist/types/domain/userinfo.d.ts +61 -0
- package/dist/types/domain/userinfo.d.ts.map +1 -0
- package/dist/types/http/context.d.ts +66 -0
- package/dist/types/http/context.d.ts.map +1 -0
- package/dist/types/http/cookies.d.ts +45 -0
- package/dist/types/http/cookies.d.ts.map +1 -0
- package/dist/types/http/errors.d.ts +36 -0
- package/dist/types/http/errors.d.ts.map +1 -0
- package/dist/types/http/handlers/authorize.d.ts +3 -0
- package/dist/types/http/handlers/authorize.d.ts.map +1 -0
- package/dist/types/http/handlers/callback.d.ts +3 -0
- package/dist/types/http/handlers/callback.d.ts.map +1 -0
- package/dist/types/http/handlers/end-session.d.ts +3 -0
- package/dist/types/http/handlers/end-session.d.ts.map +1 -0
- package/dist/types/http/handlers/metadata.d.ts +4 -0
- package/dist/types/http/handlers/metadata.d.ts.map +1 -0
- package/dist/types/http/handlers/method-route.d.ts +3 -0
- package/dist/types/http/handlers/method-route.d.ts.map +1 -0
- package/dist/types/http/handlers/par.d.ts +3 -0
- package/dist/types/http/handlers/par.d.ts.map +1 -0
- package/dist/types/http/handlers/register.d.ts +3 -0
- package/dist/types/http/handlers/register.d.ts.map +1 -0
- package/dist/types/http/handlers/revocation.d.ts +4 -0
- package/dist/types/http/handlers/revocation.d.ts.map +1 -0
- package/dist/types/http/handlers/token.d.ts +3 -0
- package/dist/types/http/handlers/token.d.ts.map +1 -0
- package/dist/types/http/handlers/userinfo.d.ts +3 -0
- package/dist/types/http/handlers/userinfo.d.ts.map +1 -0
- package/dist/types/http/middleware/error.d.ts +9 -0
- package/dist/types/http/middleware/error.d.ts.map +1 -0
- package/dist/types/http/middleware/tenant.d.ts +30 -0
- package/dist/types/http/middleware/tenant.d.ts.map +1 -0
- package/dist/types/http/resolver.d.ts +22 -0
- package/dist/types/http/resolver.d.ts.map +1 -0
- package/dist/types/http/router.d.ts +21 -0
- package/dist/types/http/router.d.ts.map +1 -0
- package/dist/types/http/schemas/authorize.d.ts +92 -0
- package/dist/types/http/schemas/authorize.d.ts.map +1 -0
- package/dist/types/http/schemas/end-session.d.ts +31 -0
- package/dist/types/http/schemas/end-session.d.ts.map +1 -0
- package/dist/types/http/schemas/par.d.ts +20 -0
- package/dist/types/http/schemas/par.d.ts.map +1 -0
- package/dist/types/http/schemas/register.d.ts +42 -0
- package/dist/types/http/schemas/register.d.ts.map +1 -0
- package/dist/types/http/schemas/revocation.d.ts +41 -0
- package/dist/types/http/schemas/revocation.d.ts.map +1 -0
- package/dist/types/http/schemas/token.d.ts +227 -0
- package/dist/types/http/schemas/token.d.ts.map +1 -0
- package/dist/types/index.d.ts +63 -13
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/methods/code.d.ts +96 -0
- package/dist/types/methods/code.d.ts.map +1 -0
- package/dist/types/methods/m2m.d.ts +41 -0
- package/dist/types/methods/m2m.d.ts.map +1 -0
- package/dist/types/methods/oauth2-factory.d.ts +133 -0
- package/dist/types/methods/oauth2-factory.d.ts.map +1 -0
- package/dist/types/methods/oauth2-generic.d.ts +75 -0
- package/dist/types/methods/oauth2-generic.d.ts.map +1 -0
- package/dist/types/methods/oidc-generic.d.ts +26 -0
- package/dist/types/methods/oidc-generic.d.ts.map +1 -0
- package/dist/types/methods/passkey.d.ts +106 -0
- package/dist/types/methods/passkey.d.ts.map +1 -0
- package/dist/types/methods/password-hash.d.ts +25 -0
- package/dist/types/methods/password-hash.d.ts.map +1 -0
- package/dist/types/methods/password.d.ts +70 -0
- package/dist/types/methods/password.d.ts.map +1 -0
- package/dist/types/methods/providers/apple.d.ts +29 -0
- package/dist/types/methods/providers/apple.d.ts.map +1 -0
- package/dist/types/methods/providers/cognito.d.ts +36 -0
- package/dist/types/methods/providers/cognito.d.ts.map +1 -0
- package/dist/types/methods/providers/discord.d.ts +22 -0
- package/dist/types/methods/providers/discord.d.ts.map +1 -0
- package/dist/types/methods/providers/facebook.d.ts +29 -0
- package/dist/types/methods/providers/facebook.d.ts.map +1 -0
- package/dist/types/methods/providers/github.d.ts +25 -0
- package/dist/types/methods/providers/github.d.ts.map +1 -0
- package/dist/types/methods/providers/google.d.ts +28 -0
- package/dist/types/methods/providers/google.d.ts.map +1 -0
- package/dist/types/methods/providers/index.d.ts +24 -0
- package/dist/types/methods/providers/index.d.ts.map +1 -0
- package/dist/types/methods/providers/jumpcloud.d.ts +22 -0
- package/dist/types/methods/providers/jumpcloud.d.ts.map +1 -0
- package/dist/types/methods/providers/keycloak.d.ts +30 -0
- package/dist/types/methods/providers/keycloak.d.ts.map +1 -0
- package/dist/types/methods/providers/linkedin.d.ts +22 -0
- package/dist/types/methods/providers/linkedin.d.ts.map +1 -0
- package/dist/types/methods/providers/microsoft.d.ts +30 -0
- package/dist/types/methods/providers/microsoft.d.ts.map +1 -0
- package/dist/types/methods/providers/slack.d.ts +25 -0
- package/dist/types/methods/providers/slack.d.ts.map +1 -0
- package/dist/types/methods/providers/spotify.d.ts +22 -0
- package/dist/types/methods/providers/spotify.d.ts.map +1 -0
- package/dist/types/methods/providers/twitch.d.ts +23 -0
- package/dist/types/methods/providers/twitch.d.ts.map +1 -0
- package/dist/types/methods/providers/x.d.ts +25 -0
- package/dist/types/methods/providers/x.d.ts.map +1 -0
- package/dist/types/methods/providers/yahoo.d.ts +22 -0
- package/dist/types/methods/providers/yahoo.d.ts.map +1 -0
- package/dist/types/pkce.d.ts +1 -2
- package/dist/types/pkce.d.ts.map +1 -1
- package/dist/types/ports/audit-log.d.ts +166 -0
- package/dist/types/ports/audit-log.d.ts.map +1 -0
- package/dist/types/ports/config-store.d.ts +32 -0
- package/dist/types/ports/config-store.d.ts.map +1 -0
- package/dist/types/ports/key-store.d.ts +98 -0
- package/dist/types/ports/key-store.d.ts.map +1 -0
- package/dist/types/ports/method-store.d.ts +29 -0
- package/dist/types/ports/method-store.d.ts.map +1 -0
- package/dist/types/ports/session-store.d.ts +109 -0
- package/dist/types/ports/session-store.d.ts.map +1 -0
- package/dist/types/ports/token-store.d.ts +105 -0
- package/dist/types/ports/token-store.d.ts.map +1 -0
- package/dist/types/types/authorization.d.ts +75 -0
- package/dist/types/types/authorization.d.ts.map +1 -0
- package/dist/types/types/error.d.ts +101 -0
- package/dist/types/types/error.d.ts.map +1 -0
- package/dist/types/types/flow.d.ts +97 -0
- package/dist/types/types/flow.d.ts.map +1 -0
- package/dist/types/types/idp.d.ts +324 -0
- package/dist/types/types/idp.d.ts.map +1 -0
- package/dist/types/types/method.d.ts +256 -0
- package/dist/types/types/method.d.ts.map +1 -0
- package/dist/types/types/picker.d.ts +31 -0
- package/dist/types/types/picker.d.ts.map +1 -0
- package/dist/types/types/result.d.ts +29 -0
- package/dist/types/types/result.d.ts.map +1 -0
- package/dist/types/types/subject.d.ts +47 -0
- package/dist/types/types/subject.d.ts.map +1 -0
- package/dist/types/types/tenant.d.ts +276 -0
- package/dist/types/types/tenant.d.ts.map +1 -0
- package/dist/types/types/token.d.ts +231 -0
- package/dist/types/types/token.d.ts.map +1 -0
- package/dist/types/ui/forms.d.ts +35 -0
- package/dist/types/ui/forms.d.ts.map +1 -0
- package/dist/types/ui/index.d.ts +14 -0
- package/dist/types/ui/index.d.ts.map +1 -0
- package/dist/types/ui/picker.d.ts +18 -0
- package/dist/types/ui/picker.d.ts.map +1 -0
- package/package.json +41 -6
- package/src/adapters/d1/audit-log.ts +32 -0
- package/src/adapters/d1/config-store.ts +67 -0
- package/src/adapters/d1/index.ts +41 -0
- package/src/adapters/d1/key-store.ts +218 -0
- package/src/adapters/d1/method-store.ts +103 -0
- package/src/adapters/d1/migrations.ts +89 -0
- package/src/adapters/d1/session-store.ts +230 -0
- package/src/adapters/d1/session.ts +38 -0
- package/src/adapters/d1/token-store.ts +251 -0
- package/src/adapters/d1/types.ts +53 -0
- package/src/adapters/durable-object/index.ts +23 -0
- package/src/adapters/durable-object/session-store.ts +227 -0
- package/src/adapters/durable-object/types.ts +25 -0
- package/src/adapters/dynamo/audit-log.ts +35 -0
- package/src/adapters/dynamo/client.ts +118 -0
- package/src/adapters/dynamo/config-store.ts +72 -0
- package/src/adapters/dynamo/index.ts +81 -0
- package/src/adapters/dynamo/key-store.ts +267 -0
- package/src/adapters/dynamo/method-store.ts +105 -0
- package/src/adapters/dynamo/passkey-credential-store.ts +132 -0
- package/src/adapters/dynamo/sdk.ts +189 -0
- package/src/adapters/dynamo/session-store.ts +229 -0
- package/src/adapters/dynamo/token-store.ts +248 -0
- package/src/adapters/kms/in-memory-backing.ts +36 -0
- package/src/adapters/kms/index.ts +39 -0
- package/src/adapters/kms/key-store.ts +176 -0
- package/src/adapters/kms/sdk.ts +39 -0
- package/src/adapters/kms/types.ts +61 -0
- package/src/adapters/kv/audit-log.ts +40 -0
- package/src/adapters/kv/config-store.ts +63 -0
- package/src/adapters/kv/index.ts +20 -0
- package/src/adapters/kv/method-store.ts +98 -0
- package/src/adapters/kv/types.ts +26 -0
- package/src/adapters/memory/audit-log.ts +28 -0
- package/src/adapters/memory/clock.ts +7 -0
- package/src/adapters/memory/config-store.ts +41 -0
- package/src/adapters/memory/index.ts +26 -0
- package/src/adapters/memory/key-store.ts +102 -0
- package/src/adapters/memory/method-store.ts +75 -0
- package/src/adapters/memory/passkey-credential-store.ts +97 -0
- package/src/adapters/memory/session-store.ts +171 -0
- package/src/adapters/memory/token-store.ts +181 -0
- package/src/adapters/postgres/audit-log.ts +34 -0
- package/src/adapters/postgres/config-store.ts +72 -0
- package/src/adapters/postgres/executor.ts +76 -0
- package/src/adapters/postgres/index.ts +60 -0
- package/src/adapters/postgres/key-store.ts +334 -0
- package/src/adapters/postgres/method-store.ts +104 -0
- package/src/adapters/postgres/migrations.ts +131 -0
- package/src/adapters/postgres/passkey-credential-store.ts +150 -0
- package/src/adapters/postgres/session-store.ts +216 -0
- package/src/adapters/postgres/token-store.ts +263 -0
- package/src/client.ts +82 -16
- package/src/domain/audit.ts +28 -0
- package/src/domain/authorize.ts +414 -0
- package/src/domain/callback.ts +268 -0
- package/src/domain/client-auth.ts +116 -0
- package/src/domain/client-credentials.ts +180 -0
- package/src/domain/crypto.ts +168 -0
- package/src/domain/discovery.ts +161 -0
- package/src/domain/dpop.ts +293 -0
- package/src/domain/id-token.ts +213 -0
- package/src/domain/introspect.ts +155 -0
- package/src/domain/jwt.ts +185 -0
- package/src/domain/logout.ts +180 -0
- package/src/domain/method-cache.ts +220 -0
- package/src/domain/method-dispatch.ts +95 -0
- package/src/domain/method-route.ts +213 -0
- package/src/domain/par.ts +141 -0
- package/src/domain/pkce.ts +37 -0
- package/src/domain/refresh.ts +210 -0
- package/src/domain/register.ts +168 -0
- package/src/domain/revoke.ts +161 -0
- package/src/domain/state-envelope.ts +142 -0
- package/src/domain/token-exchange.ts +243 -0
- package/src/domain/token.ts +483 -0
- package/src/domain/userinfo.ts +171 -0
- package/src/http/context.ts +90 -0
- package/src/http/cookies.ts +167 -0
- package/src/http/errors.ts +98 -0
- package/src/http/handlers/authorize.ts +362 -0
- package/src/http/handlers/callback.ts +77 -0
- package/src/http/handlers/end-session.ts +106 -0
- package/src/http/handlers/metadata.ts +49 -0
- package/src/http/handlers/method-route.ts +115 -0
- package/src/http/handlers/par.ts +84 -0
- package/src/http/handlers/register.ts +70 -0
- package/src/http/handlers/revocation.ts +151 -0
- package/src/http/handlers/token.ts +300 -0
- package/src/http/handlers/userinfo.ts +90 -0
- package/src/http/middleware/error.ts +26 -0
- package/src/http/middleware/tenant.ts +165 -0
- package/src/http/resolver.ts +34 -0
- package/src/http/router.ts +85 -0
- package/src/http/schemas/authorize.ts +85 -0
- package/src/http/schemas/end-session.ts +23 -0
- package/src/http/schemas/par.ts +23 -0
- package/src/http/schemas/register.ts +29 -0
- package/src/http/schemas/revocation.ts +23 -0
- package/src/http/schemas/token.ts +85 -0
- package/src/index.ts +283 -20
- package/src/methods/code.ts +359 -0
- package/src/methods/m2m.ts +82 -0
- package/src/methods/oauth2-factory.ts +151 -0
- package/src/methods/oauth2-generic.ts +360 -0
- package/src/methods/oidc-generic.ts +109 -0
- package/src/methods/passkey.ts +419 -0
- package/src/methods/password-hash.ts +134 -0
- package/src/methods/password.ts +298 -0
- package/src/methods/providers/apple.ts +42 -0
- package/src/methods/providers/cognito.ts +55 -0
- package/src/methods/providers/discord.ts +37 -0
- package/src/methods/providers/facebook.ts +54 -0
- package/src/methods/providers/github.ts +42 -0
- package/src/methods/providers/google.ts +43 -0
- package/src/methods/providers/index.ts +23 -0
- package/src/methods/providers/jumpcloud.ts +36 -0
- package/src/methods/providers/keycloak.ts +42 -0
- package/src/methods/providers/linkedin.ts +37 -0
- package/src/methods/providers/microsoft.ts +42 -0
- package/src/methods/providers/slack.ts +42 -0
- package/src/methods/providers/spotify.ts +37 -0
- package/src/methods/providers/twitch.ts +38 -0
- package/src/methods/providers/x.ts +40 -0
- package/src/methods/providers/yahoo.ts +36 -0
- package/src/pkce.ts +20 -21
- package/src/ports/CONSISTENCY.md +119 -0
- package/src/ports/audit-log.ts +177 -0
- package/src/ports/config-store.ts +34 -0
- package/src/ports/key-store.ts +106 -0
- package/src/ports/method-store.ts +41 -0
- package/src/ports/session-store.ts +131 -0
- package/src/ports/token-store.ts +116 -0
- package/src/types/authorization.ts +78 -0
- package/src/types/error.ts +146 -0
- package/src/types/flow.ts +99 -0
- package/src/types/idp.ts +365 -0
- package/src/types/method.ts +270 -0
- package/src/types/picker.ts +32 -0
- package/src/types/result.ts +23 -0
- package/src/types/subject.ts +50 -0
- package/src/types/tenant.ts +285 -0
- package/src/types/token.ts +236 -0
- package/src/ui/forms.ts +289 -0
- package/src/ui/index.ts +14 -0
- package/src/ui/picker.ts +63 -0
- package/dist/esm/issuer.js +0 -691
- package/dist/esm/jwt.js +0 -16
- package/dist/esm/keys.js +0 -113
- package/dist/esm/provider/apple.js +0 -28
- package/dist/esm/provider/arctic.js +0 -43
- package/dist/esm/provider/code.js +0 -58
- package/dist/esm/provider/cognito.js +0 -16
- package/dist/esm/provider/discord.js +0 -15
- package/dist/esm/provider/facebook.js +0 -24
- package/dist/esm/provider/github.js +0 -15
- package/dist/esm/provider/google.js +0 -25
- package/dist/esm/provider/index.js +0 -3
- package/dist/esm/provider/jumpcloud.js +0 -15
- package/dist/esm/provider/keycloak.js +0 -15
- package/dist/esm/provider/linkedin.js +0 -15
- package/dist/esm/provider/m2m.js +0 -16
- package/dist/esm/provider/microsoft.js +0 -24
- package/dist/esm/provider/oauth2.js +0 -119
- package/dist/esm/provider/oidc.js +0 -69
- package/dist/esm/provider/passkey.js +0 -315
- package/dist/esm/provider/password.js +0 -306
- package/dist/esm/provider/provider.js +0 -10
- package/dist/esm/provider/slack.js +0 -15
- package/dist/esm/provider/spotify.js +0 -15
- package/dist/esm/provider/twitch.js +0 -15
- package/dist/esm/provider/x.js +0 -16
- package/dist/esm/provider/yahoo.js +0 -15
- package/dist/esm/random.js +0 -27
- package/dist/esm/storage/aws.js +0 -39
- package/dist/esm/storage/cloudflare.js +0 -42
- package/dist/esm/storage/dynamo.js +0 -116
- package/dist/esm/storage/memory.js +0 -88
- package/dist/esm/storage/storage.js +0 -36
- package/dist/esm/subject.js +0 -7
- package/dist/esm/ui/base.js +0 -407
- package/dist/esm/ui/code.js +0 -151
- package/dist/esm/ui/form.js +0 -43
- package/dist/esm/ui/icon.js +0 -92
- package/dist/esm/ui/passkey.js +0 -329
- package/dist/esm/ui/password.js +0 -338
- package/dist/esm/ui/select.js +0 -187
- package/dist/esm/ui/theme.js +0 -115
- package/dist/esm/util.js +0 -54
- package/dist/types/issuer.d.ts +0 -607
- package/dist/types/issuer.d.ts.map +0 -1
- package/dist/types/jwt.d.ts +0 -6
- package/dist/types/jwt.d.ts.map +0 -1
- package/dist/types/keys.d.ts +0 -18
- package/dist/types/keys.d.ts.map +0 -1
- package/dist/types/provider/apple.d.ts +0 -108
- package/dist/types/provider/apple.d.ts.map +0 -1
- package/dist/types/provider/arctic.d.ts +0 -16
- package/dist/types/provider/arctic.d.ts.map +0 -1
- package/dist/types/provider/code.d.ts +0 -74
- package/dist/types/provider/code.d.ts.map +0 -1
- package/dist/types/provider/cognito.d.ts +0 -64
- package/dist/types/provider/cognito.d.ts.map +0 -1
- package/dist/types/provider/discord.d.ts +0 -38
- package/dist/types/provider/discord.d.ts.map +0 -1
- package/dist/types/provider/facebook.d.ts +0 -74
- package/dist/types/provider/facebook.d.ts.map +0 -1
- package/dist/types/provider/github.d.ts +0 -38
- package/dist/types/provider/github.d.ts.map +0 -1
- package/dist/types/provider/google.d.ts +0 -74
- package/dist/types/provider/google.d.ts.map +0 -1
- package/dist/types/provider/index.d.ts +0 -4
- package/dist/types/provider/index.d.ts.map +0 -1
- package/dist/types/provider/jumpcloud.d.ts +0 -38
- package/dist/types/provider/jumpcloud.d.ts.map +0 -1
- package/dist/types/provider/keycloak.d.ts +0 -67
- package/dist/types/provider/keycloak.d.ts.map +0 -1
- package/dist/types/provider/linkedin.d.ts +0 -6
- package/dist/types/provider/linkedin.d.ts.map +0 -1
- package/dist/types/provider/m2m.d.ts +0 -34
- package/dist/types/provider/m2m.d.ts.map +0 -1
- package/dist/types/provider/microsoft.d.ts +0 -89
- package/dist/types/provider/microsoft.d.ts.map +0 -1
- package/dist/types/provider/oauth2.d.ts +0 -133
- package/dist/types/provider/oauth2.d.ts.map +0 -1
- package/dist/types/provider/oidc.d.ts +0 -91
- package/dist/types/provider/oidc.d.ts.map +0 -1
- package/dist/types/provider/passkey.d.ts +0 -143
- package/dist/types/provider/passkey.d.ts.map +0 -1
- package/dist/types/provider/password.d.ts +0 -210
- package/dist/types/provider/password.d.ts.map +0 -1
- package/dist/types/provider/provider.d.ts +0 -29
- package/dist/types/provider/provider.d.ts.map +0 -1
- package/dist/types/provider/slack.d.ts +0 -59
- package/dist/types/provider/slack.d.ts.map +0 -1
- package/dist/types/provider/spotify.d.ts +0 -38
- package/dist/types/provider/spotify.d.ts.map +0 -1
- package/dist/types/provider/twitch.d.ts +0 -38
- package/dist/types/provider/twitch.d.ts.map +0 -1
- package/dist/types/provider/x.d.ts +0 -38
- package/dist/types/provider/x.d.ts.map +0 -1
- package/dist/types/provider/yahoo.d.ts +0 -38
- package/dist/types/provider/yahoo.d.ts.map +0 -1
- package/dist/types/random.d.ts +0 -3
- package/dist/types/random.d.ts.map +0 -1
- package/dist/types/storage/aws.d.ts +0 -4
- package/dist/types/storage/aws.d.ts.map +0 -1
- package/dist/types/storage/cloudflare.d.ts +0 -34
- package/dist/types/storage/cloudflare.d.ts.map +0 -1
- package/dist/types/storage/dynamo.d.ts +0 -65
- package/dist/types/storage/dynamo.d.ts.map +0 -1
- package/dist/types/storage/memory.d.ts +0 -49
- package/dist/types/storage/memory.d.ts.map +0 -1
- package/dist/types/storage/storage.d.ts +0 -15
- package/dist/types/storage/storage.d.ts.map +0 -1
- package/dist/types/subject.d.ts +0 -122
- package/dist/types/subject.d.ts.map +0 -1
- package/dist/types/ui/base.d.ts +0 -5
- package/dist/types/ui/base.d.ts.map +0 -1
- package/dist/types/ui/code.d.ts +0 -104
- package/dist/types/ui/code.d.ts.map +0 -1
- package/dist/types/ui/form.d.ts +0 -6
- package/dist/types/ui/form.d.ts.map +0 -1
- package/dist/types/ui/icon.d.ts +0 -6
- package/dist/types/ui/icon.d.ts.map +0 -1
- package/dist/types/ui/passkey.d.ts +0 -5
- package/dist/types/ui/passkey.d.ts.map +0 -1
- package/dist/types/ui/password.d.ts +0 -139
- package/dist/types/ui/password.d.ts.map +0 -1
- package/dist/types/ui/select.d.ts +0 -55
- package/dist/types/ui/select.d.ts.map +0 -1
- package/dist/types/ui/theme.d.ts +0 -207
- package/dist/types/ui/theme.d.ts.map +0 -1
- package/dist/types/util.d.ts +0 -8
- package/dist/types/util.d.ts.map +0 -1
- package/src/css.d.ts +0 -4
- package/src/issuer.ts +0 -1628
- package/src/jwt.ts +0 -17
- package/src/keys.ts +0 -139
- package/src/provider/apple.ts +0 -127
- package/src/provider/arctic.ts +0 -66
- package/src/provider/code.ts +0 -227
- package/src/provider/cognito.ts +0 -74
- package/src/provider/discord.ts +0 -45
- package/src/provider/facebook.ts +0 -84
- package/src/provider/github.ts +0 -45
- package/src/provider/google.ts +0 -85
- package/src/provider/index.ts +0 -3
- package/src/provider/jumpcloud.ts +0 -45
- package/src/provider/keycloak.ts +0 -75
- package/src/provider/linkedin.ts +0 -12
- package/src/provider/m2m.ts +0 -56
- package/src/provider/microsoft.ts +0 -100
- package/src/provider/oauth2.ts +0 -297
- package/src/provider/oidc.ts +0 -179
- package/src/provider/passkey.ts +0 -655
- package/src/provider/password.ts +0 -672
- package/src/provider/provider.ts +0 -33
- package/src/provider/slack.ts +0 -67
- package/src/provider/spotify.ts +0 -45
- package/src/provider/twitch.ts +0 -45
- package/src/provider/x.ts +0 -46
- package/src/provider/yahoo.ts +0 -45
- package/src/random.ts +0 -24
- package/src/storage/aws.ts +0 -59
- package/src/storage/cloudflare.ts +0 -77
- package/src/storage/dynamo.ts +0 -193
- package/src/storage/memory.ts +0 -135
- package/src/storage/storage.ts +0 -46
- package/src/subject.ts +0 -130
- package/src/ui/base.tsx +0 -118
- package/src/ui/code.tsx +0 -215
- package/src/ui/form.tsx +0 -40
- package/src/ui/icon.tsx +0 -95
- package/src/ui/passkey.tsx +0 -321
- package/src/ui/password.tsx +0 -405
- package/src/ui/select.tsx +0 -221
- package/src/ui/theme.ts +0 -319
- package/src/ui/ui.css +0 -252
- package/src/util.ts +0 -58
- /package/dist/esm/{css.d.js → adapters/d1/types.js} +0 -0
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Postgres `ConfigStore`. JSONB blob keyed by tenant id. Invalidation hook
|
|
3
|
+
* fires on every `putTenantConfig` so any in-process cache built on top of
|
|
4
|
+
* this adapter drops the stale value before the write resolves.
|
|
5
|
+
*/
|
|
6
|
+
import type { ConfigStore } from "../../ports/config-store"
|
|
7
|
+
import { authError } from "../../types/error"
|
|
8
|
+
import type { Result } from "../../types/result"
|
|
9
|
+
import { err, ok } from "../../types/result"
|
|
10
|
+
import type { TenantConfig, TenantId } from "../../types/tenant"
|
|
11
|
+
|
|
12
|
+
import type { PostgresExecutor } from "./executor"
|
|
13
|
+
|
|
14
|
+
export type PostgresConfigStoreOptions = {
|
|
15
|
+
exec: PostgresExecutor
|
|
16
|
+
clock?: () => number
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
export class PostgresConfigStore implements ConfigStore {
|
|
20
|
+
#exec: PostgresExecutor
|
|
21
|
+
#clock: () => number
|
|
22
|
+
#listeners = new Set<(id: TenantId) => void>()
|
|
23
|
+
|
|
24
|
+
constructor(opts: PostgresConfigStoreOptions) {
|
|
25
|
+
this.#exec = opts.exec
|
|
26
|
+
this.#clock = opts.clock ?? (() => Date.now())
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
async getTenantConfig(id: TenantId): Promise<Result<TenantConfig>> {
|
|
30
|
+
let row: { config: unknown } | undefined
|
|
31
|
+
try {
|
|
32
|
+
const result = await this.#exec.query<{ config: unknown }>(
|
|
33
|
+
`SELECT config FROM openauth_tenants WHERE id = $1`,
|
|
34
|
+
[id],
|
|
35
|
+
)
|
|
36
|
+
row = result.rows[0]
|
|
37
|
+
} catch (e) {
|
|
38
|
+
return err(authError.internalError("getTenantConfig: query failed", e))
|
|
39
|
+
}
|
|
40
|
+
if (!row) {
|
|
41
|
+
return err(authError.tenantNotFound(`tenant "${id}" not found`, id))
|
|
42
|
+
}
|
|
43
|
+
const config =
|
|
44
|
+
typeof row.config === "string"
|
|
45
|
+
? (JSON.parse(row.config) as TenantConfig)
|
|
46
|
+
: (row.config as TenantConfig)
|
|
47
|
+
return ok(config)
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
async putTenantConfig(config: TenantConfig): Promise<Result<void>> {
|
|
51
|
+
try {
|
|
52
|
+
await this.#exec.query(
|
|
53
|
+
`INSERT INTO openauth_tenants (id, config, updated_at)
|
|
54
|
+
VALUES ($1, $2::jsonb, $3)
|
|
55
|
+
ON CONFLICT (id) DO UPDATE SET config = EXCLUDED.config, updated_at = EXCLUDED.updated_at`,
|
|
56
|
+
[config.id, JSON.stringify(config), this.#clock()],
|
|
57
|
+
)
|
|
58
|
+
} catch (e) {
|
|
59
|
+
return err(authError.internalError("putTenantConfig: insert failed", e))
|
|
60
|
+
}
|
|
61
|
+
for (const fn of this.#listeners) {
|
|
62
|
+
try {
|
|
63
|
+
fn(config.id)
|
|
64
|
+
} catch {}
|
|
65
|
+
}
|
|
66
|
+
return ok(undefined)
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
onInvalidate(handler: (id: TenantId) => void): void {
|
|
70
|
+
this.#listeners.add(handler)
|
|
71
|
+
}
|
|
72
|
+
}
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Thin SQL-executor interface the Postgres adapters depend on.
|
|
3
|
+
*
|
|
4
|
+
* Both the production `postgres` (porsager/postgres) driver and the embedded
|
|
5
|
+
* `@electric-sql/pglite` test driver fit behind this shape. Adapters never
|
|
6
|
+
* import either driver directly — users wire one of the `from*` helpers
|
|
7
|
+
* below.
|
|
8
|
+
*/
|
|
9
|
+
|
|
10
|
+
/** One row of a SQL result, addressed by column name. */
|
|
11
|
+
export type Row = Record<string, unknown>
|
|
12
|
+
|
|
13
|
+
/**
|
|
14
|
+
* Minimal Postgres-shaped executor. Positional `$1, $2` parameters; rows are
|
|
15
|
+
* column-name keyed objects.
|
|
16
|
+
*/
|
|
17
|
+
export type PostgresExecutor = {
|
|
18
|
+
query<T extends Row = Row>(
|
|
19
|
+
sql: string,
|
|
20
|
+
params?: ReadonlyArray<unknown>,
|
|
21
|
+
): Promise<{ rows: T[] }>
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Wrap a porsager/postgres `Sql` instance in the `PostgresExecutor` shape.
|
|
26
|
+
* The adapter calls `sql.unsafe(text, params)` so positional binds work.
|
|
27
|
+
*
|
|
28
|
+
* @example
|
|
29
|
+
* import postgres from "postgres"
|
|
30
|
+
* import { fromPostgresJs, PostgresTokenStore } from "@_mustachio/openauth/adapters/postgres"
|
|
31
|
+
* const sql = postgres(process.env.DATABASE_URL!)
|
|
32
|
+
* const exec = fromPostgresJs(sql)
|
|
33
|
+
* const store = new PostgresTokenStore({ exec, keyStore })
|
|
34
|
+
*/
|
|
35
|
+
export function fromPostgresJs(sql: PostgresJsLike): PostgresExecutor {
|
|
36
|
+
return {
|
|
37
|
+
async query<T extends Row = Row>(
|
|
38
|
+
text: string,
|
|
39
|
+
params: ReadonlyArray<unknown> = [],
|
|
40
|
+
): Promise<{ rows: T[] }> {
|
|
41
|
+
const result = await sql.unsafe(text, params as unknown[])
|
|
42
|
+
// porsager/postgres returns an array-shaped result with row objects.
|
|
43
|
+
return { rows: Array.from(result as unknown as Iterable<T>) }
|
|
44
|
+
},
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/** Minimal shape we use from porsager/postgres — kept untyped to avoid a runtime import. */
|
|
49
|
+
export type PostgresJsLike = {
|
|
50
|
+
unsafe: (text: string, params: unknown[]) => Promise<unknown>
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
/**
|
|
54
|
+
* Wrap a PGlite instance in the `PostgresExecutor` shape. Used by the
|
|
55
|
+
* port-conformance suite to run the Postgres adapters in-process without a
|
|
56
|
+
* server.
|
|
57
|
+
*/
|
|
58
|
+
export function fromPGlite(db: PGliteLike): PostgresExecutor {
|
|
59
|
+
return {
|
|
60
|
+
async query<T extends Row = Row>(
|
|
61
|
+
text: string,
|
|
62
|
+
params: ReadonlyArray<unknown> = [],
|
|
63
|
+
): Promise<{ rows: T[] }> {
|
|
64
|
+
const result = await db.query<T>(text, params as unknown[])
|
|
65
|
+
return { rows: result.rows }
|
|
66
|
+
},
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Minimal shape we use from @electric-sql/pglite. */
|
|
71
|
+
export type PGliteLike = {
|
|
72
|
+
query: <T extends Row = Row>(
|
|
73
|
+
sql: string,
|
|
74
|
+
params?: unknown[],
|
|
75
|
+
) => Promise<{ rows: T[] }>
|
|
76
|
+
}
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Postgres adapter set.
|
|
3
|
+
*
|
|
4
|
+
* Suitable for Node + Postgres deployments. Satisfies every contract in
|
|
5
|
+
* `ports/CONSISTENCY.md` — `consumeCode` / `consumeFlow` use
|
|
6
|
+
* `DELETE … RETURNING` for atomic single-winner CAS, `consumeRefresh` uses
|
|
7
|
+
* `UPDATE … WHERE consumed_at IS NULL RETURNING payload`, and `KeyStore`
|
|
8
|
+
* persists JWK material in JSONB columns.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* import postgres from "postgres"
|
|
12
|
+
* import {
|
|
13
|
+
* fromPostgresJs,
|
|
14
|
+
* migrate,
|
|
15
|
+
* PostgresTokenStore,
|
|
16
|
+
* PostgresSessionStore,
|
|
17
|
+
* PostgresKeyStore,
|
|
18
|
+
* PostgresConfigStore,
|
|
19
|
+
* PostgresMethodStore,
|
|
20
|
+
* PostgresAuditLog,
|
|
21
|
+
* } from "@_mustachio/openauth/adapters/postgres"
|
|
22
|
+
*
|
|
23
|
+
* const sql = postgres(process.env.DATABASE_URL!)
|
|
24
|
+
* const exec = fromPostgresJs(sql)
|
|
25
|
+
* await migrate(exec)
|
|
26
|
+
* const keyStore = new PostgresKeyStore({ exec })
|
|
27
|
+
* const tokenStore = new PostgresTokenStore({ exec, keyStore })
|
|
28
|
+
* // ...
|
|
29
|
+
*/
|
|
30
|
+
export {
|
|
31
|
+
fromPGlite,
|
|
32
|
+
fromPostgresJs,
|
|
33
|
+
type PGliteLike,
|
|
34
|
+
type PostgresExecutor,
|
|
35
|
+
type PostgresJsLike,
|
|
36
|
+
type Row,
|
|
37
|
+
} from "./executor"
|
|
38
|
+
export { INITIAL_SCHEMA_SQL, migrate } from "./migrations"
|
|
39
|
+
export { PostgresAuditLog, type PostgresAuditLogOptions } from "./audit-log"
|
|
40
|
+
export {
|
|
41
|
+
PostgresConfigStore,
|
|
42
|
+
type PostgresConfigStoreOptions,
|
|
43
|
+
} from "./config-store"
|
|
44
|
+
export { PostgresKeyStore, type PostgresKeyStoreOptions } from "./key-store"
|
|
45
|
+
export {
|
|
46
|
+
PostgresMethodStore,
|
|
47
|
+
type PostgresMethodStoreOptions,
|
|
48
|
+
} from "./method-store"
|
|
49
|
+
export {
|
|
50
|
+
PostgresSessionStore,
|
|
51
|
+
type PostgresSessionStoreOptions,
|
|
52
|
+
} from "./session-store"
|
|
53
|
+
export {
|
|
54
|
+
PostgresTokenStore,
|
|
55
|
+
type PostgresTokenStoreOptions,
|
|
56
|
+
} from "./token-store"
|
|
57
|
+
export {
|
|
58
|
+
PostgresPasskeyCredentialStore,
|
|
59
|
+
type PostgresPasskeyCredentialStoreOptions,
|
|
60
|
+
} from "./passkey-credential-store"
|
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Postgres `KeyStore`.
|
|
3
|
+
*
|
|
4
|
+
* Signing keys are persisted as a pair of JWK blobs (public + private) so
|
|
5
|
+
* the framework can transparently `importJWK(privateKeyRef)` on first use.
|
|
6
|
+
* Encryption keys are stored as raw bytes in a `bytea` column.
|
|
7
|
+
*
|
|
8
|
+
* On first read, if no active signing or encryption key exists the adapter
|
|
9
|
+
* auto-generates one. This keeps the developer experience aligned with the
|
|
10
|
+
* memory adapter (no manual bootstrap step) while still respecting whatever
|
|
11
|
+
* keys an operator may have provisioned out-of-band.
|
|
12
|
+
*
|
|
13
|
+
* **At-rest protection.** Pass `wrapper: { wrap, unwrap }` to encrypt the
|
|
14
|
+
* private JWK and the encryption-key bytes under a host-controlled master
|
|
15
|
+
* key (typically a KMS Encrypt/Decrypt round trip). Without a wrapper the
|
|
16
|
+
* adapter stores private material in plaintext at rest — acceptable for
|
|
17
|
+
* dev / local use, **not** acceptable for production. See `INTEGRATION.md`
|
|
18
|
+
* §4. The `private_jwk_wrapped` / `key_material_wrapped` boolean columns
|
|
19
|
+
* record which representation each row uses, so flipping a wrapper on for
|
|
20
|
+
* an existing deployment is a (forthcoming) re-wrap migration rather than
|
|
21
|
+
* a schema change.
|
|
22
|
+
*
|
|
23
|
+
* Rotation (`rotateSigningKeys` / `rotateEncryptionKeys`) is left as a Phase
|
|
24
|
+
* 8 deliverable — schema columns exist for `status` and `rotated_at`, so the
|
|
25
|
+
* later implementation will be a series of `UPDATE` statements without
|
|
26
|
+
* needing a migration.
|
|
27
|
+
*/
|
|
28
|
+
import type { JWK } from "jose"
|
|
29
|
+
import { exportJWK, generateKeyPair, importJWK } from "jose"
|
|
30
|
+
|
|
31
|
+
import {
|
|
32
|
+
base64url,
|
|
33
|
+
generateSymmetricKey,
|
|
34
|
+
randomId,
|
|
35
|
+
utf8,
|
|
36
|
+
} from "../../domain/crypto"
|
|
37
|
+
import type {
|
|
38
|
+
EncryptionKey,
|
|
39
|
+
KeyStore,
|
|
40
|
+
KeyWrapper,
|
|
41
|
+
SigningKey,
|
|
42
|
+
} from "../../ports/key-store"
|
|
43
|
+
import { authError } from "../../types/error"
|
|
44
|
+
import type { Result } from "../../types/result"
|
|
45
|
+
import { err, ok } from "../../types/result"
|
|
46
|
+
|
|
47
|
+
import type { PostgresExecutor } from "./executor"
|
|
48
|
+
|
|
49
|
+
export type PostgresKeyStoreOptions = {
|
|
50
|
+
exec: PostgresExecutor
|
|
51
|
+
clock?: () => number
|
|
52
|
+
signingAlg?: "ES256" | "EdDSA"
|
|
53
|
+
/**
|
|
54
|
+
* Optional envelope that encrypts private JWKs and encryption-key bytes
|
|
55
|
+
* before they leave the process. STRONGLY RECOMMENDED in production.
|
|
56
|
+
* Pair with a cloud KMS or HSM-backed implementation.
|
|
57
|
+
*/
|
|
58
|
+
wrapper?: KeyWrapper
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
export class PostgresKeyStore implements KeyStore {
|
|
62
|
+
#exec: PostgresExecutor
|
|
63
|
+
#clock: () => number
|
|
64
|
+
#signingAlg: "ES256" | "EdDSA"
|
|
65
|
+
#wrapper: KeyWrapper | undefined
|
|
66
|
+
// Cache imported private keys so we don't re-import on every sign.
|
|
67
|
+
#privateKeyCache = new Map<string, unknown>()
|
|
68
|
+
|
|
69
|
+
constructor(opts: PostgresKeyStoreOptions) {
|
|
70
|
+
this.#exec = opts.exec
|
|
71
|
+
this.#clock = opts.clock ?? (() => Date.now())
|
|
72
|
+
this.#signingAlg = opts.signingAlg ?? "ES256"
|
|
73
|
+
this.#wrapper = opts.wrapper
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
async currentSigningKey(): Promise<Result<SigningKey>> {
|
|
77
|
+
await this.#ensureSigningKey()
|
|
78
|
+
const rows = await this.#selectSigningRows(`status = 'active'`)
|
|
79
|
+
if (rows.length === 0) {
|
|
80
|
+
return err(
|
|
81
|
+
authError.internalError(
|
|
82
|
+
"no active signing key (should be unreachable)",
|
|
83
|
+
),
|
|
84
|
+
)
|
|
85
|
+
}
|
|
86
|
+
const key = await this.#hydrateSigningKey(rows[0]!)
|
|
87
|
+
return ok(key)
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
async signingKeys(): Promise<Result<SigningKey[]>> {
|
|
91
|
+
await this.#ensureSigningKey()
|
|
92
|
+
const rows = await this.#selectSigningRows(
|
|
93
|
+
`status IN ('active','next','retired')`,
|
|
94
|
+
)
|
|
95
|
+
const keys = await Promise.all(rows.map((r) => this.#hydrateSigningKey(r)))
|
|
96
|
+
return ok(keys)
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
async currentEncryptionKey(): Promise<Result<EncryptionKey>> {
|
|
100
|
+
await this.#ensureEncryptionKey()
|
|
101
|
+
const rows = await this.#selectEncryptionRows(`status = 'active'`)
|
|
102
|
+
if (rows.length === 0) {
|
|
103
|
+
return err(
|
|
104
|
+
authError.internalError(
|
|
105
|
+
"no active encryption key (should be unreachable)",
|
|
106
|
+
),
|
|
107
|
+
)
|
|
108
|
+
}
|
|
109
|
+
return ok(await this.#hydrateEncryptionKey(rows[0]!))
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
async getEncryptionKey(kid: string): Promise<Result<EncryptionKey>> {
|
|
113
|
+
let row: EncryptionKeyRow | undefined
|
|
114
|
+
try {
|
|
115
|
+
const result = await this.#exec.query<EncryptionKeyRow>(
|
|
116
|
+
`SELECT kid, alg, key_material, key_material_wrapped, status, created_at, rotated_at
|
|
117
|
+
FROM openauth_encryption_keys WHERE kid = $1`,
|
|
118
|
+
[kid],
|
|
119
|
+
)
|
|
120
|
+
row = result.rows[0]
|
|
121
|
+
} catch (e) {
|
|
122
|
+
return err(authError.internalError("getEncryptionKey: query failed", e))
|
|
123
|
+
}
|
|
124
|
+
if (!row) {
|
|
125
|
+
return err(authError.internalError(`encryption key "${kid}" not found`))
|
|
126
|
+
}
|
|
127
|
+
return ok(await this.#hydrateEncryptionKey(row))
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
// --- bootstrap -------------------------------------------------------
|
|
131
|
+
|
|
132
|
+
async #ensureSigningKey(): Promise<void> {
|
|
133
|
+
const rows = await this.#selectSigningRows(`status = 'active'`)
|
|
134
|
+
if (rows.length > 0) return
|
|
135
|
+
const { publicKey, privateKey } = await generateKeyPair(this.#signingAlg, {
|
|
136
|
+
extractable: true,
|
|
137
|
+
})
|
|
138
|
+
const publicJwk = await exportJWK(publicKey)
|
|
139
|
+
const privateJwk = await exportJWK(privateKey)
|
|
140
|
+
const kid = randomId()
|
|
141
|
+
const { jsonPayload, wrapped } = await this.#encodePrivateJwk(privateJwk)
|
|
142
|
+
await this.#exec.query(
|
|
143
|
+
`INSERT INTO openauth_signing_keys
|
|
144
|
+
(kid, alg, crv, public_jwk, private_jwk, private_jwk_wrapped, status, created_at)
|
|
145
|
+
VALUES ($1, $2, $3, $4::jsonb, $5::jsonb, $6, 'active', $7)
|
|
146
|
+
ON CONFLICT (kid) DO NOTHING`,
|
|
147
|
+
[
|
|
148
|
+
kid,
|
|
149
|
+
this.#signingAlg,
|
|
150
|
+
publicJwk.crv ?? null,
|
|
151
|
+
JSON.stringify(publicJwk),
|
|
152
|
+
jsonPayload,
|
|
153
|
+
wrapped,
|
|
154
|
+
this.#clock(),
|
|
155
|
+
],
|
|
156
|
+
)
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
async #ensureEncryptionKey(): Promise<void> {
|
|
160
|
+
const rows = await this.#selectEncryptionRows(`status = 'active'`)
|
|
161
|
+
if (rows.length > 0) return
|
|
162
|
+
const kid = randomId()
|
|
163
|
+
const raw = generateSymmetricKey() // 32 bytes
|
|
164
|
+
const stored = this.#wrapper ? await this.#wrapper.wrap(raw) : raw
|
|
165
|
+
await this.#exec.query(
|
|
166
|
+
`INSERT INTO openauth_encryption_keys
|
|
167
|
+
(kid, alg, key_material, key_material_wrapped, status, created_at)
|
|
168
|
+
VALUES ($1, $2, $3, $4, 'active', $5)
|
|
169
|
+
ON CONFLICT (kid) DO NOTHING`,
|
|
170
|
+
[kid, "A256GCM", stored, this.#wrapper !== undefined, this.#clock()],
|
|
171
|
+
)
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
/**
|
|
175
|
+
* Encode a private JWK for `private_jwk jsonb` storage. With a wrapper,
|
|
176
|
+
* the plaintext JWK bytes are encrypted and stored as `{"ct": <base64url>}`
|
|
177
|
+
* — never as a recognizable JWK on disk. Without one, the JWK is stored
|
|
178
|
+
* verbatim.
|
|
179
|
+
*/
|
|
180
|
+
async #encodePrivateJwk(
|
|
181
|
+
jwk: JWK,
|
|
182
|
+
): Promise<{ jsonPayload: string; wrapped: boolean }> {
|
|
183
|
+
if (!this.#wrapper) {
|
|
184
|
+
return { jsonPayload: JSON.stringify(jwk), wrapped: false }
|
|
185
|
+
}
|
|
186
|
+
const ciphertext = await this.#wrapper.wrap(
|
|
187
|
+
utf8.encode(JSON.stringify(jwk)),
|
|
188
|
+
)
|
|
189
|
+
return {
|
|
190
|
+
jsonPayload: JSON.stringify({ ct: base64url.encode(ciphertext) }),
|
|
191
|
+
wrapped: true,
|
|
192
|
+
}
|
|
193
|
+
}
|
|
194
|
+
|
|
195
|
+
async #decodePrivateJwk(raw: unknown, wrapped: boolean): Promise<JWK> {
|
|
196
|
+
const parsed =
|
|
197
|
+
typeof raw === "string"
|
|
198
|
+
? (JSON.parse(raw) as Record<string, unknown>)
|
|
199
|
+
: (raw as Record<string, unknown>)
|
|
200
|
+
if (!wrapped) return parsed as unknown as JWK
|
|
201
|
+
if (!this.#wrapper) {
|
|
202
|
+
throw new Error(
|
|
203
|
+
"PostgresKeyStore: signing key row is wrapped but no `wrapper` was supplied — refusing to read",
|
|
204
|
+
)
|
|
205
|
+
}
|
|
206
|
+
const ct = typeof parsed.ct === "string" ? parsed.ct : ""
|
|
207
|
+
if (!ct) {
|
|
208
|
+
throw new Error("PostgresKeyStore: wrapped signing key row missing `ct`")
|
|
209
|
+
}
|
|
210
|
+
const plaintext = await this.#wrapper.unwrap(base64url.decode(ct))
|
|
211
|
+
return JSON.parse(utf8.decode(plaintext)) as JWK
|
|
212
|
+
}
|
|
213
|
+
|
|
214
|
+
// --- helpers --------------------------------------------------------
|
|
215
|
+
|
|
216
|
+
async #selectSigningRows(where: string): Promise<SigningKeyRow[]> {
|
|
217
|
+
const result = await this.#exec.query<SigningKeyRow>(
|
|
218
|
+
`SELECT kid, alg, crv, public_jwk, private_jwk, private_jwk_wrapped,
|
|
219
|
+
status, created_at, rotated_at
|
|
220
|
+
FROM openauth_signing_keys WHERE ${where}`,
|
|
221
|
+
)
|
|
222
|
+
return result.rows
|
|
223
|
+
}
|
|
224
|
+
|
|
225
|
+
async #selectEncryptionRows(where: string): Promise<EncryptionKeyRow[]> {
|
|
226
|
+
const result = await this.#exec.query<EncryptionKeyRow>(
|
|
227
|
+
`SELECT kid, alg, key_material, key_material_wrapped, status, created_at, rotated_at
|
|
228
|
+
FROM openauth_encryption_keys WHERE ${where}`,
|
|
229
|
+
)
|
|
230
|
+
return result.rows
|
|
231
|
+
}
|
|
232
|
+
|
|
233
|
+
async #hydrateSigningKey(row: SigningKeyRow): Promise<SigningKey> {
|
|
234
|
+
let imported = this.#privateKeyCache.get(row.kid)
|
|
235
|
+
if (!imported) {
|
|
236
|
+
const privateJwk = await this.#decodePrivateJwk(
|
|
237
|
+
row.private_jwk,
|
|
238
|
+
row.private_jwk_wrapped === true,
|
|
239
|
+
)
|
|
240
|
+
imported = await importJWK(privateJwk, row.alg)
|
|
241
|
+
this.#privateKeyCache.set(row.kid, imported)
|
|
242
|
+
}
|
|
243
|
+
const publicJwk =
|
|
244
|
+
typeof row.public_jwk === "string"
|
|
245
|
+
? (JSON.parse(row.public_jwk) as Record<string, unknown>)
|
|
246
|
+
: (row.public_jwk as Record<string, unknown>)
|
|
247
|
+
return {
|
|
248
|
+
kid: row.kid,
|
|
249
|
+
alg: row.alg,
|
|
250
|
+
...(row.crv ? { crv: row.crv } : {}),
|
|
251
|
+
publicJwk,
|
|
252
|
+
privateKeyRef: imported,
|
|
253
|
+
status: row.status as SigningKey["status"],
|
|
254
|
+
createdAt: Number(row.created_at),
|
|
255
|
+
...(row.rotated_at !== null && row.rotated_at !== undefined
|
|
256
|
+
? { rotatedAt: Number(row.rotated_at) }
|
|
257
|
+
: {}),
|
|
258
|
+
}
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
async #hydrateEncryptionKey(row: EncryptionKeyRow): Promise<EncryptionKey> {
|
|
262
|
+
const stored = ensureBytes(row.key_material)
|
|
263
|
+
let keyRef = stored
|
|
264
|
+
if (row.key_material_wrapped === true) {
|
|
265
|
+
if (!this.#wrapper) {
|
|
266
|
+
throw new Error(
|
|
267
|
+
"PostgresKeyStore: encryption key row is wrapped but no `wrapper` was supplied — refusing to read",
|
|
268
|
+
)
|
|
269
|
+
}
|
|
270
|
+
keyRef = await this.#wrapper.unwrap(stored)
|
|
271
|
+
}
|
|
272
|
+
return {
|
|
273
|
+
kid: row.kid,
|
|
274
|
+
alg: row.alg,
|
|
275
|
+
keyRef,
|
|
276
|
+
status: row.status as EncryptionKey["status"],
|
|
277
|
+
createdAt: Number(row.created_at),
|
|
278
|
+
...(row.rotated_at !== null && row.rotated_at !== undefined
|
|
279
|
+
? { rotatedAt: Number(row.rotated_at) }
|
|
280
|
+
: {}),
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
type SigningKeyRow = {
|
|
286
|
+
kid: string
|
|
287
|
+
alg: string
|
|
288
|
+
crv: string | null
|
|
289
|
+
public_jwk: unknown
|
|
290
|
+
private_jwk: unknown
|
|
291
|
+
private_jwk_wrapped: boolean | number | null
|
|
292
|
+
status: string
|
|
293
|
+
created_at: string | number
|
|
294
|
+
rotated_at: string | number | null
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
type EncryptionKeyRow = {
|
|
298
|
+
kid: string
|
|
299
|
+
alg: string
|
|
300
|
+
key_material: Uint8Array | { type: string; data: number[] } | string
|
|
301
|
+
key_material_wrapped: boolean | number | null
|
|
302
|
+
status: string
|
|
303
|
+
created_at: string | number
|
|
304
|
+
rotated_at: string | number | null
|
|
305
|
+
}
|
|
306
|
+
|
|
307
|
+
/**
|
|
308
|
+
* Some drivers return `bytea` columns as `Uint8Array`; some return
|
|
309
|
+
* `Buffer`; some return base64-decoded strings or `{ type: "Buffer", data: [...] }`.
|
|
310
|
+
* Normalize to a plain `Uint8Array` so the encryption path is driver-agnostic.
|
|
311
|
+
*/
|
|
312
|
+
function ensureBytes(value: EncryptionKeyRow["key_material"]): Uint8Array {
|
|
313
|
+
if (value instanceof Uint8Array) return value
|
|
314
|
+
if (typeof value === "string") {
|
|
315
|
+
// Best-effort: hex-encoded by postgres-js default; PGlite returns Uint8Array.
|
|
316
|
+
if (/^\\x[0-9a-fA-F]+$/.test(value)) {
|
|
317
|
+
const hex = value.slice(2)
|
|
318
|
+
const out = new Uint8Array(hex.length / 2)
|
|
319
|
+
for (let i = 0; i < out.length; i++) {
|
|
320
|
+
out[i] = parseInt(hex.slice(i * 2, i * 2 + 2), 16)
|
|
321
|
+
}
|
|
322
|
+
return out
|
|
323
|
+
}
|
|
324
|
+
return new TextEncoder().encode(value)
|
|
325
|
+
}
|
|
326
|
+
if (
|
|
327
|
+
value &&
|
|
328
|
+
typeof value === "object" &&
|
|
329
|
+
"data" in (value as Record<string, unknown>)
|
|
330
|
+
) {
|
|
331
|
+
return new Uint8Array((value as { data: number[] }).data)
|
|
332
|
+
}
|
|
333
|
+
throw new Error("PostgresKeyStore: unsupported bytea representation")
|
|
334
|
+
}
|
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Postgres `MethodStore`. `(tenant_id, method_id)` composite key, JSONB
|
|
3
|
+
* `config` column for the method-config blob.
|
|
4
|
+
*/
|
|
5
|
+
import type { MethodStore } from "../../ports/method-store"
|
|
6
|
+
import { authError } from "../../types/error"
|
|
7
|
+
import type { Result } from "../../types/result"
|
|
8
|
+
import { err, ok } from "../../types/result"
|
|
9
|
+
import type { MethodConfig, TenantId } from "../../types/tenant"
|
|
10
|
+
|
|
11
|
+
import type { PostgresExecutor } from "./executor"
|
|
12
|
+
|
|
13
|
+
export type PostgresMethodStoreOptions = {
|
|
14
|
+
exec: PostgresExecutor
|
|
15
|
+
clock?: () => number
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export class PostgresMethodStore implements MethodStore {
|
|
19
|
+
#exec: PostgresExecutor
|
|
20
|
+
#clock: () => number
|
|
21
|
+
|
|
22
|
+
constructor(opts: PostgresMethodStoreOptions) {
|
|
23
|
+
this.#exec = opts.exec
|
|
24
|
+
this.#clock = opts.clock ?? (() => Date.now())
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
async listMethods(tenantId: TenantId): Promise<Result<MethodConfig[]>> {
|
|
28
|
+
try {
|
|
29
|
+
const result = await this.#exec.query<{ config: unknown }>(
|
|
30
|
+
`SELECT config FROM openauth_methods WHERE tenant_id = $1 ORDER BY method_id`,
|
|
31
|
+
[tenantId],
|
|
32
|
+
)
|
|
33
|
+
const methods = result.rows.map((r) => parseConfig(r.config))
|
|
34
|
+
return ok(methods)
|
|
35
|
+
} catch (e) {
|
|
36
|
+
return err(authError.internalError("listMethods: query failed", e))
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
async getMethodConfig(
|
|
41
|
+
tenantId: TenantId,
|
|
42
|
+
methodId: string,
|
|
43
|
+
): Promise<Result<MethodConfig>> {
|
|
44
|
+
let row: { config: unknown } | undefined
|
|
45
|
+
try {
|
|
46
|
+
const result = await this.#exec.query<{ config: unknown }>(
|
|
47
|
+
`SELECT config FROM openauth_methods WHERE tenant_id = $1 AND method_id = $2`,
|
|
48
|
+
[tenantId, methodId],
|
|
49
|
+
)
|
|
50
|
+
row = result.rows[0]
|
|
51
|
+
} catch (e) {
|
|
52
|
+
return err(authError.internalError("getMethodConfig: query failed", e))
|
|
53
|
+
}
|
|
54
|
+
if (!row) {
|
|
55
|
+
return err(
|
|
56
|
+
authError.methodNotFound(
|
|
57
|
+
`method "${methodId}" not found for tenant "${tenantId}"`,
|
|
58
|
+
{ methodId },
|
|
59
|
+
),
|
|
60
|
+
)
|
|
61
|
+
}
|
|
62
|
+
return ok(parseConfig(row.config))
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
async putMethodConfig(
|
|
66
|
+
tenantId: TenantId,
|
|
67
|
+
method: MethodConfig,
|
|
68
|
+
): Promise<Result<void>> {
|
|
69
|
+
try {
|
|
70
|
+
await this.#exec.query(
|
|
71
|
+
`INSERT INTO openauth_methods (tenant_id, method_id, config, updated_at)
|
|
72
|
+
VALUES ($1, $2, $3::jsonb, $4)
|
|
73
|
+
ON CONFLICT (tenant_id, method_id) DO UPDATE
|
|
74
|
+
SET config = EXCLUDED.config, updated_at = EXCLUDED.updated_at`,
|
|
75
|
+
[tenantId, method.id, JSON.stringify(method), this.#clock()],
|
|
76
|
+
)
|
|
77
|
+
} catch (e) {
|
|
78
|
+
return err(authError.internalError("putMethodConfig: insert failed", e))
|
|
79
|
+
}
|
|
80
|
+
return ok(undefined)
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
async deleteMethodConfig(
|
|
84
|
+
tenantId: TenantId,
|
|
85
|
+
methodId: string,
|
|
86
|
+
): Promise<Result<void>> {
|
|
87
|
+
try {
|
|
88
|
+
await this.#exec.query(
|
|
89
|
+
`DELETE FROM openauth_methods WHERE tenant_id = $1 AND method_id = $2`,
|
|
90
|
+
[tenantId, methodId],
|
|
91
|
+
)
|
|
92
|
+
} catch (e) {
|
|
93
|
+
return err(
|
|
94
|
+
authError.internalError("deleteMethodConfig: delete failed", e),
|
|
95
|
+
)
|
|
96
|
+
}
|
|
97
|
+
return ok(undefined)
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
function parseConfig(raw: unknown): MethodConfig {
|
|
102
|
+
if (typeof raw === "string") return JSON.parse(raw) as MethodConfig
|
|
103
|
+
return raw as MethodConfig
|
|
104
|
+
}
|