@atproto/oauth-provider 0.16.0 → 0.16.2
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/CHANGELOG.md +13 -0
- package/dist/account/account-manager.d.ts +2 -1
- package/dist/account/account-manager.d.ts.map +1 -1
- package/dist/account/account-manager.js +45 -4
- package/dist/account/account-manager.js.map +1 -1
- package/dist/account/account-store.d.ts +9 -3
- package/dist/account/account-store.d.ts.map +1 -1
- package/dist/account/account-store.js +2 -1
- package/dist/account/account-store.js.map +1 -1
- package/dist/errors/invalid-credentials-error.d.ts +24 -0
- package/dist/errors/invalid-credentials-error.d.ts.map +1 -0
- package/dist/errors/invalid-credentials-error.js +30 -0
- package/dist/errors/invalid-credentials-error.js.map +1 -0
- package/dist/oauth-errors.d.ts +1 -0
- package/dist/oauth-errors.d.ts.map +1 -1
- package/dist/oauth-errors.js +1 -0
- package/dist/oauth-errors.js.map +1 -1
- package/dist/oauth-hooks.d.ts +40 -1
- package/dist/oauth-hooks.d.ts.map +1 -1
- package/dist/oauth-hooks.js +3 -1
- package/dist/oauth-hooks.js.map +1 -1
- package/dist/request/request-manager.d.ts +7 -0
- package/dist/request/request-manager.d.ts.map +1 -1
- package/dist/request/request-manager.js +11 -0
- package/dist/request/request-manager.js.map +1 -1
- package/dist/router/create-api-middleware.d.ts.map +1 -1
- package/dist/router/create-api-middleware.js +6 -1
- package/dist/router/create-api-middleware.js.map +1 -1
- package/package.json +3 -3
- package/src/account/account-manager.ts +49 -6
- package/src/account/account-store.ts +9 -1
- package/src/errors/invalid-credentials-error.ts +29 -0
- package/src/oauth-errors.ts +1 -0
- package/src/oauth-hooks.ts +42 -0
- package/src/request/request-manager.ts +12 -0
- package/src/router/create-api-middleware.ts +7 -0
- package/tsconfig.build.tsbuildinfo +1 -1
package/src/oauth-hooks.ts
CHANGED
|
@@ -23,6 +23,7 @@ import { DeviceId } from './device/device-id.js'
|
|
|
23
23
|
import { DpopProof } from './dpop/dpop-proof.js'
|
|
24
24
|
import { AccessDeniedError } from './errors/access-denied-error.js'
|
|
25
25
|
import { AuthorizationError } from './errors/authorization-error.js'
|
|
26
|
+
import { InvalidCredentialsError } from './errors/invalid-credentials-error.js'
|
|
26
27
|
import { InvalidRequestError } from './errors/invalid-request-error.js'
|
|
27
28
|
import { OAuthError } from './errors/oauth-error.js'
|
|
28
29
|
import {
|
|
@@ -32,6 +33,7 @@ import {
|
|
|
32
33
|
} from './lib/hcaptcha.js'
|
|
33
34
|
import { RequestMetadata } from './lib/http/request.js'
|
|
34
35
|
import { Awaitable, OmitKey } from './lib/util/type.js'
|
|
36
|
+
import { Sub } from './oidc/sub.js'
|
|
35
37
|
import { RequestId } from './request/request-id.js'
|
|
36
38
|
import { AccessTokenPayload } from './signer/access-token-payload.js'
|
|
37
39
|
import { TokenClaims } from './token/token-claims.js'
|
|
@@ -52,6 +54,7 @@ export {
|
|
|
52
54
|
type HcaptchaClientTokens,
|
|
53
55
|
type HcaptchaConfig,
|
|
54
56
|
type HcaptchaVerifyResult,
|
|
57
|
+
InvalidCredentialsError,
|
|
55
58
|
InvalidRequestError,
|
|
56
59
|
type Jwks,
|
|
57
60
|
type OAuthAccessToken,
|
|
@@ -67,6 +70,7 @@ export {
|
|
|
67
70
|
type SignInData,
|
|
68
71
|
type SignUpData,
|
|
69
72
|
type SignUpInput,
|
|
73
|
+
type Sub,
|
|
70
74
|
type TokenClaims,
|
|
71
75
|
}
|
|
72
76
|
|
|
@@ -159,15 +163,25 @@ export type OAuthHooks = {
|
|
|
159
163
|
deviceMetadata: RequestMetadata
|
|
160
164
|
}) => Awaitable<void>
|
|
161
165
|
|
|
166
|
+
/**
|
|
167
|
+
* `clientId` is populated when the sign-in is submitted in the context of
|
|
168
|
+
* an OAuth authorization request (i.e. the user is logging in to approve a
|
|
169
|
+
* client); it is omitted for first-party sign-ins that happen outside any
|
|
170
|
+
* authorization flow.
|
|
171
|
+
*/
|
|
162
172
|
onSignInAttempt?: (data: {
|
|
163
173
|
data: SignInData
|
|
164
174
|
deviceId: DeviceId
|
|
165
175
|
deviceMetadata: RequestMetadata
|
|
176
|
+
clientId?: ClientId
|
|
166
177
|
}) => Awaitable<void>
|
|
167
178
|
|
|
168
179
|
/**
|
|
169
180
|
* This hook is called when a user successfully signs in.
|
|
170
181
|
*
|
|
182
|
+
* `clientId` is populated when the sign-in is submitted in the context of
|
|
183
|
+
* an OAuth authorization request; see {@link OAuthHooks.onSignInAttempt}.
|
|
184
|
+
*
|
|
171
185
|
* @throws {InvalidRequestError} when the sing-in should be denied
|
|
172
186
|
*/
|
|
173
187
|
onSignedIn?: (data: {
|
|
@@ -175,6 +189,34 @@ export type OAuthHooks = {
|
|
|
175
189
|
account: Account
|
|
176
190
|
deviceId: DeviceId
|
|
177
191
|
deviceMetadata: RequestMetadata
|
|
192
|
+
clientId?: ClientId
|
|
193
|
+
}) => Awaitable<void>
|
|
194
|
+
|
|
195
|
+
/**
|
|
196
|
+
* This hook is called when a sign-in attempt is rejected by the account
|
|
197
|
+
* store due to invalid credentials (e.g. unknown identifier, wrong
|
|
198
|
+
* password). It is *not* called for unexpected server errors, nor for flows
|
|
199
|
+
* that require an additional authentication factor.
|
|
200
|
+
*
|
|
201
|
+
* `sub` is populated when the store throws an
|
|
202
|
+
* {@link InvalidCredentialsError} that carries the matched subject
|
|
203
|
+
* identifier (i.e. identifier known, credentials wrong). It is `null` when
|
|
204
|
+
* the identifier was unknown or when the store threw a plain
|
|
205
|
+
* {@link InvalidRequestError} without distinguishing the two cases.
|
|
206
|
+
*
|
|
207
|
+
* `clientId` is populated when the sign-in is submitted in the context of
|
|
208
|
+
* an OAuth authorization request; see {@link OAuthHooks.onSignInAttempt}.
|
|
209
|
+
*
|
|
210
|
+
* Errors thrown from this hook are caught and ignored so that they do not
|
|
211
|
+
* mask the original authentication failure.
|
|
212
|
+
*/
|
|
213
|
+
onSignInFailed?: (data: {
|
|
214
|
+
data: SignInData
|
|
215
|
+
error: InvalidRequestError
|
|
216
|
+
sub: Sub | null
|
|
217
|
+
deviceId: DeviceId
|
|
218
|
+
deviceMetadata: RequestMetadata
|
|
219
|
+
clientId?: ClientId
|
|
178
220
|
}) => Awaitable<void>
|
|
179
221
|
|
|
180
222
|
/**
|
|
@@ -316,6 +316,18 @@ export class RequestManager {
|
|
|
316
316
|
return parameters
|
|
317
317
|
}
|
|
318
318
|
|
|
319
|
+
/**
|
|
320
|
+
* Reads the {@link ClientId} associated with a request URI without any of
|
|
321
|
+
* the validation or side-effects performed by {@link RequestManager.get}
|
|
322
|
+
*
|
|
323
|
+
* Returns `undefined` when no such request exists.
|
|
324
|
+
*/
|
|
325
|
+
async peekClientId(requestUri: RequestUri): Promise<ClientId | undefined> {
|
|
326
|
+
const requestId = decodeRequestUri(requestUri)
|
|
327
|
+
const data = await this.store.readRequest(requestId)
|
|
328
|
+
return data?.clientId
|
|
329
|
+
}
|
|
330
|
+
|
|
319
331
|
async get(requestUri: RequestUri, deviceId?: DeviceId, clientId?: ClientId) {
|
|
320
332
|
const requestId = decodeRequestUri(requestUri)
|
|
321
333
|
|
|
@@ -145,10 +145,17 @@ export function createApiMiddleware<
|
|
|
145
145
|
// Remember when not in the context of a request by default
|
|
146
146
|
const { remember = requestUri == null, ...input } = this.input
|
|
147
147
|
|
|
148
|
+
// Look up the client identifier associated with the pending OAuth
|
|
149
|
+
// request, if any, so it can be surfaced to the sign-in hooks.
|
|
150
|
+
const clientId = requestUri
|
|
151
|
+
? await server.requestManager.peekClientId(requestUri)
|
|
152
|
+
: undefined
|
|
153
|
+
|
|
148
154
|
const account = await server.accountManager.authenticateAccount(
|
|
149
155
|
deviceId,
|
|
150
156
|
deviceMetadata,
|
|
151
157
|
input,
|
|
158
|
+
clientId,
|
|
152
159
|
)
|
|
153
160
|
|
|
154
161
|
if (remember) {
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"root":["./src/constants.ts","./src/index.ts","./src/oauth-client.ts","./src/oauth-dpop.ts","./src/oauth-errors.ts","./src/oauth-hooks.ts","./src/oauth-middleware.ts","./src/oauth-provider.ts","./src/oauth-store.ts","./src/oauth-verifier.ts","./src/access-token/access-token-mode.ts","./src/account/account-manager.ts","./src/account/account-store.ts","./src/account/sign-in-data.ts","./src/account/sign-up-input.ts","./src/client/client-auth.ts","./src/client/client-data.ts","./src/client/client-id.ts","./src/client/client-info.ts","./src/client/client-manager.ts","./src/client/client-store.ts","./src/client/client-utils.ts","./src/client/client.ts","./src/customization/branding.ts","./src/customization/build-customization-css.ts","./src/customization/build-customization-data.ts","./src/customization/colors.ts","./src/customization/customization.ts","./src/customization/links.ts","./src/device/device-data.ts","./src/device/device-id.ts","./src/device/device-manager.ts","./src/device/device-store.ts","./src/device/session-id.ts","./src/dpop/dpop-manager.ts","./src/dpop/dpop-nonce.ts","./src/dpop/dpop-proof.ts","./src/errors/access-denied-error.ts","./src/errors/account-selection-required-error.ts","./src/errors/authorization-error.ts","./src/errors/consent-required-error.ts","./src/errors/error-parser.ts","./src/errors/handle-unavailable-error.ts","./src/errors/invalid-authorization-details-error.ts","./src/errors/invalid-client-error.ts","./src/errors/invalid-client-id-error.ts","./src/errors/invalid-client-metadata-error.ts","./src/errors/invalid-dpop-key-binding-error.ts","./src/errors/invalid-dpop-proof-error.ts","./src/errors/invalid-grant-error.ts","./src/errors/invalid-invite-code-error.ts","./src/errors/invalid-redirect-uri-error.ts","./src/errors/invalid-request-error.ts","./src/errors/invalid-scope-error.ts","./src/errors/invalid-token-error.ts","./src/errors/login-required-error.ts","./src/errors/oauth-error.ts","./src/errors/second-authentication-factor-required-error.ts","./src/errors/unauthorized-client-error.ts","./src/errors/use-dpop-nonce-error.ts","./src/errors/www-authenticate-error.ts","./src/lexicon/lexicon-data.ts","./src/lexicon/lexicon-getter.ts","./src/lexicon/lexicon-manager.ts","./src/lexicon/lexicon-store.ts","./src/lib/hcaptcha.ts","./src/lib/nsid.ts","./src/lib/redis.ts","./src/lib/write-form-redirect.ts","./src/lib/write-html.ts","./src/lib/csp/index.ts","./src/lib/html/build-document.ts","./src/lib/html/escapers.ts","./src/lib/html/html.ts","./src/lib/html/hydration-data.ts","./src/lib/html/index.ts","./src/lib/html/tags.ts","./src/lib/html/util.ts","./src/lib/http/accept.ts","./src/lib/http/context.ts","./src/lib/http/headers.ts","./src/lib/http/index.ts","./src/lib/http/method.ts","./src/lib/http/middleware.ts","./src/lib/http/parser.ts","./src/lib/http/path.ts","./src/lib/http/request.ts","./src/lib/http/response.ts","./src/lib/http/route.ts","./src/lib/http/router.ts","./src/lib/http/security-headers.ts","./src/lib/http/stream.ts","./src/lib/http/types.ts","./src/lib/http/url.ts","./src/lib/util/authorization-header.ts","./src/lib/util/cast.ts","./src/lib/util/color.ts","./src/lib/util/crypto.ts","./src/lib/util/date.ts","./src/lib/util/error.ts","./src/lib/util/function.ts","./src/lib/util/locale.ts","./src/lib/util/object.ts","./src/lib/util/redirect-uri.ts","./src/lib/util/time.ts","./src/lib/util/type.ts","./src/lib/util/ui8.ts","./src/lib/util/well-known.ts","./src/lib/util/zod-error.ts","./src/metadata/build-metadata.ts","./src/oidc/sub.ts","./src/replay/replay-manager.ts","./src/replay/replay-store-memory.ts","./src/replay/replay-store-redis.ts","./src/replay/replay-store.ts","./src/request/code.ts","./src/request/request-data.ts","./src/request/request-id.ts","./src/request/request-manager.ts","./src/request/request-store.ts","./src/request/request-uri.ts","./src/result/authorization-redirect-parameters.ts","./src/result/authorization-result-authorize-page.ts","./src/result/authorization-result-redirect.ts","./src/router/create-account-page-middleware.ts","./src/router/create-api-middleware.ts","./src/router/create-authorization-page-middleware.ts","./src/router/create-oauth-middleware.ts","./src/router/error-handler.ts","./src/router/middleware-options.ts","./src/router/assets/assets-manifest.ts","./src/router/assets/assets.ts","./src/router/assets/csrf.ts","./src/router/assets/send-account-page.ts","./src/router/assets/send-authorization-page.ts","./src/router/assets/send-cookie-error-page.ts","./src/router/assets/send-error-page.ts","./src/router/assets/send-redirect.ts","./src/signer/access-token-payload.ts","./src/signer/api-token-payload.ts","./src/signer/signer.ts","./src/token/refresh-token.ts","./src/token/token-claims.ts","./src/token/token-data.ts","./src/token/token-id.ts","./src/token/token-manager.ts","./src/token/token-store.ts","./src/types/authorization-response-error.ts","./src/types/color-hue.ts","./src/types/email-otp.ts","./src/types/email.ts","./src/types/handle.ts","./src/types/invite-code.ts","./src/types/par-response-error.ts","./src/types/password.ts","./src/types/rgb-color.ts"],"version":"5.8.3"}
|
|
1
|
+
{"root":["./src/constants.ts","./src/index.ts","./src/oauth-client.ts","./src/oauth-dpop.ts","./src/oauth-errors.ts","./src/oauth-hooks.ts","./src/oauth-middleware.ts","./src/oauth-provider.ts","./src/oauth-store.ts","./src/oauth-verifier.ts","./src/access-token/access-token-mode.ts","./src/account/account-manager.ts","./src/account/account-store.ts","./src/account/sign-in-data.ts","./src/account/sign-up-input.ts","./src/client/client-auth.ts","./src/client/client-data.ts","./src/client/client-id.ts","./src/client/client-info.ts","./src/client/client-manager.ts","./src/client/client-store.ts","./src/client/client-utils.ts","./src/client/client.ts","./src/customization/branding.ts","./src/customization/build-customization-css.ts","./src/customization/build-customization-data.ts","./src/customization/colors.ts","./src/customization/customization.ts","./src/customization/links.ts","./src/device/device-data.ts","./src/device/device-id.ts","./src/device/device-manager.ts","./src/device/device-store.ts","./src/device/session-id.ts","./src/dpop/dpop-manager.ts","./src/dpop/dpop-nonce.ts","./src/dpop/dpop-proof.ts","./src/errors/access-denied-error.ts","./src/errors/account-selection-required-error.ts","./src/errors/authorization-error.ts","./src/errors/consent-required-error.ts","./src/errors/error-parser.ts","./src/errors/handle-unavailable-error.ts","./src/errors/invalid-authorization-details-error.ts","./src/errors/invalid-client-error.ts","./src/errors/invalid-client-id-error.ts","./src/errors/invalid-client-metadata-error.ts","./src/errors/invalid-credentials-error.ts","./src/errors/invalid-dpop-key-binding-error.ts","./src/errors/invalid-dpop-proof-error.ts","./src/errors/invalid-grant-error.ts","./src/errors/invalid-invite-code-error.ts","./src/errors/invalid-redirect-uri-error.ts","./src/errors/invalid-request-error.ts","./src/errors/invalid-scope-error.ts","./src/errors/invalid-token-error.ts","./src/errors/login-required-error.ts","./src/errors/oauth-error.ts","./src/errors/second-authentication-factor-required-error.ts","./src/errors/unauthorized-client-error.ts","./src/errors/use-dpop-nonce-error.ts","./src/errors/www-authenticate-error.ts","./src/lexicon/lexicon-data.ts","./src/lexicon/lexicon-getter.ts","./src/lexicon/lexicon-manager.ts","./src/lexicon/lexicon-store.ts","./src/lib/hcaptcha.ts","./src/lib/nsid.ts","./src/lib/redis.ts","./src/lib/write-form-redirect.ts","./src/lib/write-html.ts","./src/lib/csp/index.ts","./src/lib/html/build-document.ts","./src/lib/html/escapers.ts","./src/lib/html/html.ts","./src/lib/html/hydration-data.ts","./src/lib/html/index.ts","./src/lib/html/tags.ts","./src/lib/html/util.ts","./src/lib/http/accept.ts","./src/lib/http/context.ts","./src/lib/http/headers.ts","./src/lib/http/index.ts","./src/lib/http/method.ts","./src/lib/http/middleware.ts","./src/lib/http/parser.ts","./src/lib/http/path.ts","./src/lib/http/request.ts","./src/lib/http/response.ts","./src/lib/http/route.ts","./src/lib/http/router.ts","./src/lib/http/security-headers.ts","./src/lib/http/stream.ts","./src/lib/http/types.ts","./src/lib/http/url.ts","./src/lib/util/authorization-header.ts","./src/lib/util/cast.ts","./src/lib/util/color.ts","./src/lib/util/crypto.ts","./src/lib/util/date.ts","./src/lib/util/error.ts","./src/lib/util/function.ts","./src/lib/util/locale.ts","./src/lib/util/object.ts","./src/lib/util/redirect-uri.ts","./src/lib/util/time.ts","./src/lib/util/type.ts","./src/lib/util/ui8.ts","./src/lib/util/well-known.ts","./src/lib/util/zod-error.ts","./src/metadata/build-metadata.ts","./src/oidc/sub.ts","./src/replay/replay-manager.ts","./src/replay/replay-store-memory.ts","./src/replay/replay-store-redis.ts","./src/replay/replay-store.ts","./src/request/code.ts","./src/request/request-data.ts","./src/request/request-id.ts","./src/request/request-manager.ts","./src/request/request-store.ts","./src/request/request-uri.ts","./src/result/authorization-redirect-parameters.ts","./src/result/authorization-result-authorize-page.ts","./src/result/authorization-result-redirect.ts","./src/router/create-account-page-middleware.ts","./src/router/create-api-middleware.ts","./src/router/create-authorization-page-middleware.ts","./src/router/create-oauth-middleware.ts","./src/router/error-handler.ts","./src/router/middleware-options.ts","./src/router/assets/assets-manifest.ts","./src/router/assets/assets.ts","./src/router/assets/csrf.ts","./src/router/assets/send-account-page.ts","./src/router/assets/send-authorization-page.ts","./src/router/assets/send-cookie-error-page.ts","./src/router/assets/send-error-page.ts","./src/router/assets/send-redirect.ts","./src/signer/access-token-payload.ts","./src/signer/api-token-payload.ts","./src/signer/signer.ts","./src/token/refresh-token.ts","./src/token/token-claims.ts","./src/token/token-data.ts","./src/token/token-id.ts","./src/token/token-manager.ts","./src/token/token-store.ts","./src/types/authorization-response-error.ts","./src/types/color-hue.ts","./src/types/email-otp.ts","./src/types/email.ts","./src/types/handle.ts","./src/types/invite-code.ts","./src/types/par-response-error.ts","./src/types/password.ts","./src/types/rgb-color.ts"],"version":"5.8.3"}
|