@hatk/hatk 0.0.1-alpha.47 → 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 +11 -1
- package/dist/oauth/server.d.ts.map +1 -1
- package/dist/oauth/server.js +44 -13
- 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
|
@@ -75,7 +75,17 @@ export declare function handlePar(config: OAuthConfig, body: Record<string, stri
|
|
|
75
75
|
expires_in: number;
|
|
76
76
|
}>;
|
|
77
77
|
export declare function buildAuthorizeRedirect(config: OAuthConfig, request: any): string;
|
|
78
|
-
|
|
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>;
|
|
79
89
|
export declare function handleCallback(config: OAuthConfig, code: string, state: string | null, iss: string | null): Promise<{
|
|
80
90
|
requestUri: string;
|
|
81
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;;;;;;;;;;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,wBAAsB,WAAW,
|
|
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
|
@@ -305,34 +305,65 @@ export function buildAuthorizeRedirect(config, request) {
|
|
|
305
305
|
return `${request.pds_auth_server}/oauth/authorize?${params}`;
|
|
306
306
|
}
|
|
307
307
|
// --- Server-initiated login (no DPoP required from browser) ---
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
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}`);
|
|
313
331
|
}
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
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;
|
|
341
|
+
}
|
|
342
|
+
const authServerMetadata = await fetchAuthServerMetadata(pdsAuthServer);
|
|
318
343
|
// Create PKCE for PAR to PDS
|
|
319
344
|
const pdsCodeVerifier = randomToken();
|
|
320
345
|
const pdsCodeChallenge = base64UrlEncode(await sha256(pdsCodeVerifier));
|
|
321
346
|
const pdsState = randomToken();
|
|
322
347
|
// PAR to the PDS
|
|
323
|
-
const parEndpoint =
|
|
348
|
+
const parEndpoint = authServerMetadata.pushed_authorization_request_endpoint || `${pdsAuthServer}/oauth/par`;
|
|
324
349
|
const serverDpopProof = await createDpopProof(serverPrivateJwk, serverPublicJwk, 'POST', parEndpoint);
|
|
325
350
|
const scope = config.scopes?.join(' ') || 'atproto transition:generic';
|
|
326
|
-
const
|
|
351
|
+
const pdsParParams = {
|
|
327
352
|
client_id: pdsClientId(config.issuer, config),
|
|
328
353
|
redirect_uri: pdsRedirectUri(config.issuer),
|
|
329
354
|
response_type: 'code',
|
|
330
355
|
code_challenge: pdsCodeChallenge,
|
|
331
356
|
code_challenge_method: 'S256',
|
|
332
357
|
scope,
|
|
333
|
-
login_hint: handle,
|
|
334
358
|
state: pdsState,
|
|
335
|
-
}
|
|
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);
|
|
336
367
|
let pdsRequestUri;
|
|
337
368
|
const pdsParRes = await fetch(parEndpoint, {
|
|
338
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() },
|