@hatk/hatk 0.0.1-alpha.46 → 0.0.1-alpha.48
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/oauth/server.d.ts +22 -1
- package/dist/oauth/server.d.ts.map +1 -1
- package/dist/oauth/server.js +98 -27
- package/dist/server.d.ts.map +1 -1
- package/dist/server.js +5 -3
- package/package.json +1 -1
package/dist/oauth/server.d.ts
CHANGED
|
@@ -59,12 +59,33 @@ export declare function getClientMetadata(issuer: string, config: OAuthConfig):
|
|
|
59
59
|
dpop_bound_access_tokens: boolean;
|
|
60
60
|
scope: string;
|
|
61
61
|
};
|
|
62
|
+
/**
|
|
63
|
+
* Handle a Pushed Authorization Request (PAR).
|
|
64
|
+
*
|
|
65
|
+
* Supports account creation via `prompt=create`. When set, `login_hint`
|
|
66
|
+
* is treated as a PDS hostname (e.g. "selfhosted.social" or "localhost:2583")
|
|
67
|
+
* rather than a handle or DID. The auth server is discovered from the PDS's
|
|
68
|
+
* protected resource metadata, and `prompt=create` is forwarded to the PDS
|
|
69
|
+
* PAR so it shows the signup page.
|
|
70
|
+
*
|
|
71
|
+
* For normal login, `login_hint` is a handle or DID as usual.
|
|
72
|
+
*/
|
|
62
73
|
export declare function handlePar(config: OAuthConfig, body: Record<string, string>, dpopHeader: string, requestUrl: string): Promise<{
|
|
63
74
|
request_uri: string;
|
|
64
75
|
expires_in: number;
|
|
65
76
|
}>;
|
|
66
77
|
export declare function buildAuthorizeRedirect(config: OAuthConfig, request: any): string;
|
|
67
|
-
|
|
78
|
+
/**
|
|
79
|
+
* Initiate a server-side OAuth login or account creation flow.
|
|
80
|
+
*
|
|
81
|
+
* For account creation, pass `{ prompt: 'create', pds: 'selfhosted.social' }`.
|
|
82
|
+
* The `pds` is a bare hostname; the auth server is discovered from its
|
|
83
|
+
* protected resource metadata.
|
|
84
|
+
*/
|
|
85
|
+
export declare function serverLogin(config: OAuthConfig, handle: string, options?: {
|
|
86
|
+
prompt?: string;
|
|
87
|
+
pds?: string;
|
|
88
|
+
}): Promise<string>;
|
|
68
89
|
export declare function handleCallback(config: OAuthConfig, code: string, state: string | null, iss: string | null): Promise<{
|
|
69
90
|
requestUri: string;
|
|
70
91
|
clientRedirectUri: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/oauth/server.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AA4E/C,wBAAsB,SAAS,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBrG;AAID,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW;;;;;;;;;;;;;;;;;;;EAqBxE;AAED,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW;;;;;EAO/E;AAED,wBAAgB,OAAO;;;;;;;;;;;;;;;;;;;;;;EAWtB;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW;;;;;;;;;EAcpE;AAID,wBAAsB,SAAS,CAC7B,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../../src/oauth/server.ts"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,cAAc,CAAA;AA4E/C,wBAAsB,SAAS,CAAC,OAAO,EAAE,WAAW,EAAE,MAAM,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAsBrG;AAID,wBAAgB,qBAAqB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW;;;;;;;;;;;;;;;;;;;EAqBxE;AAED,wBAAgB,4BAA4B,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW;;;;;EAO/E;AAED,wBAAgB,OAAO;;;;;;;;;;;;;;;;;;;;;;EAWtB;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,WAAW;;;;;;;;;EAcpE;AAID;;;;;;;;;;GAUG;AACH,wBAAsB,SAAS,CAC7B,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,UAAU,EAAE,MAAM,CAAA;CAAE,CAAC,CAwKtD;AAID,wBAAgB,sBAAsB,CAAC,MAAM,EAAE,WAAW,EAAE,OAAO,EAAE,GAAG,GAAG,MAAM,CAShF;AAID;;;;;;GAMG;AACH,wBAAsB,WAAW,CAC/B,MAAM,EAAE,WAAW,EACnB,MAAM,EAAE,MAAM,EACd,OAAO,CAAC,EAAE;IAAE,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,GAAG,CAAC,EAAE,MAAM,CAAA;CAAE,GAC1C,OAAO,CAAC,MAAM,CAAC,CA6HjB;AAID,wBAAsB,cAAc,CAClC,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,MAAM,EACZ,KAAK,EAAE,MAAM,GAAG,IAAI,EACpB,GAAG,EAAE,MAAM,GAAG,IAAI,GACjB,OAAO,CAAC;IAAE,UAAU,EAAE,MAAM,CAAC;IAAC,iBAAiB,EAAE,MAAM,CAAC;IAAC,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAAC,GAAG,EAAE,MAAM,CAAA;CAAE,CAAC,CA0HrG;AAID,wBAAsB,WAAW,CAC/B,MAAM,EAAE,WAAW,EACnB,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,EAC5B,UAAU,EAAE,MAAM,EAClB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,GAAG,CAAC,CAUd;AA0JD,wBAAsB,iBAAiB,CACrC,MAAM,EAAE,WAAW,EACnB,OAAO,EAAE;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,YAAY,EAAE,MAAM,CAAC;IAAC,aAAa,EAAE,MAAM,CAAC;IAAC,QAAQ,EAAE,MAAM,CAAA;CAAE,GACtF,OAAO,CAAC;IAAE,WAAW,EAAE,MAAM,CAAC;IAAC,YAAY,CAAC,EAAE,MAAM,CAAC;IAAC,SAAS,CAAC,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CAoEpF;AAID,wBAAsB,YAAY,CAChC,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,UAAU,EAAE,MAAM,GAAG,IAAI,EACzB,MAAM,EAAE,MAAM,EACd,GAAG,EAAE,MAAM,GACV,OAAO,CAAC;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,CAAC,CA0BjC"}
|
package/dist/oauth/server.js
CHANGED
|
@@ -3,7 +3,7 @@ import { generateKeyPair, importPrivateKey, computeJwkThumbprint, signJwt, parse
|
|
|
3
3
|
import { parseDpopProof, createDpopProof } from "./dpop.js";
|
|
4
4
|
import { initSession } from "./session.js";
|
|
5
5
|
import { resolveClient, validateRedirectUri, isLoopbackClient } from "./client.js";
|
|
6
|
-
import { discoverAuthServer, resolveHandle } from "./discovery.js";
|
|
6
|
+
import { discoverAuthServer, resolveHandle, fetchProtectedResourceMetadata, fetchAuthServerMetadata } from "./discovery.js";
|
|
7
7
|
import { getServerKey, storeServerKey, storeOAuthRequest, getOAuthRequest, deleteOAuthRequest, storeAuthCode, consumeAuthCode, storeSession, deleteSession, checkAndStoreDpopJti, cleanupExpiredOAuth, storeRefreshToken, getRefreshToken, revokeRefreshToken, } from "./db.js";
|
|
8
8
|
import { emit } from "../logger.js";
|
|
9
9
|
import { querySQL } from "../database/db.js";
|
|
@@ -122,6 +122,17 @@ export function getClientMetadata(issuer, config) {
|
|
|
122
122
|
};
|
|
123
123
|
}
|
|
124
124
|
// --- PAR Endpoint ---
|
|
125
|
+
/**
|
|
126
|
+
* Handle a Pushed Authorization Request (PAR).
|
|
127
|
+
*
|
|
128
|
+
* Supports account creation via `prompt=create`. When set, `login_hint`
|
|
129
|
+
* is treated as a PDS hostname (e.g. "selfhosted.social" or "localhost:2583")
|
|
130
|
+
* rather than a handle or DID. The auth server is discovered from the PDS's
|
|
131
|
+
* protected resource metadata, and `prompt=create` is forwarded to the PDS
|
|
132
|
+
* PAR so it shows the signup page.
|
|
133
|
+
*
|
|
134
|
+
* For normal login, `login_hint` is a handle or DID as usual.
|
|
135
|
+
*/
|
|
125
136
|
export async function handlePar(config, body, dpopHeader, requestUrl) {
|
|
126
137
|
// Validate client DPoP proof
|
|
127
138
|
const dpop = await parseDpopProof(dpopHeader, 'POST', requestUrl);
|
|
@@ -146,9 +157,34 @@ export async function handlePar(config, body, dpopHeader, requestUrl) {
|
|
|
146
157
|
throw new Error('code_challenge is required');
|
|
147
158
|
if (body.code_challenge_method && body.code_challenge_method !== 'S256')
|
|
148
159
|
throw new Error('Only S256 supported');
|
|
149
|
-
// Resolve DID from login_hint
|
|
160
|
+
// Resolve DID and PDS from login_hint
|
|
161
|
+
const prompt = body.prompt;
|
|
150
162
|
let did = body.login_hint;
|
|
151
|
-
|
|
163
|
+
let pdsRequestUri;
|
|
164
|
+
let pdsAuthServer;
|
|
165
|
+
let pdsCodeVerifier;
|
|
166
|
+
let pdsState;
|
|
167
|
+
let pdsEndpoint;
|
|
168
|
+
if (prompt === 'create' && body.login_hint) {
|
|
169
|
+
// Account creation: login_hint is a PDS URL, discover auth server from it directly
|
|
170
|
+
let pdsUrl;
|
|
171
|
+
if (body.login_hint.startsWith('http')) {
|
|
172
|
+
pdsUrl = body.login_hint;
|
|
173
|
+
}
|
|
174
|
+
else if (body.login_hint.match(/^localhost[:/]/)) {
|
|
175
|
+
pdsUrl = `http://${body.login_hint}`;
|
|
176
|
+
}
|
|
177
|
+
else {
|
|
178
|
+
pdsUrl = `https://${body.login_hint}`;
|
|
179
|
+
}
|
|
180
|
+
pdsEndpoint = pdsUrl;
|
|
181
|
+
const protectedResource = await fetchProtectedResourceMetadata(pdsUrl);
|
|
182
|
+
pdsAuthServer = protectedResource.authorization_servers[0];
|
|
183
|
+
if (!pdsAuthServer)
|
|
184
|
+
throw new Error(`No auth server for PDS ${pdsUrl}`);
|
|
185
|
+
did = undefined; // no DID yet for account creation
|
|
186
|
+
}
|
|
187
|
+
else if (did && !did.startsWith('did:')) {
|
|
152
188
|
try {
|
|
153
189
|
did = await resolveHandle(did, _relayUrl);
|
|
154
190
|
}
|
|
@@ -156,33 +192,37 @@ export async function handlePar(config, body, dpopHeader, requestUrl) {
|
|
|
156
192
|
throw new Error('Handle not found');
|
|
157
193
|
}
|
|
158
194
|
}
|
|
159
|
-
// Discover user's PDS auth server
|
|
160
|
-
|
|
161
|
-
let pdsAuthServer;
|
|
162
|
-
let pdsCodeVerifier;
|
|
163
|
-
let pdsState;
|
|
164
|
-
let pdsEndpoint;
|
|
165
|
-
if (did) {
|
|
195
|
+
// Discover user's PDS auth server (for login flow with a resolved DID)
|
|
196
|
+
if (did && !pdsAuthServer) {
|
|
166
197
|
const discovery = await discoverAuthServer(did, _plcUrl);
|
|
167
198
|
pdsAuthServer = discovery.authServerEndpoint;
|
|
168
199
|
pdsEndpoint = discovery.pdsEndpoint;
|
|
200
|
+
}
|
|
201
|
+
if (pdsAuthServer) {
|
|
202
|
+
const authServerMetadata = await fetchAuthServerMetadata(pdsAuthServer);
|
|
169
203
|
// Create PKCE for our PAR to the PDS
|
|
170
204
|
pdsCodeVerifier = randomToken();
|
|
171
205
|
const pdsCodeChallenge = base64UrlEncode(await sha256(pdsCodeVerifier));
|
|
172
206
|
pdsState = randomToken(); // unique state to correlate callback
|
|
173
207
|
// PAR to the PDS
|
|
174
|
-
const parEndpoint =
|
|
208
|
+
const parEndpoint = authServerMetadata.pushed_authorization_request_endpoint || `${pdsAuthServer}/oauth/par`;
|
|
175
209
|
const serverDpopProof = await createDpopProof(serverPrivateJwk, serverPublicJwk, 'POST', parEndpoint);
|
|
176
|
-
const
|
|
210
|
+
const pdsParParams = {
|
|
177
211
|
client_id: pdsClientId(config.issuer, config),
|
|
178
212
|
redirect_uri: pdsRedirectUri(config.issuer),
|
|
179
213
|
response_type: 'code',
|
|
180
214
|
code_challenge: pdsCodeChallenge,
|
|
181
215
|
code_challenge_method: 'S256',
|
|
182
216
|
scope: body.scope || 'atproto transition:generic',
|
|
183
|
-
login_hint: body.login_hint || did,
|
|
184
217
|
state: pdsState,
|
|
185
|
-
}
|
|
218
|
+
};
|
|
219
|
+
if (prompt === 'create') {
|
|
220
|
+
pdsParParams.prompt = 'create';
|
|
221
|
+
}
|
|
222
|
+
if (did) {
|
|
223
|
+
pdsParParams.login_hint = body.login_hint || did;
|
|
224
|
+
}
|
|
225
|
+
const pdsParBody = new URLSearchParams(pdsParParams);
|
|
186
226
|
const pdsParRes = await fetch(parEndpoint, {
|
|
187
227
|
method: 'POST',
|
|
188
228
|
headers: { 'Content-Type': 'application/x-www-form-urlencoded', DPoP: serverDpopProof },
|
|
@@ -265,34 +305,65 @@ export function buildAuthorizeRedirect(config, request) {
|
|
|
265
305
|
return `${request.pds_auth_server}/oauth/authorize?${params}`;
|
|
266
306
|
}
|
|
267
307
|
// --- Server-initiated login (no DPoP required from browser) ---
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
308
|
+
/**
|
|
309
|
+
* Initiate a server-side OAuth login or account creation flow.
|
|
310
|
+
*
|
|
311
|
+
* For account creation, pass `{ prompt: 'create', pds: 'selfhosted.social' }`.
|
|
312
|
+
* The `pds` is a bare hostname; the auth server is discovered from its
|
|
313
|
+
* protected resource metadata.
|
|
314
|
+
*/
|
|
315
|
+
export async function serverLogin(config, handle, options) {
|
|
316
|
+
let did;
|
|
317
|
+
let pdsAuthServer;
|
|
318
|
+
let pdsEndpoint;
|
|
319
|
+
if (options?.prompt === 'create' && options?.pds) {
|
|
320
|
+
// Account creation: discover auth server from PDS hostname
|
|
321
|
+
const pdsUrl = options.pds.startsWith('http')
|
|
322
|
+
? options.pds
|
|
323
|
+
: options.pds.match(/^localhost[:/]/)
|
|
324
|
+
? `http://${options.pds}`
|
|
325
|
+
: `https://${options.pds}`;
|
|
326
|
+
pdsEndpoint = pdsUrl;
|
|
327
|
+
const protectedResource = await fetchProtectedResourceMetadata(pdsUrl);
|
|
328
|
+
pdsAuthServer = protectedResource.authorization_servers[0];
|
|
329
|
+
if (!pdsAuthServer)
|
|
330
|
+
throw new Error(`No auth server for PDS ${pdsUrl}`);
|
|
331
|
+
}
|
|
332
|
+
else {
|
|
333
|
+
// Normal login: resolve handle to DID
|
|
334
|
+
did = handle;
|
|
335
|
+
if (!did.startsWith('did:')) {
|
|
336
|
+
did = await resolveHandle(handle, _relayUrl);
|
|
337
|
+
}
|
|
338
|
+
const discovery = await discoverAuthServer(did, _plcUrl);
|
|
339
|
+
pdsAuthServer = discovery.authServerEndpoint;
|
|
340
|
+
pdsEndpoint = discovery.pdsEndpoint;
|
|
273
341
|
}
|
|
274
|
-
|
|
275
|
-
const discovery = await discoverAuthServer(did, _plcUrl);
|
|
276
|
-
const pdsAuthServer = discovery.authServerEndpoint;
|
|
277
|
-
const pdsEndpoint = discovery.pdsEndpoint;
|
|
342
|
+
const authServerMetadata = await fetchAuthServerMetadata(pdsAuthServer);
|
|
278
343
|
// Create PKCE for PAR to PDS
|
|
279
344
|
const pdsCodeVerifier = randomToken();
|
|
280
345
|
const pdsCodeChallenge = base64UrlEncode(await sha256(pdsCodeVerifier));
|
|
281
346
|
const pdsState = randomToken();
|
|
282
347
|
// PAR to the PDS
|
|
283
|
-
const parEndpoint =
|
|
348
|
+
const parEndpoint = authServerMetadata.pushed_authorization_request_endpoint || `${pdsAuthServer}/oauth/par`;
|
|
284
349
|
const serverDpopProof = await createDpopProof(serverPrivateJwk, serverPublicJwk, 'POST', parEndpoint);
|
|
285
350
|
const scope = config.scopes?.join(' ') || 'atproto transition:generic';
|
|
286
|
-
const
|
|
351
|
+
const pdsParParams = {
|
|
287
352
|
client_id: pdsClientId(config.issuer, config),
|
|
288
353
|
redirect_uri: pdsRedirectUri(config.issuer),
|
|
289
354
|
response_type: 'code',
|
|
290
355
|
code_challenge: pdsCodeChallenge,
|
|
291
356
|
code_challenge_method: 'S256',
|
|
292
357
|
scope,
|
|
293
|
-
login_hint: handle,
|
|
294
358
|
state: pdsState,
|
|
295
|
-
}
|
|
359
|
+
};
|
|
360
|
+
if (options?.prompt === 'create') {
|
|
361
|
+
pdsParParams.prompt = 'create';
|
|
362
|
+
}
|
|
363
|
+
if (did) {
|
|
364
|
+
pdsParParams.login_hint = handle;
|
|
365
|
+
}
|
|
366
|
+
const pdsParBody = new URLSearchParams(pdsParParams);
|
|
296
367
|
let pdsRequestUri;
|
|
297
368
|
const pdsParRes = await fetch(parEndpoint, {
|
|
298
369
|
method: 'POST',
|
package/dist/server.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAyDA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AA0B9C;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,GAAG,IAAI,CAuK3F;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,KAAK,EAAE,WAAW,GAAG,IAAI,CAAA;IACzB,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACxF,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IAC5D,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CACtB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,
|
|
1
|
+
{"version":3,"file":"server.d.ts","sourceRoot":"","sources":["../src/server.ts"],"names":[],"mappings":"AAyDA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,aAAa,CAAA;AA0B9C;;;GAGG;AACH,wBAAgB,oBAAoB,CAAC,WAAW,EAAE,MAAM,EAAE,EAAE,KAAK,EAAE,WAAW,GAAG,IAAI,GAAG,IAAI,CAuK3F;AAED,MAAM,WAAW,aAAa;IAC5B,WAAW,EAAE,MAAM,EAAE,CAAA;IACrB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAA;IACxB,KAAK,EAAE,WAAW,GAAG,IAAI,CAAA;IACzB,MAAM,EAAE,MAAM,EAAE,CAAA;IAChB,QAAQ,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,GAAG,KAAK,OAAO,CAAC;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC,CAAA;IACxF,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK;QAAE,GAAG,EAAE,MAAM,CAAA;KAAE,GAAG,IAAI,CAAA;IAC5D,QAAQ,CAAC,EAAE,MAAM,IAAI,CAAA;CACtB;AAED;;;GAGG;AACH,wBAAgB,aAAa,CAAC,MAAM,EAAE,aAAa,GAAG,CAAC,OAAO,EAAE,OAAO,KAAK,OAAO,CAAC,QAAQ,CAAC,CA+zB5F;AAGD,wBAAgB,WAAW,CACzB,IAAI,EAAE,MAAM,EACZ,WAAW,EAAE,MAAM,EAAE,EACrB,SAAS,EAAE,MAAM,GAAG,IAAI,EACxB,KAAK,EAAE,WAAW,GAAG,IAAI,EACzB,MAAM,GAAE,MAAM,EAAO,EACrB,aAAa,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK;IAAE,GAAG,EAAE,MAAM,CAAA;CAAE,GAAG,IAAI,EAC5D,QAAQ,CAAC,EAAE,MAAM,IAAI,GACpB,OAAO,WAAW,EAAE,MAAM,CAG5B"}
|
package/dist/server.js
CHANGED
|
@@ -728,11 +728,13 @@ export function createHandler(config) {
|
|
|
728
728
|
}
|
|
729
729
|
// OAuth Login (server-initiated, no DPoP required)
|
|
730
730
|
if (url.pathname === '/oauth/login' && oauth) {
|
|
731
|
-
const handle = url.searchParams.get('handle');
|
|
732
|
-
|
|
731
|
+
const handle = url.searchParams.get('handle') || '';
|
|
732
|
+
const prompt = url.searchParams.get('prompt') || undefined;
|
|
733
|
+
const pds = url.searchParams.get('pds') || undefined;
|
|
734
|
+
if (!handle && prompt !== 'create')
|
|
733
735
|
return withCors(jsonError(400, 'handle required', acceptEncoding));
|
|
734
736
|
try {
|
|
735
|
-
const redirectUrl = await serverLogin(oauth, handle);
|
|
737
|
+
const redirectUrl = await serverLogin(oauth, handle, { prompt, pds });
|
|
736
738
|
return new Response(null, {
|
|
737
739
|
status: 302,
|
|
738
740
|
headers: { Location: redirectUrl, 'Set-Cookie': clearSessionCookieHeader() },
|