@~lyre/auth 0.0.8 → 0.0.9
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/{chunk-2FSPKJAC.js → chunk-QIAL6IDV.js} +32 -0
- package/dist/index.d.ts +15 -1
- package/dist/index.js +7 -3
- package/dist/sveltekit.d.ts +12 -2
- package/dist/sveltekit.js +35 -2
- package/package.json +1 -1
|
@@ -278,6 +278,36 @@ async function introspectServiceKey(input) {
|
|
|
278
278
|
return null;
|
|
279
279
|
}
|
|
280
280
|
}
|
|
281
|
+
async function logoutFromAccounts(input) {
|
|
282
|
+
const base = normalizeOptionalString(input.config.baseUrl);
|
|
283
|
+
if (!base || !input.accessToken) return { success: false };
|
|
284
|
+
const fetchImpl = input.fetchImpl ?? fetch;
|
|
285
|
+
try {
|
|
286
|
+
const res = await fetchImpl(new URL("/api/auth/logout", base), {
|
|
287
|
+
method: "POST",
|
|
288
|
+
headers: {
|
|
289
|
+
"content-type": "application/json",
|
|
290
|
+
authorization: `Bearer ${input.accessToken}`,
|
|
291
|
+
accept: "application/json"
|
|
292
|
+
},
|
|
293
|
+
body: JSON.stringify({ all: input.all ?? false })
|
|
294
|
+
});
|
|
295
|
+
if (!res.ok) return { success: false };
|
|
296
|
+
return await res.json();
|
|
297
|
+
} catch {
|
|
298
|
+
return { success: false };
|
|
299
|
+
}
|
|
300
|
+
}
|
|
301
|
+
function verifyWebhookSignature(rawBody, signature, secret) {
|
|
302
|
+
if (!signature || !secret) return false;
|
|
303
|
+
const provided = (signature.startsWith("sha256=") ? signature.slice(7) : signature).toLowerCase();
|
|
304
|
+
if (!/^[0-9a-f]{64}$/.test(provided)) return false;
|
|
305
|
+
const expected = createHmac("sha256", secret).update(rawBody).digest("hex");
|
|
306
|
+
const a = Buffer.from(provided, "hex");
|
|
307
|
+
const b = Buffer.from(expected, "hex");
|
|
308
|
+
if (a.length !== b.length) return false;
|
|
309
|
+
return timingSafeEqual(a, b);
|
|
310
|
+
}
|
|
281
311
|
function scopeSatisfied(granted, required) {
|
|
282
312
|
if (!granted || granted.length === 0) return false;
|
|
283
313
|
return granted.includes(required);
|
|
@@ -296,5 +326,7 @@ export {
|
|
|
296
326
|
clearPlatformSessionCookie,
|
|
297
327
|
serviceKeyFromRequest,
|
|
298
328
|
introspectServiceKey,
|
|
329
|
+
logoutFromAccounts,
|
|
330
|
+
verifyWebhookSignature,
|
|
299
331
|
scopeSatisfied
|
|
300
332
|
};
|
package/dist/index.d.ts
CHANGED
|
@@ -162,6 +162,20 @@ declare function introspectServiceKey(input: {
|
|
|
162
162
|
key: string;
|
|
163
163
|
fetchImpl?: typeof fetch;
|
|
164
164
|
}): Promise<ServiceKeyContext | null>;
|
|
165
|
+
declare function logoutFromAccounts(input: {
|
|
166
|
+
config: Pick<AccountsClientConfig, 'baseUrl'>;
|
|
167
|
+
accessToken: string;
|
|
168
|
+
all?: boolean;
|
|
169
|
+
fetchImpl?: typeof fetch;
|
|
170
|
+
}): Promise<{
|
|
171
|
+
success: boolean;
|
|
172
|
+
revokedCount?: number;
|
|
173
|
+
}>;
|
|
174
|
+
declare function verifyWebhookSignature(rawBody: string, signature: string | null | undefined, secret: string): boolean;
|
|
175
|
+
type AccountsWebhookEvent = {
|
|
176
|
+
type: string;
|
|
177
|
+
[key: string]: unknown;
|
|
178
|
+
};
|
|
165
179
|
declare function scopeSatisfied(granted: string[] | undefined, required: string): boolean;
|
|
166
180
|
|
|
167
|
-
export { type AccountsClientConfig, type AccountsIdentity, type AccountsTokenResponse, type AuthenticatedPrincipal, type AuthorizationState, type CookieOptions, type LocalUser, type PermissionSet, type PlatformSession, type ServiceKeyApp, type ServiceKeyContext, type SyncAccountsUser, type SyncAccountsUserResult, type TenantAccessContext, type TenantContext, type TenantMembership, beginAccountsLoginRedirect, clearPlatformSessionCookie, createAccountsClientConfig, createPlatformAuth, exchangeAuthorizationCode, handleAccountsCallback, identityPassthroughSync, introspectServiceKey, readPlatformSessionCookie, resolveActiveTenant, scopeSatisfied, serviceKeyFromRequest, syncAccountsUser };
|
|
181
|
+
export { type AccountsClientConfig, type AccountsIdentity, type AccountsTokenResponse, type AccountsWebhookEvent, type AuthenticatedPrincipal, type AuthorizationState, type CookieOptions, type LocalUser, type PermissionSet, type PlatformSession, type ServiceKeyApp, type ServiceKeyContext, type SyncAccountsUser, type SyncAccountsUserResult, type TenantAccessContext, type TenantContext, type TenantMembership, beginAccountsLoginRedirect, clearPlatformSessionCookie, createAccountsClientConfig, createPlatformAuth, exchangeAuthorizationCode, handleAccountsCallback, identityPassthroughSync, introspectServiceKey, logoutFromAccounts, readPlatformSessionCookie, resolveActiveTenant, scopeSatisfied, serviceKeyFromRequest, syncAccountsUser, verifyWebhookSignature };
|
package/dist/index.js
CHANGED
|
@@ -7,12 +7,14 @@ import {
|
|
|
7
7
|
handleAccountsCallback,
|
|
8
8
|
identityPassthroughSync,
|
|
9
9
|
introspectServiceKey,
|
|
10
|
+
logoutFromAccounts,
|
|
10
11
|
readPlatformSessionCookie,
|
|
11
12
|
resolveActiveTenant,
|
|
12
13
|
scopeSatisfied,
|
|
13
14
|
serviceKeyFromRequest,
|
|
14
|
-
syncAccountsUser
|
|
15
|
-
|
|
15
|
+
syncAccountsUser,
|
|
16
|
+
verifyWebhookSignature
|
|
17
|
+
} from "./chunk-QIAL6IDV.js";
|
|
16
18
|
export {
|
|
17
19
|
beginAccountsLoginRedirect,
|
|
18
20
|
clearPlatformSessionCookie,
|
|
@@ -22,9 +24,11 @@ export {
|
|
|
22
24
|
handleAccountsCallback,
|
|
23
25
|
identityPassthroughSync,
|
|
24
26
|
introspectServiceKey,
|
|
27
|
+
logoutFromAccounts,
|
|
25
28
|
readPlatformSessionCookie,
|
|
26
29
|
resolveActiveTenant,
|
|
27
30
|
scopeSatisfied,
|
|
28
31
|
serviceKeyFromRequest,
|
|
29
|
-
syncAccountsUser
|
|
32
|
+
syncAccountsUser,
|
|
33
|
+
verifyWebhookSignature
|
|
30
34
|
};
|
package/dist/sveltekit.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { RequestEvent, Handle } from '@sveltejs/kit';
|
|
2
|
-
import { PlatformSession, AccountsClientConfig, ServiceKeyContext, SyncAccountsUser, CookieOptions } from './index.js';
|
|
2
|
+
import { AccountsWebhookEvent, PlatformSession, AccountsClientConfig, ServiceKeyContext, SyncAccountsUser, CookieOptions } from './index.js';
|
|
3
3
|
export { clearPlatformSessionCookie } from './index.js';
|
|
4
4
|
|
|
5
5
|
type SvelteKitAuthOptions = {
|
|
@@ -51,5 +51,15 @@ type ServiceKeyLocals = {
|
|
|
51
51
|
serviceKey?: ServiceKeyContext | null;
|
|
52
52
|
};
|
|
53
53
|
declare function createServiceKeyHandle(opts: ServiceKeyHandleOptions): Handle;
|
|
54
|
+
type AccountsWebhookOptions = {
|
|
55
|
+
secret: string;
|
|
56
|
+
/** Route to receive webhooks on. Default '/api/auth/accounts/webhook'. */
|
|
57
|
+
path?: string;
|
|
58
|
+
/** Header carrying the signature. Default 'x-accounts-signature'. */
|
|
59
|
+
signatureHeader?: string;
|
|
60
|
+
/** React to a verified event. Throwing yields a 500 (Accounts may retry). */
|
|
61
|
+
onEvent: (event: AccountsWebhookEvent, raw: string, request: RequestEvent) => void | Promise<void>;
|
|
62
|
+
};
|
|
63
|
+
declare function createAccountsWebhookHandle(opts: AccountsWebhookOptions): Handle;
|
|
54
64
|
|
|
55
|
-
export { type PlatformLocals, type ServiceKeyHandleOptions, type ServiceKeyLocals, type SvelteKitAuthOptions, createAuthHandle, createServiceKeyHandle };
|
|
65
|
+
export { type AccountsWebhookOptions, type PlatformLocals, type ServiceKeyHandleOptions, type ServiceKeyLocals, type SvelteKitAuthOptions, createAccountsWebhookHandle, createAuthHandle, createServiceKeyHandle };
|
package/dist/sveltekit.js
CHANGED
|
@@ -4,9 +4,11 @@ import {
|
|
|
4
4
|
handleAccountsCallback,
|
|
5
5
|
identityPassthroughSync,
|
|
6
6
|
introspectServiceKey,
|
|
7
|
+
logoutFromAccounts,
|
|
7
8
|
readPlatformSessionCookie,
|
|
8
|
-
serviceKeyFromRequest
|
|
9
|
-
|
|
9
|
+
serviceKeyFromRequest,
|
|
10
|
+
verifyWebhookSignature
|
|
11
|
+
} from "./chunk-QIAL6IDV.js";
|
|
10
12
|
|
|
11
13
|
// src/sveltekit.ts
|
|
12
14
|
import { createHash } from "crypto";
|
|
@@ -55,6 +57,10 @@ function createAuthHandle(opts) {
|
|
|
55
57
|
]);
|
|
56
58
|
}
|
|
57
59
|
if (path === logoutPath) {
|
|
60
|
+
if (session.accessToken) {
|
|
61
|
+
const all = event.url.searchParams.get("all") === "1" || event.url.searchParams.get("all") === "true";
|
|
62
|
+
await logoutFromAccounts({ config: opts.config, accessToken: session.accessToken, all });
|
|
63
|
+
}
|
|
58
64
|
return redirectWithCookies(postLogoutPath, [
|
|
59
65
|
clearPlatformSessionCookie(cookieOptions),
|
|
60
66
|
`${STATE_COOKIE}=; ${cookieOptions?.sameSite === "none" ? "Path=/; HttpOnly; SameSite=None; Secure" : "Path=/; HttpOnly; SameSite=Lax"}; Max-Age=0`
|
|
@@ -102,8 +108,35 @@ function createServiceKeyHandle(opts) {
|
|
|
102
108
|
});
|
|
103
109
|
};
|
|
104
110
|
}
|
|
111
|
+
function jsonResponse(status, body) {
|
|
112
|
+
return new Response(JSON.stringify(body), { status, headers: { "content-type": "application/json" } });
|
|
113
|
+
}
|
|
114
|
+
function createAccountsWebhookHandle(opts) {
|
|
115
|
+
const path = opts.path ?? "/api/auth/accounts/webhook";
|
|
116
|
+
const sigHeader = opts.signatureHeader ?? "x-accounts-signature";
|
|
117
|
+
return async ({ event, resolve }) => {
|
|
118
|
+
if (event.url.pathname !== path || event.request.method !== "POST") return resolve(event);
|
|
119
|
+
const raw = await event.request.text();
|
|
120
|
+
if (!verifyWebhookSignature(raw, event.request.headers.get(sigHeader), opts.secret)) {
|
|
121
|
+
return jsonResponse(401, { ok: false, error: "Invalid webhook signature." });
|
|
122
|
+
}
|
|
123
|
+
let payload;
|
|
124
|
+
try {
|
|
125
|
+
payload = JSON.parse(raw);
|
|
126
|
+
} catch {
|
|
127
|
+
return jsonResponse(400, { ok: false, error: "Invalid JSON body." });
|
|
128
|
+
}
|
|
129
|
+
try {
|
|
130
|
+
await opts.onEvent({ ...payload, type: String(payload.type ?? "unknown") }, raw, event);
|
|
131
|
+
} catch {
|
|
132
|
+
return jsonResponse(500, { ok: false, error: "Webhook handler failed." });
|
|
133
|
+
}
|
|
134
|
+
return jsonResponse(200, { ok: true });
|
|
135
|
+
};
|
|
136
|
+
}
|
|
105
137
|
export {
|
|
106
138
|
clearPlatformSessionCookie,
|
|
139
|
+
createAccountsWebhookHandle,
|
|
107
140
|
createAuthHandle,
|
|
108
141
|
createServiceKeyHandle
|
|
109
142
|
};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@~lyre/auth",
|
|
3
|
-
"version": "0.0.
|
|
3
|
+
"version": "0.0.9",
|
|
4
4
|
"description": "Shared Axis Accounts auth SDK — framework-agnostic session/identity core (HMAC-signed cookies, accounts login/callback/logout) plus an optional turnkey SvelteKit adapter.",
|
|
5
5
|
"type": "module",
|
|
6
6
|
"sideEffects": false,
|