@atproto/oauth-provider 0.19.7 → 0.19.8

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.
Files changed (165) hide show
  1. package/CHANGELOG.md +26 -0
  2. package/dist/errors/error-parser.js +5 -5
  3. package/dist/errors/error-parser.js.map +1 -1
  4. package/package.json +22 -18
  5. package/src/access-token/access-token-mode.ts +0 -4
  6. package/src/account/account-manager.ts +0 -591
  7. package/src/account/account-store.ts +0 -305
  8. package/src/account/sign-in-data.ts +0 -15
  9. package/src/account/sign-up-input.ts +0 -20
  10. package/src/client/client-auth.ts +0 -64
  11. package/src/client/client-data.ts +0 -9
  12. package/src/client/client-id.ts +0 -4
  13. package/src/client/client-info.ts +0 -13
  14. package/src/client/client-manager.ts +0 -772
  15. package/src/client/client-store.ts +0 -35
  16. package/src/client/client-utils.ts +0 -37
  17. package/src/client/client.ts +0 -394
  18. package/src/constants.ts +0 -80
  19. package/src/customization/branding.ts +0 -12
  20. package/src/customization/build-customization-css.ts +0 -55
  21. package/src/customization/build-customization-data.ts +0 -24
  22. package/src/customization/colors.ts +0 -48
  23. package/src/customization/customization.ts +0 -29
  24. package/src/customization/links.ts +0 -10
  25. package/src/device/device-data.ts +0 -11
  26. package/src/device/device-id.ts +0 -27
  27. package/src/device/device-manager.ts +0 -292
  28. package/src/device/device-store.ts +0 -31
  29. package/src/device/session-id.ts +0 -21
  30. package/src/dpop/dpop-manager.ts +0 -214
  31. package/src/dpop/dpop-nonce.ts +0 -121
  32. package/src/dpop/dpop-proof.ts +0 -6
  33. package/src/errors/access-denied-error.ts +0 -12
  34. package/src/errors/account-selection-required-error.ts +0 -12
  35. package/src/errors/authorization-error.ts +0 -45
  36. package/src/errors/consent-required-error.ts +0 -12
  37. package/src/errors/error-parser.ts +0 -147
  38. package/src/errors/handle-unavailable-error.ts +0 -23
  39. package/src/errors/invalid-authorization-details-error.ts +0 -27
  40. package/src/errors/invalid-client-error.ts +0 -20
  41. package/src/errors/invalid-client-id-error.ts +0 -31
  42. package/src/errors/invalid-client-metadata-error.ts +0 -68
  43. package/src/errors/invalid-credentials-error.ts +0 -29
  44. package/src/errors/invalid-dpop-key-binding-error.ts +0 -21
  45. package/src/errors/invalid-dpop-proof-error.ts +0 -13
  46. package/src/errors/invalid-grant-error.ts +0 -21
  47. package/src/errors/invalid-invite-code-error.ts +0 -10
  48. package/src/errors/invalid-redirect-uri-error.ts +0 -17
  49. package/src/errors/invalid-request-error.ts +0 -32
  50. package/src/errors/invalid-scope-error.ts +0 -15
  51. package/src/errors/invalid-token-error.ts +0 -60
  52. package/src/errors/login-required-error.ts +0 -12
  53. package/src/errors/oauth-error.ts +0 -28
  54. package/src/errors/second-authentication-factor-required-error.ts +0 -25
  55. package/src/errors/unauthorized-client-error.ts +0 -20
  56. package/src/errors/use-dpop-nonce-error.ts +0 -32
  57. package/src/errors/www-authenticate-error.ts +0 -64
  58. package/src/index.ts +0 -16
  59. package/src/lexicon/lexicon-data.ts +0 -11
  60. package/src/lexicon/lexicon-getter.ts +0 -55
  61. package/src/lexicon/lexicon-manager.ts +0 -116
  62. package/src/lexicon/lexicon-store.ts +0 -35
  63. package/src/lib/csp/index.ts +0 -101
  64. package/src/lib/hcaptcha.ts +0 -228
  65. package/src/lib/html/README.md +0 -9
  66. package/src/lib/html/build-document.ts +0 -151
  67. package/src/lib/html/escapers.ts +0 -66
  68. package/src/lib/html/html.ts +0 -56
  69. package/src/lib/html/hydration-data.ts +0 -19
  70. package/src/lib/html/index.ts +0 -5
  71. package/src/lib/html/tags.ts +0 -67
  72. package/src/lib/html/util.ts +0 -17
  73. package/src/lib/http/README.md +0 -11
  74. package/src/lib/http/accept.ts +0 -90
  75. package/src/lib/http/context.ts +0 -42
  76. package/src/lib/http/headers.ts +0 -15
  77. package/src/lib/http/index.ts +0 -10
  78. package/src/lib/http/method.ts +0 -18
  79. package/src/lib/http/middleware.ts +0 -169
  80. package/src/lib/http/parser.ts +0 -101
  81. package/src/lib/http/path.ts +0 -82
  82. package/src/lib/http/request.ts +0 -256
  83. package/src/lib/http/response.ts +0 -122
  84. package/src/lib/http/route.ts +0 -60
  85. package/src/lib/http/router.ts +0 -117
  86. package/src/lib/http/security-headers.ts +0 -100
  87. package/src/lib/http/stream.ts +0 -57
  88. package/src/lib/http/types.ts +0 -16
  89. package/src/lib/http/url.ts +0 -23
  90. package/src/lib/nsid.ts +0 -10
  91. package/src/lib/redis.ts +0 -25
  92. package/src/lib/util/authorization-header.ts +0 -28
  93. package/src/lib/util/cast.ts +0 -18
  94. package/src/lib/util/color.ts +0 -168
  95. package/src/lib/util/crypto.ts +0 -32
  96. package/src/lib/util/date.ts +0 -7
  97. package/src/lib/util/error.ts +0 -7
  98. package/src/lib/util/function.ts +0 -39
  99. package/src/lib/util/locale.ts +0 -12
  100. package/src/lib/util/object.ts +0 -23
  101. package/src/lib/util/redirect-uri.ts +0 -46
  102. package/src/lib/util/time.ts +0 -49
  103. package/src/lib/util/type.ts +0 -182
  104. package/src/lib/util/ui8.ts +0 -14
  105. package/src/lib/util/well-known.ts +0 -8
  106. package/src/lib/util/zod-error.ts +0 -26
  107. package/src/lib/write-form-redirect.ts +0 -58
  108. package/src/lib/write-html.ts +0 -70
  109. package/src/metadata/build-metadata.ts +0 -141
  110. package/src/oauth-client.ts +0 -3
  111. package/src/oauth-dpop.ts +0 -2
  112. package/src/oauth-errors.ts +0 -26
  113. package/src/oauth-hooks.ts +0 -519
  114. package/src/oauth-middleware.ts +0 -53
  115. package/src/oauth-provider.ts +0 -1110
  116. package/src/oauth-store.ts +0 -12
  117. package/src/oauth-verifier.ts +0 -260
  118. package/src/replay/replay-manager.ts +0 -51
  119. package/src/replay/replay-store-memory.ts +0 -36
  120. package/src/replay/replay-store-redis.ts +0 -30
  121. package/src/replay/replay-store.ts +0 -44
  122. package/src/request/code.ts +0 -23
  123. package/src/request/request-data.ts +0 -36
  124. package/src/request/request-id.ts +0 -22
  125. package/src/request/request-manager.ts +0 -521
  126. package/src/request/request-store.ts +0 -60
  127. package/src/request/request-uri.ts +0 -42
  128. package/src/result/authorization-redirect-parameters.ts +0 -24
  129. package/src/result/authorization-result-authorize-page.ts +0 -16
  130. package/src/result/authorization-result-redirect.ts +0 -8
  131. package/src/router/assets/assets-manifest.ts +0 -117
  132. package/src/router/assets/assets.ts +0 -124
  133. package/src/router/assets/csrf.ts +0 -79
  134. package/src/router/assets/send-account-page.ts +0 -23
  135. package/src/router/assets/send-authorization-page.ts +0 -42
  136. package/src/router/assets/send-cookie-error-page.ts +0 -21
  137. package/src/router/assets/send-error-page.ts +0 -25
  138. package/src/router/assets/send-redirect.ts +0 -140
  139. package/src/router/create-account-page-middleware.ts +0 -88
  140. package/src/router/create-api-middleware.ts +0 -1051
  141. package/src/router/create-authorization-page-middleware.ts +0 -281
  142. package/src/router/create-oauth-middleware.ts +0 -257
  143. package/src/router/error-handler.ts +0 -6
  144. package/src/router/middleware-options.ts +0 -9
  145. package/src/signer/access-token-payload.ts +0 -25
  146. package/src/signer/api-token-payload.ts +0 -18
  147. package/src/signer/signer.ts +0 -121
  148. package/src/token/refresh-token.ts +0 -30
  149. package/src/token/token-claims.ts +0 -22
  150. package/src/token/token-data.ts +0 -40
  151. package/src/token/token-id.ts +0 -25
  152. package/src/token/token-manager.ts +0 -427
  153. package/src/token/token-store.ts +0 -88
  154. package/src/types/authorization-response-error.ts +0 -27
  155. package/src/types/color-hue.ts +0 -3
  156. package/src/types/email-otp.ts +0 -3
  157. package/src/types/email.ts +0 -26
  158. package/src/types/handle.ts +0 -23
  159. package/src/types/invite-code.ts +0 -4
  160. package/src/types/par-response-error.ts +0 -25
  161. package/src/types/password.ts +0 -4
  162. package/src/types/rgb-color.ts +0 -21
  163. package/tsconfig.build.json +0 -8
  164. package/tsconfig.build.tsbuildinfo +0 -1
  165. package/tsconfig.json +0 -4
@@ -1,121 +0,0 @@
1
- import { createHmac, randomBytes } from 'node:crypto'
2
- import { z } from 'zod'
3
- import { DPOP_NONCE_MAX_AGE } from '../constants.js'
4
-
5
- const MAX_ROTATION_INTERVAL = DPOP_NONCE_MAX_AGE / 3
6
- const MIN_ROTATION_INTERVAL = Math.min(1000, MAX_ROTATION_INTERVAL)
7
-
8
- export const rotationIntervalSchema = z
9
- .number()
10
- .int()
11
- .min(MIN_ROTATION_INTERVAL)
12
- .max(MAX_ROTATION_INTERVAL)
13
-
14
- const SECRET_BYTE_LENGTH = 32
15
-
16
- export const secretBytesSchema = z
17
- .instanceof(Uint8Array<ArrayBufferLike>)
18
- .refine((secret) => secret.length === SECRET_BYTE_LENGTH, {
19
- message: `Secret must be exactly ${SECRET_BYTE_LENGTH} bytes long`,
20
- })
21
-
22
- export const secretHexSchema = z
23
- .string()
24
- .regex(
25
- /^[0-9a-f]+$/i,
26
- `Secret must be a ${SECRET_BYTE_LENGTH * 2} chars hex string`,
27
- )
28
- .length(SECRET_BYTE_LENGTH * 2)
29
- .transform((hex): Uint8Array => Buffer.from(hex, 'hex'))
30
-
31
- export const dpopSecretSchema = z.union([secretBytesSchema, secretHexSchema])
32
- export type DpopSecret = z.input<typeof dpopSecretSchema>
33
-
34
- export class DpopNonce {
35
- readonly #rotationInterval: number
36
- readonly #secret: Uint8Array
37
-
38
- // Nonce state
39
- #counter: number
40
- #prev: string
41
- #now: string
42
- #next: string
43
-
44
- constructor(
45
- secret: DpopSecret = randomBytes(SECRET_BYTE_LENGTH),
46
- rotationInterval = MAX_ROTATION_INTERVAL,
47
- ) {
48
- this.#rotationInterval = rotationIntervalSchema.parse(rotationInterval)
49
- this.#secret = Uint8Array.from(dpopSecretSchema.parse(secret))
50
-
51
- this.#counter = this.currentCounter
52
- this.#prev = this.compute(this.#counter - 1)
53
- this.#now = this.compute(this.#counter)
54
- this.#next = this.compute(this.#counter + 1)
55
- }
56
-
57
- /**
58
- * Returns the number of full rotations since the epoch
59
- */
60
- protected get currentCounter() {
61
- return (Date.now() / this.#rotationInterval) | 0
62
- }
63
-
64
- protected rotate() {
65
- const counter = this.currentCounter
66
- switch (counter - this.#counter) {
67
- case 0:
68
- // counter === this.#counter => nothing to do
69
- return
70
- case 1:
71
- // Optimization: avoid recomputing #prev & #now
72
- this.#prev = this.#now
73
- this.#now = this.#next
74
- this.#next = this.compute(counter + 1)
75
- break
76
- case 2:
77
- // Optimization: avoid recomputing #prev
78
- this.#prev = this.#next
79
- this.#now = this.compute(counter)
80
- this.#next = this.compute(counter + 1)
81
- break
82
- default:
83
- // All nonces are outdated, so we recompute all of them
84
- this.#prev = this.compute(counter - 1)
85
- this.#now = this.compute(counter)
86
- this.#next = this.compute(counter + 1)
87
- break
88
- }
89
- this.#counter = counter
90
- }
91
-
92
- protected compute(counter: number) {
93
- return createHmac('sha256', this.#secret)
94
- .update(numTo64bits(counter))
95
- .digest()
96
- .toString('base64url')
97
- }
98
-
99
- public next() {
100
- this.rotate()
101
- return this.#next
102
- }
103
-
104
- public check(nonce: string) {
105
- return this.#next === nonce || this.#now === nonce || this.#prev === nonce
106
- }
107
- }
108
-
109
- function numTo64bits(num: number) {
110
- const arr = new Uint8Array(8)
111
- // @NOTE Assigning to an uint8 will only keep the last 8 int bits
112
- arr[7] = num |= 0
113
- arr[6] = num >>= 8
114
- arr[5] = num >>= 8
115
- arr[4] = num >>= 8
116
- arr[3] = num >>= 8
117
- arr[2] = num >>= 8
118
- arr[1] = num >>= 8
119
- arr[0] = num >>= 8
120
- return arr
121
- }
@@ -1,6 +0,0 @@
1
- export type DpopProof = Readonly<{
2
- jti: string
3
- jkt: string
4
- htm: string
5
- htu: string
6
- }>
@@ -1,12 +0,0 @@
1
- import { OAuthAuthorizationRequestParameters } from '@atproto/oauth-types'
2
- import { AuthorizationError } from './authorization-error.js'
3
-
4
- export class AccessDeniedError extends AuthorizationError {
5
- constructor(
6
- parameters: OAuthAuthorizationRequestParameters,
7
- error_description = 'Access denied',
8
- cause?: unknown,
9
- ) {
10
- super(parameters, error_description, 'access_denied', cause)
11
- }
12
- }
@@ -1,12 +0,0 @@
1
- import { OAuthAuthorizationRequestParameters } from '@atproto/oauth-types'
2
- import { AuthorizationError } from './authorization-error.js'
3
-
4
- export class AccountSelectionRequiredError extends AuthorizationError {
5
- constructor(
6
- parameters: OAuthAuthorizationRequestParameters,
7
- error_description = 'Account selection required',
8
- cause?: unknown,
9
- ) {
10
- super(parameters, error_description, 'account_selection_required', cause)
11
- }
12
- }
@@ -1,45 +0,0 @@
1
- import { OAuthAuthorizationRequestParameters } from '@atproto/oauth-types'
2
- import {
3
- AuthorizationResponseError,
4
- isAuthorizationResponseError,
5
- } from '../types/authorization-response-error.js'
6
- import { buildErrorPayload } from './error-parser.js'
7
- import { OAuthError } from './oauth-error.js'
8
-
9
- export type { AuthorizationResponseError, OAuthAuthorizationRequestParameters }
10
-
11
- export class AuthorizationError extends OAuthError {
12
- constructor(
13
- public readonly parameters: OAuthAuthorizationRequestParameters,
14
- error_description: string,
15
- error: AuthorizationResponseError = 'invalid_request',
16
- cause?: unknown,
17
- ) {
18
- super(error, error_description, 400, cause)
19
- }
20
-
21
- static from(
22
- parameters: OAuthAuthorizationRequestParameters,
23
- cause: unknown,
24
- ): AuthorizationError {
25
- if (cause instanceof AuthorizationError) return cause
26
- const payload = buildErrorPayload(cause)
27
- return new AuthorizationError(
28
- parameters,
29
- payload.error_description,
30
- isAuthorizationResponseError(payload.error)
31
- ? payload.error // Propagate "error" derived from the cause
32
- : rootCause(cause) instanceof OAuthError
33
- ? 'invalid_request'
34
- : 'server_error',
35
- cause,
36
- )
37
- }
38
- }
39
-
40
- function rootCause(err: unknown): unknown {
41
- while (err instanceof Error && err.cause != null) {
42
- err = err.cause
43
- }
44
- return err
45
- }
@@ -1,12 +0,0 @@
1
- import { OAuthAuthorizationRequestParameters } from '@atproto/oauth-types'
2
- import { AuthorizationError } from './authorization-error.js'
3
-
4
- export class ConsentRequiredError extends AuthorizationError {
5
- constructor(
6
- parameters: OAuthAuthorizationRequestParameters,
7
- error_description = 'User consent required',
8
- cause?: unknown,
9
- ) {
10
- super(parameters, error_description, 'consent_required', cause)
11
- }
12
- }
@@ -1,147 +0,0 @@
1
- import { errors } from 'jose'
2
- import { ZodError } from 'zod'
3
- import { JwtVerifyError } from '@atproto/jwk'
4
- import { formatZodError } from '../lib/util/zod-error.js'
5
- import { OAuthError } from './oauth-error.js'
6
-
7
- const { JOSEError } = errors
8
-
9
- const INVALID_REQUEST = 'invalid_request'
10
- const SERVER_ERROR = 'server_error'
11
-
12
- export function buildErrorStatus(error: unknown): number {
13
- if (error instanceof OAuthError) {
14
- return error.statusCode
15
- }
16
-
17
- if (error instanceof JwtVerifyError) {
18
- return 400
19
- }
20
-
21
- if (error instanceof ZodError) {
22
- return 400
23
- }
24
-
25
- if (error instanceof JOSEError) {
26
- return 400
27
- }
28
-
29
- if (error instanceof TypeError) {
30
- return 400
31
- }
32
-
33
- if (isBoom(error)) {
34
- return error.output.statusCode
35
- }
36
-
37
- if (isXrpcError(error)) {
38
- return error.type
39
- }
40
-
41
- const status = (error as any)?.status
42
- if (
43
- typeof status === 'number' &&
44
- status === (status | 0) &&
45
- status >= 400 &&
46
- status < 600
47
- ) {
48
- return status
49
- }
50
-
51
- return 500
52
- }
53
-
54
- export type ErrorPayload = {
55
- error: string
56
- error_description: string
57
- }
58
-
59
- export function buildErrorPayload(error: unknown): ErrorPayload {
60
- if (error instanceof OAuthError) {
61
- return error.toJSON()
62
- }
63
-
64
- if (error instanceof ZodError) {
65
- return {
66
- error: INVALID_REQUEST,
67
- error_description: formatZodError(error, 'Validation error'),
68
- }
69
- }
70
-
71
- if (error instanceof JOSEError) {
72
- return {
73
- error: INVALID_REQUEST,
74
- error_description: error.message,
75
- }
76
- }
77
-
78
- if (error instanceof TypeError) {
79
- return {
80
- error: INVALID_REQUEST,
81
- error_description: error.message,
82
- }
83
- }
84
-
85
- if (isBoom(error)) {
86
- return {
87
- error: error.output.statusCode <= 500 ? INVALID_REQUEST : SERVER_ERROR,
88
- error_description:
89
- error.output.statusCode <= 500
90
- ? isPayloadLike(error.output?.payload)
91
- ? error.output.payload.message
92
- : error.message
93
- : 'Server error',
94
- }
95
- }
96
-
97
- if (isXrpcError(error)) {
98
- return {
99
- error: error.type <= 500 ? INVALID_REQUEST : SERVER_ERROR,
100
- error_description: error.payload.message,
101
- }
102
- }
103
-
104
- const status = buildErrorStatus(error)
105
- return {
106
- error: status < 500 ? INVALID_REQUEST : SERVER_ERROR,
107
- error_description:
108
- error instanceof Error && (error as any)?.expose === true
109
- ? error.message
110
- : 'Server error',
111
- }
112
- }
113
-
114
- function isBoom(v: unknown): v is Error & {
115
- isBoom: true
116
- output: { statusCode: number; payload: unknown }
117
- } {
118
- return (
119
- v instanceof Error &&
120
- (v as any).isBoom === true &&
121
- isHttpErrorCode(v['output']?.['statusCode'])
122
- )
123
- }
124
-
125
- function isXrpcError(v: unknown): v is Error & {
126
- type: number
127
- payload: { error: string; message: string }
128
- } {
129
- return (
130
- v instanceof Error &&
131
- isHttpErrorCode(v['type']) &&
132
- isPayloadLike(v['payload'])
133
- )
134
- }
135
-
136
- function isHttpErrorCode(v: unknown): v is number {
137
- return typeof v === 'number' && v >= 400 && v < 600 && v === (v | 0)
138
- }
139
-
140
- function isPayloadLike(v: unknown): v is { error: string; message: string } {
141
- return (
142
- v != null &&
143
- typeof v === 'object' &&
144
- typeof v['error'] === 'string' &&
145
- typeof v['message'] === 'string'
146
- )
147
- }
@@ -1,23 +0,0 @@
1
- import { HandleUnavailableReason } from '@atproto/oauth-provider-api'
2
- import { OAuthError } from './oauth-error.js'
3
-
4
- // @TODO this is *not* and "OAuthError" error but rather an ApiError.
5
-
6
- export type { HandleUnavailableReason }
7
-
8
- export class HandleUnavailableError extends OAuthError {
9
- constructor(
10
- readonly reason: HandleUnavailableReason,
11
- details: string = 'That handle is not available',
12
- cause?: unknown,
13
- ) {
14
- super('handle_unavailable', details, 400, cause)
15
- }
16
-
17
- toJSON() {
18
- return {
19
- ...super.toJSON(),
20
- reason: this.reason,
21
- } as const
22
- }
23
- }
@@ -1,27 +0,0 @@
1
- import { OAuthAuthorizationRequestParameters } from '@atproto/oauth-types'
2
- import { AuthorizationError } from './authorization-error.js'
3
-
4
- /**
5
- * @see
6
- * {@link https://datatracker.ietf.org/doc/html/rfc9396#section-14.6 | RFC 9396 - OAuth Dynamic Client Registration Metadata Registration Error}
7
- *
8
- * The AS MUST refuse to process any unknown authorization details type or
9
- * authorization details not conforming to the respective type definition. The
10
- * AS MUST abort processing and respond with an error
11
- * invalid_authorization_details to the client if any of the following are true
12
- * of the objects in the authorization_details structure:
13
- * - contains an unknown authorization details type value,
14
- * - is an object of known type but containing unknown fields,
15
- * - contains fields of the wrong type for the authorization details type,
16
- * - contains fields with invalid values for the authorization details type, or
17
- * - is missing required fields for the authorization details type.
18
- */
19
- export class InvalidAuthorizationDetailsError extends AuthorizationError {
20
- constructor(
21
- parameters: OAuthAuthorizationRequestParameters,
22
- error_description: string,
23
- cause?: unknown,
24
- ) {
25
- super(parameters, error_description, 'invalid_authorization_details', cause)
26
- }
27
- }
@@ -1,20 +0,0 @@
1
- import { OAuthError } from './oauth-error.js'
2
-
3
- /**
4
- * @see
5
- * {@link https://datatracker.ietf.org/doc/html/rfc6749#section-5.2 | RFC6749 - Issuing an Access Token }
6
- *
7
- * Client authentication failed (e.g., unknown client, no client authentication
8
- * included, or unsupported authentication method). The authorization server MAY
9
- * return an HTTP 401 (Unauthorized) status code to indicate which HTTP
10
- * authentication schemes are supported. If the client attempted to
11
- * authenticate via the "Authorization" request header field, the authorization
12
- * server MUST respond with an HTTP 401 (Unauthorized) status code and include
13
- * the "WWW-Authenticate" response header field matching the authentication
14
- * scheme used by the client.
15
- */
16
- export class InvalidClientError extends OAuthError {
17
- constructor(error_description: string, cause?: unknown) {
18
- super('invalid_client', error_description, 400, cause)
19
- }
20
- }
@@ -1,31 +0,0 @@
1
- import { OAuthError } from './oauth-error.js'
2
-
3
- /**
4
- * @see {@link https://datatracker.ietf.org/doc/html/rfc7591#section-3.2.2 | RFC7591 - Client Registration Error Response}
5
- *
6
- * The value of one of the client metadata fields is invalid and the server has
7
- * rejected this request. Note that an authorization server MAY choose to
8
- * substitute a valid value for any requested parameter of a client's metadata.
9
- */
10
- export class InvalidClientIdError extends OAuthError {
11
- constructor(error_description: string, cause?: unknown) {
12
- super('invalid_client_id', error_description, 400, cause)
13
- }
14
-
15
- static from(
16
- cause: unknown,
17
- fallbackMessage = 'Invalid client identifier',
18
- ): InvalidClientIdError {
19
- if (cause instanceof InvalidClientIdError) {
20
- return cause
21
- }
22
- if (cause instanceof TypeError) {
23
- // This method is meant to be used in the context of parsing & validating
24
- // a client client metadata. In that context, a TypeError would more
25
- // likely represent a problem with the data (e.g. invalid URL constructor
26
- // arg) and not a programming error.
27
- return new InvalidClientIdError(cause.message, cause)
28
- }
29
- return new InvalidClientIdError(fallbackMessage, cause)
30
- }
31
- }
@@ -1,68 +0,0 @@
1
- import { ZodError } from 'zod'
2
- import { FetchError } from '@atproto-labs/fetch'
3
- import { OAuthError } from './oauth-error.js'
4
-
5
- /**
6
- * @see {@link https://datatracker.ietf.org/doc/html/rfc7591#section-3.2.2 | RFC7591 - Client Registration Error Response}
7
- *
8
- * The value of one of the client metadata fields is invalid and the server has
9
- * rejected this request. Note that an authorization server MAY choose to
10
- * substitute a valid value for any requested parameter of a client's metadata.
11
- */
12
- export class InvalidClientMetadataError extends OAuthError {
13
- constructor(error_description: string, cause?: unknown) {
14
- super('invalid_client_metadata', error_description, 400, cause)
15
- }
16
-
17
- static from(cause: unknown, message = 'Invalid client metadata'): OAuthError {
18
- if (cause instanceof OAuthError) {
19
- return cause
20
- }
21
-
22
- if (cause instanceof FetchError) {
23
- throw new InvalidClientMetadataError(
24
- cause.expose ? `${message}: ${cause.message}` : message,
25
- cause,
26
- )
27
- }
28
-
29
- if (cause instanceof ZodError) {
30
- const causeMessage =
31
- cause.issues
32
- .map(
33
- ({ path, message }) =>
34
- `Validation${path.length ? ` of "${path.join('.')}"` : ''} failed with error: ${message}`,
35
- )
36
- .join(' ') || cause.message
37
-
38
- throw new InvalidClientMetadataError(
39
- causeMessage ? `${message}: ${causeMessage}` : message,
40
- cause,
41
- )
42
- }
43
-
44
- if (
45
- cause instanceof Error &&
46
- 'code' in cause &&
47
- cause.code === 'DEPTH_ZERO_SELF_SIGNED_CERT'
48
- ) {
49
- throw new InvalidClientMetadataError(
50
- `${message}: Self-signed certificate`,
51
- cause,
52
- )
53
- }
54
-
55
- if (cause instanceof TypeError) {
56
- // This method is meant to be used in the context of parsing & validating
57
- // a client client metadata. In that context, a TypeError would more
58
- // likely represent a problem with the data (e.g. invalid URL constructor
59
- // arg) and not a programming error.
60
- return new InvalidClientMetadataError(
61
- `${message}: ${cause.message}`,
62
- cause,
63
- )
64
- }
65
-
66
- return new InvalidClientMetadataError(message, cause)
67
- }
68
- }
@@ -1,29 +0,0 @@
1
- import { Did } from '@atproto/did'
2
- import { InvalidRequestError } from './invalid-request-error.js'
3
-
4
- /**
5
- * Thrown by {@link AccountStore.authenticateAccount} implementations to signal
6
- * that a sign-in attempt was rejected because the provided credentials did not
7
- * match a known account.
8
- *
9
- * Stores should populate {@link did}. when the identifier resolved to an
10
- * existing account but e.g. the password or OTP was incorrect. The
11
- * identifier-unknown case should leave {@link did} unset. This information is
12
- * surfaced to the `onSignInFailed` hook and never sent back to the client, so
13
- * populating it does not affect the client-visible response.
14
- *
15
- * Only the subject identifier (DID) is carried — not a full `Account` — to
16
- * avoid embedding PII (email, name, etc.) in an error that may be serialized
17
- * by loggers or monitoring tools walking the `.cause` chain. Hook consumers
18
- * that need richer profile info can resolve it from their own account store
19
- * using {@link did}.
20
- */
21
- export class InvalidCredentialsError extends InvalidRequestError {
22
- constructor(
23
- message = 'Invalid identifier or password',
24
- public readonly did?: Did,
25
- cause?: unknown,
26
- ) {
27
- super(message, cause)
28
- }
29
- }
@@ -1,21 +0,0 @@
1
- import { WWWAuthenticateError } from './www-authenticate-error.js'
2
-
3
- /**
4
- * @see
5
- * {@link https://datatracker.ietf.org/doc/html/rfc6750#section-3.1 | RFC6750 - The WWW-Authenticate Response Header Field}
6
- *
7
- * @see
8
- * {@link https://datatracker.ietf.org/doc/html/rfc9449#name-the-dpop-authentication-sch | RFC9449 - The DPoP Authentication Scheme}
9
- */
10
- export class InvalidDpopKeyBindingError extends WWWAuthenticateError {
11
- constructor(cause?: unknown) {
12
- const error = 'invalid_token'
13
- const error_description = 'Invalid DPoP key binding'
14
- super(
15
- error,
16
- error_description,
17
- { DPoP: { error, error_description } },
18
- cause,
19
- )
20
- }
21
- }
@@ -1,13 +0,0 @@
1
- import { WWWAuthenticateError } from './www-authenticate-error.js'
2
-
3
- export class InvalidDpopProofError extends WWWAuthenticateError {
4
- constructor(error_description: string, cause?: unknown) {
5
- const error = 'invalid_dpop_proof'
6
- super(
7
- error,
8
- error_description,
9
- { DPoP: { error, error_description } },
10
- cause,
11
- )
12
- }
13
- }
@@ -1,21 +0,0 @@
1
- import { OAuthError } from './oauth-error.js'
2
-
3
- /**
4
- * @see
5
- * {@link https://datatracker.ietf.org/doc/html/rfc6749#section-5.2 | RFC6749 - Issuing an Access Token }
6
- *
7
- * The provided authorization grant (e.g., authorization code, resource owner
8
- * credentials) or refresh token is invalid, expired, revoked, does not match
9
- * the redirection URI used in the authorization request, or was issued to
10
- * another client.
11
- */
12
- export class InvalidGrantError extends OAuthError {
13
- constructor(error_description: string, cause?: unknown) {
14
- super('invalid_grant', error_description, 400, cause)
15
- }
16
-
17
- static from(err: unknown, error_description: string): InvalidGrantError {
18
- if (err instanceof InvalidGrantError) return err
19
- return new InvalidGrantError(error_description, err)
20
- }
21
- }
@@ -1,10 +0,0 @@
1
- import { InvalidRequestError } from './invalid-request-error.js'
2
-
3
- export class InvalidInviteCodeError extends InvalidRequestError {
4
- constructor(details?: string, cause?: unknown) {
5
- super(
6
- 'This invite code is invalid.' + (details ? ` ${details}` : ''),
7
- cause,
8
- )
9
- }
10
- }
@@ -1,17 +0,0 @@
1
- import { OAuthError } from './oauth-error.js'
2
-
3
- /**
4
- * @see {@link https://datatracker.ietf.org/doc/html/rfc7591#section-3.2.2 | RFC7591}
5
- *
6
- * The value of one or more redirection URIs is invalid.
7
- */
8
- export class InvalidRedirectUriError extends OAuthError {
9
- constructor(error_description: string, cause?: unknown) {
10
- super('invalid_redirect_uri', error_description, 400, cause)
11
- }
12
-
13
- static from(cause?: unknown): InvalidRedirectUriError {
14
- if (cause instanceof InvalidRedirectUriError) return cause
15
- return new InvalidRedirectUriError('Invalid redirect URI', cause)
16
- }
17
- }