@atproto/oauth-provider 0.9.2 → 0.10.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/CHANGELOG.md +38 -0
- package/dist/client/client-manager.d.ts.map +1 -1
- package/dist/client/client-manager.js +0 -7
- package/dist/client/client-manager.js.map +1 -1
- package/dist/client/client.js +6 -6
- package/dist/client/client.js.map +1 -1
- package/dist/device/device-manager.js +1 -1
- package/dist/device/device-manager.js.map +1 -1
- package/dist/dpop/dpop-manager.js +15 -15
- package/dist/dpop/dpop-manager.js.map +1 -1
- package/dist/errors/access-denied-error.d.ts +4 -7
- package/dist/errors/access-denied-error.d.ts.map +1 -1
- package/dist/errors/access-denied-error.js +4 -13
- package/dist/errors/access-denied-error.js.map +1 -1
- package/dist/errors/account-selection-required-error.d.ts +2 -2
- package/dist/errors/account-selection-required-error.d.ts.map +1 -1
- package/dist/errors/account-selection-required-error.js +2 -2
- package/dist/errors/account-selection-required-error.js.map +1 -1
- package/dist/errors/authorization-error.d.ts +10 -0
- package/dist/errors/authorization-error.d.ts.map +1 -0
- package/dist/errors/authorization-error.js +31 -0
- package/dist/errors/authorization-error.js.map +1 -0
- package/dist/errors/consent-required-error.d.ts +2 -2
- package/dist/errors/consent-required-error.d.ts.map +1 -1
- package/dist/errors/consent-required-error.js +2 -2
- package/dist/errors/consent-required-error.js.map +1 -1
- package/dist/errors/error-parser.d.ts.map +1 -1
- package/dist/errors/error-parser.js +2 -1
- package/dist/errors/error-parser.js.map +1 -1
- package/dist/errors/invalid-authorization-details-error.d.ts +2 -2
- package/dist/errors/invalid-authorization-details-error.d.ts.map +1 -1
- package/dist/errors/invalid-authorization-details-error.js +2 -2
- package/dist/errors/invalid-authorization-details-error.js.map +1 -1
- package/dist/errors/invalid-scope-error.d.ts +2 -2
- package/dist/errors/invalid-scope-error.d.ts.map +1 -1
- package/dist/errors/invalid-scope-error.js +2 -2
- package/dist/errors/invalid-scope-error.js.map +1 -1
- package/dist/errors/login-required-error.d.ts +2 -3
- package/dist/errors/login-required-error.d.ts.map +1 -1
- package/dist/errors/login-required-error.js +2 -7
- package/dist/errors/login-required-error.js.map +1 -1
- package/dist/lib/http/response.d.ts +4 -4
- package/dist/lib/http/response.d.ts.map +1 -1
- package/dist/lib/http/response.js +8 -7
- package/dist/lib/http/response.js.map +1 -1
- package/dist/lib/http/stream.d.ts +1 -0
- package/dist/lib/http/stream.d.ts.map +1 -1
- package/dist/lib/http/stream.js +6 -0
- package/dist/lib/http/stream.js.map +1 -1
- package/dist/lib/util/error.d.ts +2 -0
- package/dist/lib/util/error.d.ts.map +1 -0
- package/dist/lib/util/error.js +11 -0
- package/dist/lib/util/error.js.map +1 -0
- package/dist/lib/util/zod-error.d.ts +3 -1
- package/dist/lib/util/zod-error.d.ts.map +1 -1
- package/dist/lib/util/zod-error.js +20 -10
- package/dist/lib/util/zod-error.js.map +1 -1
- package/dist/metadata/build-metadata.d.ts +0 -1
- package/dist/metadata/build-metadata.d.ts.map +1 -1
- package/dist/metadata/build-metadata.js +6 -2
- package/dist/metadata/build-metadata.js.map +1 -1
- package/dist/oauth-errors.d.ts +1 -1
- package/dist/oauth-errors.d.ts.map +1 -1
- package/dist/oauth-errors.js +1 -1
- package/dist/oauth-errors.js.map +1 -1
- package/dist/oauth-hooks.d.ts +17 -3
- package/dist/oauth-hooks.d.ts.map +1 -1
- package/dist/oauth-hooks.js +7 -4
- package/dist/oauth-hooks.js.map +1 -1
- package/dist/oauth-provider.d.ts +1 -0
- package/dist/oauth-provider.d.ts.map +1 -1
- package/dist/oauth-provider.js +35 -49
- package/dist/oauth-provider.js.map +1 -1
- package/dist/oauth-verifier.d.ts +2 -1
- package/dist/oauth-verifier.d.ts.map +1 -1
- package/dist/oauth-verifier.js.map +1 -1
- package/dist/request/request-manager.d.ts +5 -5
- package/dist/request/request-manager.d.ts.map +1 -1
- package/dist/request/request-manager.js +63 -45
- package/dist/request/request-manager.js.map +1 -1
- package/dist/request/request-store.d.ts +6 -6
- package/dist/request/request-store.d.ts.map +1 -1
- package/dist/result/authorization-result-authorize-page.d.ts +2 -3
- package/dist/result/authorization-result-authorize-page.d.ts.map +1 -1
- package/dist/router/assets/send-authorization-page.js +3 -2
- package/dist/router/assets/send-authorization-page.js.map +1 -1
- package/dist/router/create-api-middleware.d.ts.map +1 -1
- package/dist/router/create-api-middleware.js +68 -48
- package/dist/router/create-api-middleware.js.map +1 -1
- package/dist/router/create-authorization-page-middleware.d.ts.map +1 -1
- package/dist/router/create-authorization-page-middleware.js +19 -17
- package/dist/router/create-authorization-page-middleware.js.map +1 -1
- package/dist/router/create-oauth-middleware.d.ts.map +1 -1
- package/dist/router/create-oauth-middleware.js +21 -18
- package/dist/router/create-oauth-middleware.js.map +1 -1
- package/dist/router/send-redirect.js +2 -2
- package/dist/router/send-redirect.js.map +1 -1
- package/dist/token/token-manager.js +1 -1
- package/dist/token/verify-token-claims.d.ts +1 -0
- package/dist/token/verify-token-claims.d.ts.map +1 -1
- package/dist/token/verify-token-claims.js.map +1 -1
- package/dist/types/authorization-response-error.d.ts +5 -0
- package/dist/types/authorization-response-error.d.ts.map +1 -0
- package/dist/types/authorization-response-error.js +21 -0
- package/dist/types/authorization-response-error.js.map +1 -0
- package/dist/types/par-response-error.d.ts +5 -0
- package/dist/types/par-response-error.d.ts.map +1 -0
- package/dist/types/par-response-error.js +22 -0
- package/dist/types/par-response-error.js.map +1 -0
- package/package.json +7 -6
- package/src/client/client-manager.ts +0 -8
- package/src/client/client.ts +6 -6
- package/src/device/device-manager.ts +1 -1
- package/src/dpop/dpop-manager.ts +16 -16
- package/src/errors/access-denied-error.ts +6 -33
- package/src/errors/account-selection-required-error.ts +2 -2
- package/src/errors/authorization-error.ts +45 -0
- package/src/errors/consent-required-error.ts +2 -2
- package/src/errors/error-parser.ts +2 -1
- package/src/errors/invalid-authorization-details-error.ts +2 -2
- package/src/errors/invalid-scope-error.ts +2 -2
- package/src/errors/login-required-error.ts +2 -12
- package/src/lib/http/response.ts +14 -13
- package/src/lib/http/stream.ts +6 -0
- package/src/lib/util/error.ts +7 -0
- package/src/lib/util/zod-error.ts +23 -11
- package/src/metadata/build-metadata.ts +8 -3
- package/src/oauth-errors.ts +1 -1
- package/src/oauth-hooks.ts +18 -2
- package/src/oauth-provider.ts +37 -58
- package/src/oauth-verifier.ts +3 -1
- package/src/request/request-manager.ts +76 -55
- package/src/request/request-store.ts +6 -6
- package/src/result/authorization-result-authorize-page.ts +2 -3
- package/src/router/assets/send-authorization-page.ts +3 -3
- package/src/router/create-api-middleware.ts +92 -64
- package/src/router/create-authorization-page-middleware.ts +19 -21
- package/src/router/create-oauth-middleware.ts +28 -27
- package/src/router/send-redirect.ts +2 -2
- package/src/token/token-manager.ts +1 -1
- package/src/token/verify-token-claims.ts +8 -0
- package/src/types/authorization-response-error.ts +27 -0
- package/src/types/par-response-error.ts +25 -0
- package/tsconfig.build.tsbuildinfo +1 -1
- package/dist/errors/invalid-parameters-error.d.ts +0 -6
- package/dist/errors/invalid-parameters-error.d.ts.map +0 -1
- package/dist/errors/invalid-parameters-error.js +0 -11
- package/dist/errors/invalid-parameters-error.js.map +0 -1
- package/dist/request/request-info.d.ts +0 -14
- package/dist/request/request-info.d.ts.map +0 -1
- package/dist/request/request-info.js +0 -3
- package/dist/request/request-info.js.map +0 -1
- package/src/errors/invalid-parameters-error.ts +0 -12
- package/src/request/request-info.ts +0 -14
@@ -1,5 +1,6 @@
|
|
1
1
|
import { isAtprotoDid } from '@atproto/did'
|
2
2
|
import type { Account } from '@atproto/oauth-provider-api'
|
3
|
+
import { isValidAtprotoOauthScope } from '@atproto/oauth-scopes'
|
3
4
|
import {
|
4
5
|
OAuthAuthorizationRequestParameters,
|
5
6
|
OAuthAuthorizationServerMetadata,
|
@@ -16,10 +17,10 @@ import {
|
|
16
17
|
} from '../constants.js'
|
17
18
|
import { DeviceId } from '../device/device-id.js'
|
18
19
|
import { AccessDeniedError } from '../errors/access-denied-error.js'
|
20
|
+
import { AuthorizationError } from '../errors/authorization-error.js'
|
19
21
|
import { ConsentRequiredError } from '../errors/consent-required-error.js'
|
20
22
|
import { InvalidAuthorizationDetailsError } from '../errors/invalid-authorization-details-error.js'
|
21
23
|
import { InvalidGrantError } from '../errors/invalid-grant-error.js'
|
22
|
-
import { InvalidParametersError } from '../errors/invalid-parameters-error.js'
|
23
24
|
import { InvalidRequestError } from '../errors/invalid-request-error.js'
|
24
25
|
import { InvalidScopeError } from '../errors/invalid-scope-error.js'
|
25
26
|
import { RequestMetadata } from '../lib/http/request.js'
|
@@ -60,10 +61,16 @@ export class RequestManager {
|
|
60
61
|
) {
|
61
62
|
const parameters = await this.validate(client, clientAuth, input)
|
62
63
|
|
64
|
+
await callAsync(this.hooks.onAuthorizationRequest, {
|
65
|
+
client,
|
66
|
+
clientAuth,
|
67
|
+
parameters,
|
68
|
+
})
|
69
|
+
|
63
70
|
const expiresAt = new Date(Date.now() + PAR_EXPIRES_IN)
|
64
|
-
const
|
71
|
+
const requestId = await generateRequestId()
|
65
72
|
|
66
|
-
await this.store.createRequest(
|
73
|
+
await this.store.createRequest(requestId, {
|
67
74
|
clientId: client.id,
|
68
75
|
clientAuth,
|
69
76
|
parameters,
|
@@ -73,8 +80,8 @@ export class RequestManager {
|
|
73
80
|
code: null,
|
74
81
|
})
|
75
82
|
|
76
|
-
const
|
77
|
-
return {
|
83
|
+
const requestUri = encodeRequestUri(requestId)
|
84
|
+
return { requestUri, expiresAt, parameters }
|
78
85
|
}
|
79
86
|
|
80
87
|
protected async validate(
|
@@ -93,10 +100,7 @@ export class RequestManager {
|
|
93
100
|
'nonce', // note that OIDC "nonce" is redundant with PKCE
|
94
101
|
] as const) {
|
95
102
|
if (parameters[k] !== undefined) {
|
96
|
-
throw new
|
97
|
-
parameters,
|
98
|
-
`Unsupported "${k}" parameter`,
|
99
|
-
)
|
103
|
+
throw new AuthorizationError(parameters, `Unsupported "${k}" parameter`)
|
100
104
|
}
|
101
105
|
}
|
102
106
|
|
@@ -109,7 +113,7 @@ export class RequestManager {
|
|
109
113
|
parameters.response_type,
|
110
114
|
)
|
111
115
|
) {
|
112
|
-
throw new
|
116
|
+
throw new AuthorizationError(
|
113
117
|
parameters,
|
114
118
|
`Unsupported response_type "${parameters.response_type}"`,
|
115
119
|
'unsupported_response_type',
|
@@ -120,27 +124,13 @@ export class RequestManager {
|
|
120
124
|
parameters.response_type === 'code' &&
|
121
125
|
!this.metadata.grant_types_supported?.includes('authorization_code')
|
122
126
|
) {
|
123
|
-
throw new
|
127
|
+
throw new AuthorizationError(
|
124
128
|
parameters,
|
125
129
|
`Unsupported grant_type "authorization_code"`,
|
126
130
|
'invalid_request',
|
127
131
|
)
|
128
132
|
}
|
129
133
|
|
130
|
-
if (parameters.scope) {
|
131
|
-
for (const scope of parameters.scope.split(' ')) {
|
132
|
-
// Currently, the implementation requires all the scopes to be statically
|
133
|
-
// defined in the server metadata. In the future, we might add support
|
134
|
-
// for dynamic scopes.
|
135
|
-
if (!this.metadata.scopes_supported?.includes(scope)) {
|
136
|
-
throw new InvalidParametersError(
|
137
|
-
parameters,
|
138
|
-
`Scope "${scope}" is not supported by this server`,
|
139
|
-
)
|
140
|
-
}
|
141
|
-
}
|
142
|
-
}
|
143
|
-
|
144
134
|
if (parameters.authorization_details) {
|
145
135
|
for (const detail of parameters.authorization_details) {
|
146
136
|
if (
|
@@ -169,7 +159,7 @@ export class RequestManager {
|
|
169
159
|
if (!parameters.redirect_uri) {
|
170
160
|
// Should already be ensured by client.validateRequest(). Adding here for
|
171
161
|
// clarity & extra safety.
|
172
|
-
throw new
|
162
|
+
throw new AuthorizationError(parameters, 'Missing "redirect_uri"')
|
173
163
|
}
|
174
164
|
|
175
165
|
// https://datatracker.ietf.org/doc/html/draft-ietf-oauth-v2-1-10#section-1.4.1
|
@@ -180,8 +170,16 @@ export class RequestManager {
|
|
180
170
|
// > server MUST include the scope response parameter in the token response
|
181
171
|
// > (Section 3.2.3) to inform the client of the actual scope granted.
|
182
172
|
|
183
|
-
// Let's make sure the scopes are unique (to reduce the token & storage
|
184
|
-
|
173
|
+
// Let's make sure the scopes are unique (to reduce the token & storage
|
174
|
+
// size) & are indeed supported.
|
175
|
+
|
176
|
+
// @NOTE An app requesting a not yet supported list of scopes will need to
|
177
|
+
// re-authenticate the user once the scopes are supported. This is due to
|
178
|
+
// the fact that the AS does not know how to properly display those scopes
|
179
|
+
// to the user, so it cannot properly ask for consent.
|
180
|
+
const scopes = new Set(
|
181
|
+
parameters.scope?.split(' ')?.filter(isValidAtprotoOauthScope),
|
182
|
+
)
|
185
183
|
|
186
184
|
parameters = { ...parameters, scope: [...scopes].join(' ') || undefined }
|
187
185
|
|
@@ -195,7 +193,7 @@ export class RequestManager {
|
|
195
193
|
case 'S256':
|
196
194
|
break
|
197
195
|
default: {
|
198
|
-
throw new
|
196
|
+
throw new AuthorizationError(
|
199
197
|
parameters,
|
200
198
|
`Unsupported code_challenge_method "${parameters.code_challenge_method}"`,
|
201
199
|
)
|
@@ -204,7 +202,7 @@ export class RequestManager {
|
|
204
202
|
} else {
|
205
203
|
if (parameters.code_challenge_method) {
|
206
204
|
// https://datatracker.ietf.org/doc/html/rfc7636#section-4.4.1
|
207
|
-
throw new
|
205
|
+
throw new AuthorizationError(
|
208
206
|
parameters,
|
209
207
|
'code_challenge is required when code_challenge_method is provided',
|
210
208
|
)
|
@@ -225,7 +223,7 @@ export class RequestManager {
|
|
225
223
|
// atproto does not implement the OpenID Connect nonce mechanism, so we
|
226
224
|
// require the use of PKCE for all clients.
|
227
225
|
|
228
|
-
throw new
|
226
|
+
throw new AuthorizationError(parameters, 'Use of PKCE is required')
|
229
227
|
}
|
230
228
|
|
231
229
|
// -----------------
|
@@ -233,7 +231,7 @@ export class RequestManager {
|
|
233
231
|
// -----------------
|
234
232
|
|
235
233
|
if (parameters.response_type !== 'code') {
|
236
|
-
throw new
|
234
|
+
throw new AuthorizationError(
|
237
235
|
parameters,
|
238
236
|
'atproto only supports the "code" response_type',
|
239
237
|
)
|
@@ -249,7 +247,7 @@ export class RequestManager {
|
|
249
247
|
}
|
250
248
|
|
251
249
|
if (parameters.code_challenge_method !== 'S256') {
|
252
|
-
throw new
|
250
|
+
throw new AuthorizationError(
|
253
251
|
parameters,
|
254
252
|
'atproto requires use of "S256" code_challenge_method',
|
255
253
|
)
|
@@ -280,10 +278,7 @@ export class RequestManager {
|
|
280
278
|
const hint = parameters.login_hint?.toLowerCase()
|
281
279
|
if (hint) {
|
282
280
|
if (!isAtprotoDid(hint) && !isValidHandle(hint)) {
|
283
|
-
throw new
|
284
|
-
parameters,
|
285
|
-
`Invalid login_hint "${hint}"`,
|
286
|
-
)
|
281
|
+
throw new AuthorizationError(parameters, `Invalid login_hint "${hint}"`)
|
287
282
|
}
|
288
283
|
|
289
284
|
// @TODO: ensure that the account actually exists on this server (there is
|
@@ -296,10 +291,10 @@ export class RequestManager {
|
|
296
291
|
return parameters
|
297
292
|
}
|
298
293
|
|
299
|
-
async get(
|
300
|
-
const
|
294
|
+
async get(requestUri: RequestUri, deviceId: DeviceId, clientId?: ClientId) {
|
295
|
+
const requestId = decodeRequestUri(requestUri)
|
301
296
|
|
302
|
-
const data = await this.store.readRequest(
|
297
|
+
const data = await this.store.readRequest(requestId)
|
303
298
|
if (!data) throw new InvalidRequestError('Unknown request_uri')
|
304
299
|
|
305
300
|
const updates: UpdateRequestData = {}
|
@@ -338,16 +333,16 @@ export class RequestManager {
|
|
338
333
|
)
|
339
334
|
}
|
340
335
|
} catch (err) {
|
341
|
-
await this.store.deleteRequest(
|
336
|
+
await this.store.deleteRequest(requestId)
|
342
337
|
throw err
|
343
338
|
}
|
344
339
|
|
345
340
|
if (Object.keys(updates).length > 0) {
|
346
|
-
await this.store.updateRequest(
|
341
|
+
await this.store.updateRequest(requestId, updates)
|
347
342
|
}
|
348
343
|
|
349
344
|
return {
|
350
|
-
|
345
|
+
requestUri,
|
351
346
|
expiresAt: updates.expiresAt || data.expiresAt,
|
352
347
|
parameters: data.parameters,
|
353
348
|
clientId: data.clientId,
|
@@ -355,40 +350,65 @@ export class RequestManager {
|
|
355
350
|
}
|
356
351
|
|
357
352
|
async setAuthorized(
|
358
|
-
|
353
|
+
requestUri: RequestUri,
|
359
354
|
client: Client,
|
360
355
|
account: Account,
|
361
356
|
deviceId: DeviceId,
|
362
357
|
deviceMetadata: RequestMetadata,
|
358
|
+
scopeOverride?: string,
|
363
359
|
): Promise<Code> {
|
364
|
-
const requestId = decodeRequestUri(
|
360
|
+
const requestId = decodeRequestUri(requestUri)
|
365
361
|
|
366
362
|
const data = await this.store.readRequest(requestId)
|
367
363
|
if (!data) throw new InvalidRequestError('Unknown request_uri')
|
368
364
|
|
365
|
+
let { parameters } = data
|
366
|
+
|
369
367
|
try {
|
370
368
|
if (data.expiresAt < new Date()) {
|
371
|
-
throw new AccessDeniedError(
|
369
|
+
throw new AccessDeniedError(parameters, 'This request has expired')
|
372
370
|
}
|
373
371
|
if (!data.deviceId) {
|
374
372
|
throw new AccessDeniedError(
|
375
|
-
|
373
|
+
parameters,
|
376
374
|
'This request was not initiated',
|
377
375
|
)
|
378
376
|
}
|
379
377
|
if (data.deviceId !== deviceId) {
|
380
378
|
throw new AccessDeniedError(
|
381
|
-
|
379
|
+
parameters,
|
382
380
|
'This request was initiated from another device',
|
383
381
|
)
|
384
382
|
}
|
385
383
|
if (data.sub || data.code) {
|
386
384
|
throw new AccessDeniedError(
|
387
|
-
|
385
|
+
parameters,
|
388
386
|
'This request was already authorized',
|
389
387
|
)
|
390
388
|
}
|
391
389
|
|
390
|
+
// If a new scope value is provided, update the parameters by ensuring
|
391
|
+
// that every existing scope in the parameters is also present in the
|
392
|
+
// override value. This allows the user to remove scopes from the request,
|
393
|
+
// but not to add new ones.
|
394
|
+
if (scopeOverride != null) {
|
395
|
+
const allowedScopes = new Set(scopeOverride.split(' '))
|
396
|
+
const existingScopes = parameters.scope?.split(' ')
|
397
|
+
|
398
|
+
// Compute the intersection of the existing scopes and the overrides.
|
399
|
+
const newScopes = existingScopes?.filter((s) => allowedScopes.has(s))
|
400
|
+
|
401
|
+
// Validate: make sure the new scopes are valid
|
402
|
+
if (!newScopes?.includes('atproto')) {
|
403
|
+
throw new AccessDeniedError(
|
404
|
+
parameters,
|
405
|
+
'The "atproto" scope is required',
|
406
|
+
)
|
407
|
+
}
|
408
|
+
|
409
|
+
parameters = { ...parameters, scope: newScopes.join(' ') }
|
410
|
+
}
|
411
|
+
|
392
412
|
// Only response_type=code is supported
|
393
413
|
const code = await generateCode()
|
394
414
|
|
@@ -398,12 +418,13 @@ export class RequestManager {
|
|
398
418
|
code,
|
399
419
|
// Allow the client to exchange the code for a token within the next 60 seconds.
|
400
420
|
expiresAt: new Date(Date.now() + AUTHORIZATION_INACTIVITY_TIMEOUT),
|
421
|
+
parameters,
|
401
422
|
})
|
402
423
|
|
403
424
|
await callAsync(this.hooks.onAuthorized, {
|
404
425
|
client,
|
405
426
|
account,
|
406
|
-
parameters
|
427
|
+
parameters,
|
407
428
|
deviceId,
|
408
429
|
deviceMetadata,
|
409
430
|
requestId,
|
@@ -424,12 +445,12 @@ export class RequestManager {
|
|
424
445
|
const result = await this.store.consumeRequestCode(code)
|
425
446
|
if (!result) throw new InvalidGrantError('Invalid code')
|
426
447
|
|
427
|
-
const {
|
448
|
+
const { requestId, data } = result
|
428
449
|
|
429
450
|
// Fool-proofing the store implementation against code replay attacks (in
|
430
451
|
// case consumeRequestCode() does not delete the request).
|
431
452
|
if (NODE_ENV !== 'production') {
|
432
|
-
const result = await this.store.readRequest(
|
453
|
+
const result = await this.store.readRequest(requestId)
|
433
454
|
if (result) {
|
434
455
|
throw new Error('Invalid store implementation: request not deleted')
|
435
456
|
}
|
@@ -447,8 +468,8 @@ export class RequestManager {
|
|
447
468
|
return data
|
448
469
|
}
|
449
470
|
|
450
|
-
async delete(
|
451
|
-
const
|
452
|
-
await this.store.deleteRequest(
|
471
|
+
async delete(requestUri: RequestUri): Promise<void> {
|
472
|
+
const requestId = decodeRequestUri(requestUri)
|
473
|
+
await this.store.deleteRequest(requestId)
|
453
474
|
}
|
454
475
|
}
|
@@ -12,25 +12,25 @@ export type { Awaitable }
|
|
12
12
|
|
13
13
|
export type UpdateRequestData = Pick<
|
14
14
|
Partial<RequestData>,
|
15
|
-
'sub' | 'code' | 'deviceId' | 'expiresAt'
|
15
|
+
'sub' | 'code' | 'deviceId' | 'expiresAt' | 'parameters'
|
16
16
|
>
|
17
17
|
|
18
18
|
export type FoundRequestResult = {
|
19
|
-
|
19
|
+
requestId: RequestId
|
20
20
|
data: RequestData
|
21
21
|
}
|
22
22
|
|
23
23
|
export { InvalidGrantError }
|
24
24
|
|
25
25
|
export interface RequestStore {
|
26
|
-
createRequest(
|
26
|
+
createRequest(requestId: RequestId, data: RequestData): Awaitable<void>
|
27
27
|
/**
|
28
28
|
* Note that expired requests **can** be returned to yield a different error
|
29
29
|
* message than if the request was not found.
|
30
30
|
*/
|
31
|
-
readRequest(
|
32
|
-
updateRequest(
|
33
|
-
deleteRequest(
|
31
|
+
readRequest(requestId: RequestId): Awaitable<RequestData | null>
|
32
|
+
updateRequest(requestId: RequestId, data: UpdateRequestData): Awaitable<void>
|
33
|
+
deleteRequest(requestId: RequestId): void | Awaitable<void>
|
34
34
|
/**
|
35
35
|
* @note it is **IMPORTANT** that this method prevents concurrent retrieval of
|
36
36
|
* the same code. If two requests are made with the same code, only one of
|
@@ -1,4 +1,4 @@
|
|
1
|
-
import type {
|
1
|
+
import type { Session } from '@atproto/oauth-provider-api'
|
2
2
|
import { OAuthAuthorizationRequestParameters } from '@atproto/oauth-types'
|
3
3
|
import { Client } from '../client/client.js'
|
4
4
|
import { RequestUri } from '../request/request-uri.js'
|
@@ -8,7 +8,6 @@ export type AuthorizationResultAuthorizePage = {
|
|
8
8
|
client: Client
|
9
9
|
parameters: OAuthAuthorizationRequestParameters
|
10
10
|
|
11
|
-
|
12
|
-
scopeDetails?: ScopeDetail[]
|
11
|
+
requestUri: RequestUri
|
13
12
|
sessions: readonly Session[]
|
14
13
|
}
|
@@ -36,14 +36,14 @@ export function sendAuthorizePageFactory(customization: Customization) {
|
|
36
36
|
const script = declareHydrationData<HydrationData['authorization-page']>({
|
37
37
|
__customizationData: customizationData,
|
38
38
|
__authorizeData: {
|
39
|
-
requestUri: data.
|
39
|
+
requestUri: data.requestUri,
|
40
40
|
|
41
41
|
clientId: data.client.id,
|
42
42
|
clientMetadata: data.client.metadata,
|
43
43
|
clientTrusted: data.client.info.isTrusted,
|
44
|
+
clientFirstParty: data.client.info.isFirstParty,
|
44
45
|
|
45
|
-
|
46
|
-
|
46
|
+
scope: data.parameters.scope,
|
47
47
|
uiLocales: data.parameters.ui_locales,
|
48
48
|
loginHint: data.parameters.login_hint,
|
49
49
|
},
|