@atproto/oauth-provider 0.13.1 → 0.13.3
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 +32 -0
- package/dist/access-token/access-token-mode.js.map +1 -1
- package/dist/account/account-manager.d.ts.map +1 -1
- package/dist/account/account-manager.js +20 -2
- package/dist/account/account-manager.js.map +1 -1
- package/dist/account/account-store.d.ts +2 -2
- package/dist/account/account-store.d.ts.map +1 -1
- package/dist/account/account-store.js.map +1 -1
- package/dist/account/sign-in-data.js.map +1 -1
- package/dist/account/sign-up-input.js.map +1 -1
- package/dist/client/client-auth.js.map +1 -1
- package/dist/client/client-data.js.map +1 -1
- package/dist/client/client-id.js.map +1 -1
- package/dist/client/client-info.js.map +1 -1
- package/dist/client/client-manager.d.ts.map +1 -1
- package/dist/client/client-manager.js +31 -53
- package/dist/client/client-manager.js.map +1 -1
- package/dist/client/client-store.js.map +1 -1
- package/dist/client/client-utils.d.ts.map +1 -1
- package/dist/client/client-utils.js +1 -2
- package/dist/client/client-utils.js.map +1 -1
- package/dist/client/client.js.map +1 -1
- package/dist/constants.js.map +1 -1
- package/dist/customization/branding.js.map +1 -1
- package/dist/customization/build-customization-css.js.map +1 -1
- package/dist/customization/build-customization-data.js.map +1 -1
- package/dist/customization/colors.js.map +1 -1
- package/dist/customization/customization.js.map +1 -1
- package/dist/customization/links.js.map +1 -1
- package/dist/device/device-data.js.map +1 -1
- package/dist/device/device-id.js.map +1 -1
- package/dist/device/device-manager.d.ts +8 -8
- package/dist/device/device-manager.js.map +1 -1
- package/dist/device/device-store.js.map +1 -1
- package/dist/device/session-id.js.map +1 -1
- package/dist/dpop/dpop-manager.js.map +1 -1
- package/dist/dpop/dpop-nonce.js.map +1 -1
- package/dist/dpop/dpop-proof.js.map +1 -1
- package/dist/errors/access-denied-error.js.map +1 -1
- package/dist/errors/account-selection-required-error.js.map +1 -1
- package/dist/errors/authorization-error.js.map +1 -1
- package/dist/errors/consent-required-error.js.map +1 -1
- package/dist/errors/error-parser.js.map +1 -1
- package/dist/errors/handle-unavailable-error.js.map +1 -1
- package/dist/errors/invalid-authorization-details-error.js.map +1 -1
- package/dist/errors/invalid-client-error.js.map +1 -1
- package/dist/errors/invalid-client-id-error.js.map +1 -1
- package/dist/errors/invalid-client-metadata-error.js.map +1 -1
- package/dist/errors/invalid-dpop-key-binding-error.js.map +1 -1
- package/dist/errors/invalid-dpop-proof-error.js.map +1 -1
- package/dist/errors/invalid-grant-error.js.map +1 -1
- package/dist/errors/invalid-invite-code-error.js.map +1 -1
- package/dist/errors/invalid-redirect-uri-error.js.map +1 -1
- package/dist/errors/invalid-request-error.js.map +1 -1
- package/dist/errors/invalid-scope-error.js.map +1 -1
- package/dist/errors/invalid-token-error.js.map +1 -1
- package/dist/errors/login-required-error.js.map +1 -1
- package/dist/errors/oauth-error.js.map +1 -1
- package/dist/errors/second-authentication-factor-required-error.js.map +1 -1
- package/dist/errors/unauthorized-client-error.js.map +1 -1
- package/dist/errors/use-dpop-nonce-error.js.map +1 -1
- package/dist/errors/www-authenticate-error.js.map +1 -1
- package/dist/index.js.map +1 -1
- package/dist/lexicon/lexicon-data.js.map +1 -1
- package/dist/lexicon/lexicon-getter.js.map +1 -1
- package/dist/lexicon/lexicon-manager.js.map +1 -1
- package/dist/lexicon/lexicon-store.js.map +1 -1
- package/dist/lib/csp/index.js.map +1 -1
- package/dist/lib/hcaptcha.js.map +1 -1
- package/dist/lib/html/build-document.js.map +1 -1
- package/dist/lib/html/escapers.js.map +1 -1
- package/dist/lib/html/html.js.map +1 -1
- package/dist/lib/html/hydration-data.js.map +1 -1
- package/dist/lib/html/index.js.map +1 -1
- package/dist/lib/html/tags.js.map +1 -1
- package/dist/lib/html/util.js.map +1 -1
- package/dist/lib/http/accept.js.map +1 -1
- package/dist/lib/http/context.js.map +1 -1
- package/dist/lib/http/headers.js.map +1 -1
- package/dist/lib/http/index.js.map +1 -1
- package/dist/lib/http/method.js.map +1 -1
- package/dist/lib/http/middleware.js.map +1 -1
- package/dist/lib/http/parser.js.map +1 -1
- package/dist/lib/http/path.js.map +1 -1
- package/dist/lib/http/request.js.map +1 -1
- package/dist/lib/http/response.js.map +1 -1
- package/dist/lib/http/route.js.map +1 -1
- package/dist/lib/http/router.js.map +1 -1
- package/dist/lib/http/security-headers.js.map +1 -1
- package/dist/lib/http/stream.js.map +1 -1
- package/dist/lib/http/types.js.map +1 -1
- package/dist/lib/http/url.js.map +1 -1
- package/dist/lib/nsid.js.map +1 -1
- package/dist/lib/redis.js.map +1 -1
- package/dist/lib/send-web-page.js.map +1 -1
- package/dist/lib/util/authorization-header.js.map +1 -1
- package/dist/lib/util/cast.js.map +1 -1
- package/dist/lib/util/color.js.map +1 -1
- package/dist/lib/util/crypto.js.map +1 -1
- package/dist/lib/util/date.js.map +1 -1
- package/dist/lib/util/error.js.map +1 -1
- package/dist/lib/util/function.js.map +1 -1
- package/dist/lib/util/locale.js.map +1 -1
- package/dist/lib/util/redirect-uri.js.map +1 -1
- package/dist/lib/util/time.js.map +1 -1
- package/dist/lib/util/type.js.map +1 -1
- package/dist/lib/util/ui8.js.map +1 -1
- package/dist/lib/util/well-known.js.map +1 -1
- package/dist/lib/util/zod-error.js.map +1 -1
- package/dist/metadata/build-metadata.js +4 -3
- package/dist/metadata/build-metadata.js.map +1 -1
- package/dist/oauth-client.js.map +1 -1
- package/dist/oauth-dpop.js.map +1 -1
- package/dist/oauth-errors.js.map +1 -1
- package/dist/oauth-hooks.d.ts +20 -0
- package/dist/oauth-hooks.d.ts.map +1 -1
- package/dist/oauth-hooks.js.map +1 -1
- package/dist/oauth-middleware.js.map +1 -1
- package/dist/oauth-provider.d.ts +128 -98
- package/dist/oauth-provider.d.ts.map +1 -1
- package/dist/oauth-provider.js.map +1 -1
- package/dist/oauth-store.js.map +1 -1
- package/dist/oauth-verifier.js.map +1 -1
- package/dist/oidc/sub.js.map +1 -1
- package/dist/replay/replay-manager.js.map +1 -1
- package/dist/replay/replay-store-memory.js.map +1 -1
- package/dist/replay/replay-store-redis.js.map +1 -1
- package/dist/replay/replay-store.js.map +1 -1
- package/dist/request/code.js.map +1 -1
- package/dist/request/request-data.js.map +1 -1
- package/dist/request/request-id.js.map +1 -1
- package/dist/request/request-manager.d.ts +18 -18
- package/dist/request/request-manager.d.ts.map +1 -1
- package/dist/request/request-manager.js.map +1 -1
- package/dist/request/request-store.js.map +1 -1
- package/dist/request/request-uri.js.map +1 -1
- package/dist/result/authorization-redirect-parameters.js.map +1 -1
- package/dist/result/authorization-result-authorize-page.js.map +1 -1
- package/dist/result/authorization-result-redirect.js.map +1 -1
- package/dist/router/assets/assets-manifest.js.map +1 -1
- package/dist/router/assets/assets.js.map +1 -1
- package/dist/router/assets/csrf.js.map +1 -1
- package/dist/router/assets/send-account-page.js.map +1 -1
- package/dist/router/assets/send-authorization-page.js.map +1 -1
- package/dist/router/assets/send-error-page.js.map +1 -1
- package/dist/router/create-account-page-middleware.js.map +1 -1
- package/dist/router/create-api-middleware.js.map +1 -1
- package/dist/router/create-authorization-page-middleware.js.map +1 -1
- package/dist/router/create-oauth-middleware.js.map +1 -1
- package/dist/router/error-handler.js.map +1 -1
- package/dist/router/middleware-options.js.map +1 -1
- package/dist/router/send-redirect.js.map +1 -1
- package/dist/signer/access-token-payload.d.ts +4113 -1362
- package/dist/signer/access-token-payload.d.ts.map +1 -1
- package/dist/signer/access-token-payload.js.map +1 -1
- package/dist/signer/api-token-payload.d.ts +3974 -1223
- package/dist/signer/api-token-payload.d.ts.map +1 -1
- package/dist/signer/api-token-payload.js.map +1 -1
- package/dist/signer/signer.d.ts +46 -26
- package/dist/signer/signer.d.ts.map +1 -1
- package/dist/signer/signer.js.map +1 -1
- package/dist/token/refresh-token.js.map +1 -1
- package/dist/token/token-claims.js.map +1 -1
- package/dist/token/token-data.js.map +1 -1
- package/dist/token/token-id.js.map +1 -1
- package/dist/token/token-manager.js.map +1 -1
- package/dist/token/token-store.js.map +1 -1
- package/dist/types/authorization-response-error.js.map +1 -1
- package/dist/types/color-hue.js.map +1 -1
- package/dist/types/email-otp.js.map +1 -1
- package/dist/types/email.js.map +1 -1
- package/dist/types/handle.js.map +1 -1
- package/dist/types/invite-code.js.map +1 -1
- package/dist/types/par-response-error.js.map +1 -1
- package/dist/types/password.js.map +1 -1
- package/dist/types/rgb-color.js.map +1 -1
- package/package.json +11 -11
- package/src/account/account-manager.ts +24 -2
- package/src/account/account-store.ts +7 -2
- package/src/client/client-manager.ts +41 -71
- package/src/client/client-utils.ts +1 -1
- package/src/metadata/build-metadata.ts +4 -4
- package/src/oauth-hooks.ts +22 -0
|
@@ -258,7 +258,18 @@ export class AccountManager {
|
|
|
258
258
|
})
|
|
259
259
|
|
|
260
260
|
return constantTime(TIMING_ATTACK_MITIGATION_DELAY, async () => {
|
|
261
|
-
await this.store.resetPasswordRequest(input)
|
|
261
|
+
const account = await this.store.resetPasswordRequest(input)
|
|
262
|
+
|
|
263
|
+
if (!account) {
|
|
264
|
+
return // Silently ignore to prevent user enumeration
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
await this.hooks.onResetPasswordRequested?.call(null, {
|
|
268
|
+
input,
|
|
269
|
+
deviceId,
|
|
270
|
+
deviceMetadata,
|
|
271
|
+
account,
|
|
272
|
+
})
|
|
262
273
|
})
|
|
263
274
|
}
|
|
264
275
|
|
|
@@ -274,7 +285,18 @@ export class AccountManager {
|
|
|
274
285
|
})
|
|
275
286
|
|
|
276
287
|
return constantTime(TIMING_ATTACK_MITIGATION_DELAY, async () => {
|
|
277
|
-
await this.store.resetPasswordConfirm(input)
|
|
288
|
+
const account = await this.store.resetPasswordConfirm(input)
|
|
289
|
+
|
|
290
|
+
if (!account) {
|
|
291
|
+
throw new InvalidRequestError('Invalid token')
|
|
292
|
+
}
|
|
293
|
+
|
|
294
|
+
await this.hooks.onResetPasswordConfirmed?.call(null, {
|
|
295
|
+
input,
|
|
296
|
+
deviceId,
|
|
297
|
+
deviceMetadata,
|
|
298
|
+
account,
|
|
299
|
+
})
|
|
278
300
|
})
|
|
279
301
|
}
|
|
280
302
|
|
|
@@ -171,8 +171,13 @@ export interface AccountStore {
|
|
|
171
171
|
filter: { sub: Sub } | { deviceId: DeviceId },
|
|
172
172
|
): Awaitable<DeviceAccount[]>
|
|
173
173
|
|
|
174
|
-
resetPasswordRequest(
|
|
175
|
-
|
|
174
|
+
resetPasswordRequest(
|
|
175
|
+
data: ResetPasswordRequestInput,
|
|
176
|
+
): Awaitable<null | Account>
|
|
177
|
+
|
|
178
|
+
resetPasswordConfirm(
|
|
179
|
+
data: ResetPasswordConfirmInput,
|
|
180
|
+
): Awaitable<null | Account>
|
|
176
181
|
|
|
177
182
|
/**
|
|
178
183
|
* @throws {HandleUnavailableError} - To indicate that the handle is already taken
|
|
@@ -5,7 +5,7 @@ import {
|
|
|
5
5
|
OAuthClientIdLoopback,
|
|
6
6
|
OAuthClientMetadata,
|
|
7
7
|
OAuthClientMetadataInput,
|
|
8
|
-
|
|
8
|
+
isLocalHostname,
|
|
9
9
|
isOAuthClientIdDiscoverable,
|
|
10
10
|
isOAuthClientIdLoopback,
|
|
11
11
|
oauthClientMetadataSchema,
|
|
@@ -17,7 +17,6 @@ import {
|
|
|
17
17
|
fetchJsonZodProcessor,
|
|
18
18
|
fetchOkProcessor,
|
|
19
19
|
} from '@atproto-labs/fetch'
|
|
20
|
-
import { isLocalHostname } from '@atproto-labs/fetch-node'
|
|
21
20
|
import { pipe } from '@atproto-labs/pipe'
|
|
22
21
|
import {
|
|
23
22
|
CachedGetter,
|
|
@@ -36,7 +35,7 @@ import { Client } from './client.js'
|
|
|
36
35
|
|
|
37
36
|
const fetchMetadataHandler = pipe(
|
|
38
37
|
fetchOkProcessor(),
|
|
39
|
-
// https://
|
|
38
|
+
// https://www.ietf.org/archive/id/draft-ietf-oauth-client-id-metadata-document-00.html#section-4.1
|
|
40
39
|
fetchJsonProcessor('application/json', true),
|
|
41
40
|
fetchJsonZodProcessor(oauthClientMetadataSchema),
|
|
42
41
|
)
|
|
@@ -176,10 +175,24 @@ export class ClientManager {
|
|
|
176
175
|
throw new InvalidClientMetadataError('Loopback clients are not allowed')
|
|
177
176
|
}
|
|
178
177
|
|
|
179
|
-
const
|
|
180
|
-
|
|
178
|
+
const metadataRaw = await callAsync(loopbackMetadata, clientId).catch(
|
|
179
|
+
(err) => {
|
|
180
|
+
throw InvalidClientMetadataError.from(
|
|
181
|
+
err,
|
|
182
|
+
`Invalid loopback client id "${clientId}"`,
|
|
183
|
+
)
|
|
184
|
+
},
|
|
181
185
|
)
|
|
182
186
|
|
|
187
|
+
const metadata = await oauthClientMetadataSchema
|
|
188
|
+
.parseAsync(metadataRaw)
|
|
189
|
+
.catch((err) => {
|
|
190
|
+
throw InvalidClientMetadataError.from(
|
|
191
|
+
err,
|
|
192
|
+
`Invalid loopback client metadata for "${clientId}"`,
|
|
193
|
+
)
|
|
194
|
+
})
|
|
195
|
+
|
|
183
196
|
return this.validateClientMetadata(clientId, metadata)
|
|
184
197
|
}
|
|
185
198
|
|
|
@@ -218,6 +231,10 @@ export class ClientManager {
|
|
|
218
231
|
clientId: ClientId,
|
|
219
232
|
metadata: OAuthClientMetadata,
|
|
220
233
|
): OAuthClientMetadata {
|
|
234
|
+
// @TODO This method should only check for rules that are specific to this
|
|
235
|
+
// implementation or the ATPROTO specification. All generic validation rules
|
|
236
|
+
// should be moved to the @atproto/oauth-types package.
|
|
237
|
+
|
|
221
238
|
if (metadata.jwks && metadata.jwks_uri) {
|
|
222
239
|
throw new InvalidClientMetadataError(
|
|
223
240
|
'jwks_uri and jwks are mutually exclusive',
|
|
@@ -590,56 +607,12 @@ export class ClientManager {
|
|
|
590
607
|
}
|
|
591
608
|
|
|
592
609
|
case isPrivateUseUriScheme(url): {
|
|
593
|
-
// https://datatracker.ietf.org/doc/html/rfc8252#section-7.1
|
|
594
|
-
//
|
|
595
|
-
// > When choosing a URI scheme to associate with the app, apps MUST
|
|
596
|
-
// > use a URI scheme based on a domain name under their control,
|
|
597
|
-
// > expressed in reverse order, as recommended by Section 3.8 of
|
|
598
|
-
// > [RFC7595] for private-use URI schemes.
|
|
599
|
-
|
|
600
610
|
if (metadata.application_type !== 'native') {
|
|
601
611
|
throw new InvalidRedirectUriError(
|
|
602
612
|
`Private-Use URI Scheme redirect URI are only allowed for native apps`,
|
|
603
613
|
)
|
|
604
614
|
}
|
|
605
615
|
|
|
606
|
-
// https://datatracker.ietf.org/doc/html/rfc8252#section-8.4
|
|
607
|
-
//
|
|
608
|
-
// > In addition to the collision-resistant properties, requiring a
|
|
609
|
-
// > URI scheme based on a domain name that is under the control of
|
|
610
|
-
// > the app can help to prove ownership in the event of a dispute
|
|
611
|
-
// > where two apps claim the same private-use URI scheme (where one
|
|
612
|
-
// > app is acting maliciously).
|
|
613
|
-
//
|
|
614
|
-
// We can't check for ownership here (as there is no concept of
|
|
615
|
-
// proven ownership in the generic client validation), but we can
|
|
616
|
-
// check that the domain is a valid domain name.
|
|
617
|
-
|
|
618
|
-
const urlDomain = reverseDomain(url.protocol.slice(0, -1))
|
|
619
|
-
|
|
620
|
-
if (isLocalHostname(urlDomain)) {
|
|
621
|
-
throw new InvalidRedirectUriError(
|
|
622
|
-
`Private-use URI Scheme redirect URI must not be a local hostname`,
|
|
623
|
-
)
|
|
624
|
-
}
|
|
625
|
-
|
|
626
|
-
// https://datatracker.ietf.org/doc/html/rfc8252#section-7.1
|
|
627
|
-
//
|
|
628
|
-
// > Following the requirements of Section 3.2 of [RFC3986], as there
|
|
629
|
-
// > is no naming authority for private-use URI scheme redirects, only
|
|
630
|
-
// > a single slash ("/") appears after the scheme component.
|
|
631
|
-
if (
|
|
632
|
-
url.href.startsWith(`${url.protocol}//`) ||
|
|
633
|
-
url.username ||
|
|
634
|
-
url.password ||
|
|
635
|
-
url.hostname ||
|
|
636
|
-
url.port
|
|
637
|
-
) {
|
|
638
|
-
throw new InvalidRedirectUriError(
|
|
639
|
-
`Private-Use URI Scheme must be in the form ${url.protocol}/<path>`,
|
|
640
|
-
)
|
|
641
|
-
}
|
|
642
|
-
|
|
643
616
|
break
|
|
644
617
|
}
|
|
645
618
|
|
|
@@ -686,22 +659,6 @@ export class ClientManager {
|
|
|
686
659
|
)
|
|
687
660
|
}
|
|
688
661
|
|
|
689
|
-
for (const redirectUri of metadata.redirect_uris) {
|
|
690
|
-
const url = parseRedirectUri(redirectUri)
|
|
691
|
-
|
|
692
|
-
if (url.protocol !== 'http:') {
|
|
693
|
-
throw new InvalidRedirectUriError(
|
|
694
|
-
`Loopback clients must use HTTP redirect URIs`,
|
|
695
|
-
)
|
|
696
|
-
}
|
|
697
|
-
|
|
698
|
-
if (!isLoopbackHost(url.hostname)) {
|
|
699
|
-
throw new InvalidRedirectUriError(
|
|
700
|
-
`Loopback clients must use loopback redirect URIs`,
|
|
701
|
-
)
|
|
702
|
-
}
|
|
703
|
-
}
|
|
704
|
-
|
|
705
662
|
return metadata
|
|
706
663
|
}
|
|
707
664
|
|
|
@@ -710,7 +667,7 @@ export class ClientManager {
|
|
|
710
667
|
metadata: OAuthClientMetadata,
|
|
711
668
|
): OAuthClientMetadata {
|
|
712
669
|
if (!metadata.client_id) {
|
|
713
|
-
// https://
|
|
670
|
+
// https://www.ietf.org/archive/id/draft-ietf-oauth-client-id-metadata-document-00.html
|
|
714
671
|
throw new InvalidClientMetadataError(
|
|
715
672
|
`client_id is required for discoverable clients`,
|
|
716
673
|
)
|
|
@@ -719,7 +676,7 @@ export class ClientManager {
|
|
|
719
676
|
const clientIdUrl = parseDiscoverableClientId(clientId)
|
|
720
677
|
|
|
721
678
|
if (metadata.client_uri) {
|
|
722
|
-
// https://
|
|
679
|
+
// https://www.ietf.org/archive/id/draft-ietf-oauth-client-id-metadata-document-00.html
|
|
723
680
|
//
|
|
724
681
|
// The client_uri must be a parent of the client_id URL. This might be
|
|
725
682
|
// relaxed in the future.
|
|
@@ -748,9 +705,19 @@ export class ClientManager {
|
|
|
748
705
|
}
|
|
749
706
|
|
|
750
707
|
for (const redirectUri of metadata.redirect_uris) {
|
|
708
|
+
// @NOTE at this point, all redirect URIs have already been validated by
|
|
709
|
+
// oauthRedirectUriSchema
|
|
710
|
+
|
|
751
711
|
const url = parseRedirectUri(redirectUri)
|
|
752
712
|
|
|
753
713
|
if (isPrivateUseUriScheme(url)) {
|
|
714
|
+
// https://datatracker.ietf.org/doc/html/rfc8252#section-7.1
|
|
715
|
+
//
|
|
716
|
+
// > When choosing a URI scheme to associate with the app, apps MUST use
|
|
717
|
+
// > a URI scheme based on a domain name under their control, expressed
|
|
718
|
+
// > in reverse order, as recommended by Section 3.8 of [RFC7595] for
|
|
719
|
+
// > private-use URI schemes.
|
|
720
|
+
|
|
754
721
|
// https://datatracker.ietf.org/doc/html/rfc8252#section-8.4
|
|
755
722
|
//
|
|
756
723
|
// > In addition to the collision-resistant properties, requiring a
|
|
@@ -759,11 +726,14 @@ export class ClientManager {
|
|
|
759
726
|
// > where two apps claim the same private-use URI scheme (where one
|
|
760
727
|
// > app is acting maliciously).
|
|
761
728
|
|
|
762
|
-
// https://
|
|
729
|
+
// https://atproto.com/specs/oauth
|
|
763
730
|
//
|
|
764
|
-
//
|
|
765
|
-
// order.
|
|
766
|
-
//
|
|
731
|
+
// > Any custom scheme must match the client_id hostname in
|
|
732
|
+
// > reverse-domain order. The URI scheme must be followed by a single
|
|
733
|
+
// > colon (:) then a single forward slash (/) and then a URI path
|
|
734
|
+
// > component. For example, an app with client_id
|
|
735
|
+
// > https://app.example.com/client-metadata.json could have a
|
|
736
|
+
// > redirect_uri of com.example.app:/callback.
|
|
767
737
|
const protocol = `${reverseDomain(clientIdUrl.hostname)}:`
|
|
768
738
|
if (url.protocol !== protocol) {
|
|
769
739
|
throw new InvalidRedirectUriError(
|
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
import {
|
|
2
2
|
OAuthClientIdDiscoverable,
|
|
3
|
+
isLocalHostname,
|
|
3
4
|
parseOAuthDiscoverableClientId,
|
|
4
5
|
} from '@atproto/oauth-types'
|
|
5
|
-
import { isLocalHostname } from '@atproto-labs/fetch-node'
|
|
6
6
|
import { InvalidClientIdError } from '../errors/invalid-client-id-error.js'
|
|
7
7
|
import { InvalidRedirectUriError } from '../errors/invalid-redirect-uri-error.js'
|
|
8
8
|
|
|
@@ -106,8 +106,8 @@ export function buildMetadata(
|
|
|
106
106
|
|
|
107
107
|
revocation_endpoint: new URL('/oauth/revoke', issuer).href,
|
|
108
108
|
|
|
109
|
-
|
|
110
|
-
|
|
109
|
+
// @TODO Should we implement these endpoints?
|
|
110
|
+
// introspection_endpoint: new URL('/oauth/introspect', issuer).href,
|
|
111
111
|
// end_session_endpoint: new URL('/oauth/logout', issuer).href,
|
|
112
112
|
|
|
113
113
|
// https://datatracker.ietf.org/doc/html/rfc9126#section-5
|
|
@@ -122,10 +122,10 @@ export function buildMetadata(
|
|
|
122
122
|
authorization_details_types_supported:
|
|
123
123
|
customMetadata?.authorization_details_types_supported,
|
|
124
124
|
|
|
125
|
-
// https://
|
|
125
|
+
// https://www.rfc-editor.org/rfc/rfc9728.html#section-4
|
|
126
126
|
protected_resources: customMetadata?.protected_resources,
|
|
127
127
|
|
|
128
|
-
// https://
|
|
128
|
+
// https://www.ietf.org/archive/id/draft-ietf-oauth-client-id-metadata-document-00.html
|
|
129
129
|
client_id_metadata_document_supported: true,
|
|
130
130
|
})
|
|
131
131
|
}
|
package/src/oauth-hooks.ts
CHANGED
|
@@ -115,6 +115,17 @@ export type OAuthHooks = {
|
|
|
115
115
|
deviceMetadata: RequestMetadata
|
|
116
116
|
}) => Awaitable<void>
|
|
117
117
|
|
|
118
|
+
/**
|
|
119
|
+
* This hook is called when a user requests a password reset, before the
|
|
120
|
+
* reset password request is triggered on the account store.
|
|
121
|
+
*/
|
|
122
|
+
onResetPasswordRequested?: (data: {
|
|
123
|
+
input: ResetPasswordRequestInput
|
|
124
|
+
deviceId: DeviceId
|
|
125
|
+
deviceMetadata: RequestMetadata
|
|
126
|
+
account: Account
|
|
127
|
+
}) => Awaitable<void>
|
|
128
|
+
|
|
118
129
|
/**
|
|
119
130
|
* This hook is called when a user confirms a password reset, before the
|
|
120
131
|
* password is actually reset on the account store.
|
|
@@ -125,6 +136,17 @@ export type OAuthHooks = {
|
|
|
125
136
|
deviceMetadata: RequestMetadata
|
|
126
137
|
}) => Awaitable<void>
|
|
127
138
|
|
|
139
|
+
/**
|
|
140
|
+
* This hook is called after a user confirms a password reset, and the
|
|
141
|
+
* password was successfully reset on the account store.
|
|
142
|
+
*/
|
|
143
|
+
onResetPasswordConfirmed?: (data: {
|
|
144
|
+
input: ResetPasswordConfirmInput
|
|
145
|
+
deviceId: DeviceId
|
|
146
|
+
deviceMetadata: RequestMetadata
|
|
147
|
+
account: Account
|
|
148
|
+
}) => Awaitable<void>
|
|
149
|
+
|
|
128
150
|
/**
|
|
129
151
|
* This hook is called when a user successfully signs up.
|
|
130
152
|
*
|