@authon/node 0.1.0 → 0.1.14
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/index.cjs +22 -10
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +22 -2
- package/dist/index.d.ts +22 -2
- package/dist/index.js +22 -10
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
package/dist/index.cjs
CHANGED
|
@@ -47,32 +47,44 @@ var AuthonBackend = class {
|
|
|
47
47
|
if (options?.limit) params.set("limit", String(options.limit));
|
|
48
48
|
if (options?.search) params.set("search", options.search);
|
|
49
49
|
const qs = params.toString();
|
|
50
|
-
return this.request("GET", `/v1/users${qs ? `?${qs}` : ""}`);
|
|
50
|
+
return this.request("GET", `/v1/backend/users${qs ? `?${qs}` : ""}`);
|
|
51
51
|
},
|
|
52
52
|
get: (userId) => {
|
|
53
|
-
return this.request("GET", `/v1/users/${userId}`);
|
|
53
|
+
return this.request("GET", `/v1/backend/users/${userId}`);
|
|
54
|
+
},
|
|
55
|
+
getByExternalId: (externalId) => {
|
|
56
|
+
return this.request("GET", `/v1/backend/users/by-external-id/${externalId}`);
|
|
54
57
|
},
|
|
55
58
|
create: (data) => {
|
|
56
|
-
return this.request("POST", "/v1/users", data);
|
|
59
|
+
return this.request("POST", "/v1/backend/users", data);
|
|
57
60
|
},
|
|
58
61
|
update: (userId, data) => {
|
|
59
|
-
return this.request("PATCH", `/v1/users/${userId}`, data);
|
|
62
|
+
return this.request("PATCH", `/v1/backend/users/${userId}`, data);
|
|
60
63
|
},
|
|
61
64
|
delete: (userId) => {
|
|
62
|
-
return this.request("DELETE", `/v1/users/${userId}`);
|
|
65
|
+
return this.request("DELETE", `/v1/backend/users/${userId}`);
|
|
63
66
|
},
|
|
64
67
|
ban: (userId, reason) => {
|
|
65
|
-
return this.request("POST", `/v1/users/${userId}/ban`, { reason });
|
|
68
|
+
return this.request("POST", `/v1/backend/users/${userId}/ban`, { reason });
|
|
66
69
|
},
|
|
67
70
|
unban: (userId) => {
|
|
68
|
-
return this.request("POST", `/v1/users/${userId}/unban`);
|
|
71
|
+
return this.request("POST", `/v1/backend/users/${userId}/unban`);
|
|
69
72
|
}
|
|
70
73
|
};
|
|
71
74
|
webhooks = {
|
|
72
|
-
|
|
75
|
+
/**
|
|
76
|
+
* Verify an Authon webhook signature.
|
|
77
|
+
* @param payload - Raw request body (string or Buffer)
|
|
78
|
+
* @param signature - Value of `X-Authon-Signature` header (format: `v1=<hex>`)
|
|
79
|
+
* @param timestamp - Value of `X-Authon-Timestamp` header (ISO 8601)
|
|
80
|
+
* @param secret - Your webhook signing secret
|
|
81
|
+
* @returns Parsed payload object
|
|
82
|
+
*/
|
|
83
|
+
verify: (payload, signature, timestamp, secret) => {
|
|
73
84
|
const body = typeof payload === "string" ? payload : payload.toString("utf8");
|
|
74
|
-
const
|
|
75
|
-
const
|
|
85
|
+
const signedPayload = `${timestamp}.${body}`;
|
|
86
|
+
const expected = (0, import_crypto.createHmac)("sha256", secret).update(signedPayload).digest("hex");
|
|
87
|
+
const actual = signature.replace("v1=", "");
|
|
76
88
|
const expectedBuf = Buffer.from(expected, "hex");
|
|
77
89
|
const actualBuf = Buffer.from(actual, "hex");
|
|
78
90
|
if (expectedBuf.length !== actualBuf.length || !(0, import_crypto.timingSafeEqual)(expectedBuf, actualBuf)) {
|
package/dist/index.cjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/index.ts","../src/authon.ts","../src/middleware.ts"],"sourcesContent":["export { AuthonBackend } from './authon';\nexport { expressMiddleware, fastifyPlugin } from './middleware';\nexport type { AuthonMiddlewareOptions } from './middleware';\n","import type { AuthonUser } from '@authon/shared';\nimport { createHmac, timingSafeEqual } from 'crypto';\n\ninterface AuthonBackendConfig {\n apiUrl?: string;\n}\n\ninterface ListOptions {\n page?: number;\n limit?: number;\n search?: string;\n}\n\ninterface ListResult<T> {\n data: T[];\n total: number;\n page: number;\n limit: number;\n}\n\nexport class AuthonBackend {\n private secretKey: string;\n private apiUrl: string;\n\n constructor(secretKey: string, config?: AuthonBackendConfig) {\n this.secretKey = secretKey;\n this.apiUrl = config?.apiUrl || 'https://api.authon.dev';\n }\n\n async verifyToken(accessToken: string): Promise<AuthonUser> {\n return this.request<AuthonUser>('GET', '/v1/auth/token/verify', undefined, {\n Authorization: `Bearer ${accessToken}`,\n });\n }\n\n users = {\n list: (options?: ListOptions): Promise<ListResult<AuthonUser>> => {\n const params = new URLSearchParams();\n if (options?.page) params.set('page', String(options.page));\n if (options?.limit) params.set('limit', String(options.limit));\n if (options?.search) params.set('search', options.search);\n const qs = params.toString();\n return this.request('GET', `/v1/users${qs ? `?${qs}` : ''}`);\n },\n\n get: (userId: string): Promise<AuthonUser> => {\n return this.request('GET', `/v1/users/${userId}`);\n },\n\n create: (data: {\n email: string;\n password?: string;\n displayName?: string;\n }): Promise<AuthonUser> => {\n return this.request('POST', '/v1/users', data);\n },\n\n update: (\n userId: string,\n data: Partial<{ email: string; displayName: string; publicMetadata: Record<string, unknown> }>,\n ): Promise<AuthonUser> => {\n return this.request('PATCH', `/v1/users/${userId}`, data);\n },\n\n delete: (userId: string): Promise<void> => {\n return this.request('DELETE', `/v1/users/${userId}`);\n },\n\n ban: (userId: string, reason?: string): Promise<AuthonUser> => {\n return this.request('POST', `/v1/users/${userId}/ban`, { reason });\n },\n\n unban: (userId: string): Promise<AuthonUser> => {\n return this.request('POST', `/v1/users/${userId}/unban`);\n },\n };\n\n webhooks = {\n verify: (\n payload: string | Buffer,\n signature: string,\n secret: string,\n ): Record<string, unknown> => {\n const body = typeof payload === 'string' ? payload : payload.toString('utf8');\n const expected = createHmac('sha256', secret).update(body).digest('hex');\n const actual = signature.replace('sha256=', '');\n\n const expectedBuf = Buffer.from(expected, 'hex');\n const actualBuf = Buffer.from(actual, 'hex');\n\n if (expectedBuf.length !== actualBuf.length || !timingSafeEqual(expectedBuf, actualBuf)) {\n throw new Error('Invalid webhook signature');\n }\n\n return JSON.parse(body);\n },\n };\n\n private async request<T>(\n method: string,\n path: string,\n body?: unknown,\n extraHeaders?: Record<string, string>,\n ): Promise<T> {\n const res = await fetch(`${this.apiUrl}${path}`, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.secretKey,\n ...extraHeaders,\n },\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Authon API error ${res.status}: ${text}`);\n }\n\n if (res.status === 204) return undefined as T;\n return res.json() as Promise<T>;\n }\n}\n","import type { AuthonUser } from '@authon/shared';\nimport { AuthonBackend } from './authon';\n\nexport interface AuthonMiddlewareOptions {\n secretKey: string;\n apiUrl?: string;\n onError?: (error: Error) => void;\n}\n\nexport function expressMiddleware(options: AuthonMiddlewareOptions) {\n const client = new AuthonBackend(options.secretKey, { apiUrl: options.apiUrl });\n\n return async (\n req: { headers: Record<string, string | string[] | undefined>; auth?: AuthonUser },\n res: { status: (code: number) => { json: (body: unknown) => void } },\n next: (err?: unknown) => void,\n ) => {\n const authHeader = req.headers['authorization'];\n const token = typeof authHeader === 'string' ? authHeader.replace('Bearer ', '') : null;\n\n if (!token) {\n res.status(401).json({ error: 'Missing authorization header' });\n return;\n }\n\n try {\n req.auth = await client.verifyToken(token);\n next();\n } catch (err) {\n options.onError?.(err instanceof Error ? err : new Error(String(err)));\n res.status(401).json({ error: 'Invalid token' });\n }\n };\n}\n\nexport function fastifyPlugin(options: AuthonMiddlewareOptions) {\n const client = new AuthonBackend(options.secretKey, { apiUrl: options.apiUrl });\n\n return async (\n request: { headers: Record<string, string | string[] | undefined>; auth?: AuthonUser },\n reply: { code: (code: number) => { send: (body: unknown) => void } },\n ) => {\n const authHeader = request.headers['authorization'];\n const token = typeof authHeader === 'string' ? authHeader.replace('Bearer ', '') : null;\n\n if (!token) {\n reply.code(401).send({ error: 'Missing authorization header' });\n return;\n }\n\n try {\n request.auth = await client.verifyToken(token);\n } catch (err) {\n options.onError?.(err instanceof Error ? err : new Error(String(err)));\n reply.code(401).send({ error: 'Invalid token' });\n }\n };\n}\n"],"mappings":"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","names":[]}
|
|
1
|
+
{"version":3,"sources":["../src/index.ts","../src/authon.ts","../src/middleware.ts"],"sourcesContent":["export { AuthonBackend } from './authon';\nexport { expressMiddleware, fastifyPlugin } from './middleware';\nexport type { AuthonMiddlewareOptions } from './middleware';\n","import type { AuthonUser } from '@authon/shared';\nimport { createHmac, timingSafeEqual } from 'crypto';\n\ninterface AuthonBackendConfig {\n apiUrl?: string;\n}\n\ninterface ListOptions {\n page?: number;\n limit?: number;\n search?: string;\n}\n\ninterface ListResult<T> {\n data: T[];\n total: number;\n page: number;\n limit: number;\n}\n\nexport class AuthonBackend {\n private secretKey: string;\n private apiUrl: string;\n\n constructor(secretKey: string, config?: AuthonBackendConfig) {\n this.secretKey = secretKey;\n this.apiUrl = config?.apiUrl || 'https://api.authon.dev';\n }\n\n async verifyToken(accessToken: string): Promise<AuthonUser> {\n return this.request<AuthonUser>('GET', '/v1/auth/token/verify', undefined, {\n Authorization: `Bearer ${accessToken}`,\n });\n }\n\n users = {\n list: (options?: ListOptions): Promise<ListResult<AuthonUser>> => {\n const params = new URLSearchParams();\n if (options?.page) params.set('page', String(options.page));\n if (options?.limit) params.set('limit', String(options.limit));\n if (options?.search) params.set('search', options.search);\n const qs = params.toString();\n return this.request('GET', `/v1/backend/users${qs ? `?${qs}` : ''}`);\n },\n\n get: (userId: string): Promise<AuthonUser> => {\n return this.request('GET', `/v1/backend/users/${userId}`);\n },\n\n getByExternalId: (externalId: string): Promise<AuthonUser> => {\n return this.request('GET', `/v1/backend/users/by-external-id/${externalId}`);\n },\n\n create: (data: {\n email: string;\n password?: string;\n displayName?: string;\n externalId?: string;\n provider?: string;\n avatarUrl?: string;\n phone?: string;\n emailVerified?: boolean;\n publicMetadata?: Record<string, unknown>;\n privateMetadata?: Record<string, unknown>;\n }): Promise<AuthonUser> => {\n return this.request('POST', '/v1/backend/users', data);\n },\n\n update: (\n userId: string,\n data: Partial<{\n displayName: string;\n externalId: string;\n avatarUrl: string;\n phone: string;\n emailVerified: boolean;\n publicMetadata: Record<string, unknown>;\n privateMetadata: Record<string, unknown>;\n }>,\n ): Promise<AuthonUser> => {\n return this.request('PATCH', `/v1/backend/users/${userId}`, data);\n },\n\n delete: (userId: string): Promise<void> => {\n return this.request('DELETE', `/v1/backend/users/${userId}`);\n },\n\n ban: (userId: string, reason?: string): Promise<AuthonUser> => {\n return this.request('POST', `/v1/backend/users/${userId}/ban`, { reason });\n },\n\n unban: (userId: string): Promise<AuthonUser> => {\n return this.request('POST', `/v1/backend/users/${userId}/unban`);\n },\n };\n\n webhooks = {\n /**\n * Verify an Authon webhook signature.\n * @param payload - Raw request body (string or Buffer)\n * @param signature - Value of `X-Authon-Signature` header (format: `v1=<hex>`)\n * @param timestamp - Value of `X-Authon-Timestamp` header (ISO 8601)\n * @param secret - Your webhook signing secret\n * @returns Parsed payload object\n */\n verify: (\n payload: string | Buffer,\n signature: string,\n timestamp: string,\n secret: string,\n ): Record<string, unknown> => {\n const body = typeof payload === 'string' ? payload : payload.toString('utf8');\n const signedPayload = `${timestamp}.${body}`;\n const expected = createHmac('sha256', secret).update(signedPayload).digest('hex');\n const actual = signature.replace('v1=', '');\n\n const expectedBuf = Buffer.from(expected, 'hex');\n const actualBuf = Buffer.from(actual, 'hex');\n\n if (expectedBuf.length !== actualBuf.length || !timingSafeEqual(expectedBuf, actualBuf)) {\n throw new Error('Invalid webhook signature');\n }\n\n return JSON.parse(body);\n },\n };\n\n private async request<T>(\n method: string,\n path: string,\n body?: unknown,\n extraHeaders?: Record<string, string>,\n ): Promise<T> {\n const res = await fetch(`${this.apiUrl}${path}`, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.secretKey,\n ...extraHeaders,\n },\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Authon API error ${res.status}: ${text}`);\n }\n\n if (res.status === 204) return undefined as T;\n return res.json() as Promise<T>;\n }\n}\n","import type { AuthonUser } from '@authon/shared';\nimport { AuthonBackend } from './authon';\n\nexport interface AuthonMiddlewareOptions {\n secretKey: string;\n apiUrl?: string;\n onError?: (error: Error) => void;\n}\n\nexport function expressMiddleware(options: AuthonMiddlewareOptions) {\n const client = new AuthonBackend(options.secretKey, { apiUrl: options.apiUrl });\n\n return async (\n req: { headers: Record<string, string | string[] | undefined>; auth?: AuthonUser },\n res: { status: (code: number) => { json: (body: unknown) => void } },\n next: (err?: unknown) => void,\n ) => {\n const authHeader = req.headers['authorization'];\n const token = typeof authHeader === 'string' ? authHeader.replace('Bearer ', '') : null;\n\n if (!token) {\n res.status(401).json({ error: 'Missing authorization header' });\n return;\n }\n\n try {\n req.auth = await client.verifyToken(token);\n next();\n } catch (err) {\n options.onError?.(err instanceof Error ? err : new Error(String(err)));\n res.status(401).json({ error: 'Invalid token' });\n }\n };\n}\n\nexport function fastifyPlugin(options: AuthonMiddlewareOptions) {\n const client = new AuthonBackend(options.secretKey, { apiUrl: options.apiUrl });\n\n return async (\n request: { headers: Record<string, string | string[] | undefined>; auth?: AuthonUser },\n reply: { code: (code: number) => { send: (body: unknown) => void } },\n ) => {\n const authHeader = request.headers['authorization'];\n const token = typeof authHeader === 'string' ? authHeader.replace('Bearer ', '') : null;\n\n if (!token) {\n reply.code(401).send({ error: 'Missing authorization header' });\n return;\n }\n\n try {\n request.auth = await client.verifyToken(token);\n } catch (err) {\n options.onError?.(err instanceof Error ? err : new Error(String(err)));\n reply.code(401).send({ error: 'Invalid token' });\n }\n };\n}\n"],"mappings":"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","names":[]}
|
package/dist/index.d.cts
CHANGED
|
@@ -22,22 +22,42 @@ declare class AuthonBackend {
|
|
|
22
22
|
users: {
|
|
23
23
|
list: (options?: ListOptions) => Promise<ListResult<AuthonUser>>;
|
|
24
24
|
get: (userId: string) => Promise<AuthonUser>;
|
|
25
|
+
getByExternalId: (externalId: string) => Promise<AuthonUser>;
|
|
25
26
|
create: (data: {
|
|
26
27
|
email: string;
|
|
27
28
|
password?: string;
|
|
28
29
|
displayName?: string;
|
|
30
|
+
externalId?: string;
|
|
31
|
+
provider?: string;
|
|
32
|
+
avatarUrl?: string;
|
|
33
|
+
phone?: string;
|
|
34
|
+
emailVerified?: boolean;
|
|
35
|
+
publicMetadata?: Record<string, unknown>;
|
|
36
|
+
privateMetadata?: Record<string, unknown>;
|
|
29
37
|
}) => Promise<AuthonUser>;
|
|
30
38
|
update: (userId: string, data: Partial<{
|
|
31
|
-
email: string;
|
|
32
39
|
displayName: string;
|
|
40
|
+
externalId: string;
|
|
41
|
+
avatarUrl: string;
|
|
42
|
+
phone: string;
|
|
43
|
+
emailVerified: boolean;
|
|
33
44
|
publicMetadata: Record<string, unknown>;
|
|
45
|
+
privateMetadata: Record<string, unknown>;
|
|
34
46
|
}>) => Promise<AuthonUser>;
|
|
35
47
|
delete: (userId: string) => Promise<void>;
|
|
36
48
|
ban: (userId: string, reason?: string) => Promise<AuthonUser>;
|
|
37
49
|
unban: (userId: string) => Promise<AuthonUser>;
|
|
38
50
|
};
|
|
39
51
|
webhooks: {
|
|
40
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Verify an Authon webhook signature.
|
|
54
|
+
* @param payload - Raw request body (string or Buffer)
|
|
55
|
+
* @param signature - Value of `X-Authon-Signature` header (format: `v1=<hex>`)
|
|
56
|
+
* @param timestamp - Value of `X-Authon-Timestamp` header (ISO 8601)
|
|
57
|
+
* @param secret - Your webhook signing secret
|
|
58
|
+
* @returns Parsed payload object
|
|
59
|
+
*/
|
|
60
|
+
verify: (payload: string | Buffer, signature: string, timestamp: string, secret: string) => Record<string, unknown>;
|
|
41
61
|
};
|
|
42
62
|
private request;
|
|
43
63
|
}
|
package/dist/index.d.ts
CHANGED
|
@@ -22,22 +22,42 @@ declare class AuthonBackend {
|
|
|
22
22
|
users: {
|
|
23
23
|
list: (options?: ListOptions) => Promise<ListResult<AuthonUser>>;
|
|
24
24
|
get: (userId: string) => Promise<AuthonUser>;
|
|
25
|
+
getByExternalId: (externalId: string) => Promise<AuthonUser>;
|
|
25
26
|
create: (data: {
|
|
26
27
|
email: string;
|
|
27
28
|
password?: string;
|
|
28
29
|
displayName?: string;
|
|
30
|
+
externalId?: string;
|
|
31
|
+
provider?: string;
|
|
32
|
+
avatarUrl?: string;
|
|
33
|
+
phone?: string;
|
|
34
|
+
emailVerified?: boolean;
|
|
35
|
+
publicMetadata?: Record<string, unknown>;
|
|
36
|
+
privateMetadata?: Record<string, unknown>;
|
|
29
37
|
}) => Promise<AuthonUser>;
|
|
30
38
|
update: (userId: string, data: Partial<{
|
|
31
|
-
email: string;
|
|
32
39
|
displayName: string;
|
|
40
|
+
externalId: string;
|
|
41
|
+
avatarUrl: string;
|
|
42
|
+
phone: string;
|
|
43
|
+
emailVerified: boolean;
|
|
33
44
|
publicMetadata: Record<string, unknown>;
|
|
45
|
+
privateMetadata: Record<string, unknown>;
|
|
34
46
|
}>) => Promise<AuthonUser>;
|
|
35
47
|
delete: (userId: string) => Promise<void>;
|
|
36
48
|
ban: (userId: string, reason?: string) => Promise<AuthonUser>;
|
|
37
49
|
unban: (userId: string) => Promise<AuthonUser>;
|
|
38
50
|
};
|
|
39
51
|
webhooks: {
|
|
40
|
-
|
|
52
|
+
/**
|
|
53
|
+
* Verify an Authon webhook signature.
|
|
54
|
+
* @param payload - Raw request body (string or Buffer)
|
|
55
|
+
* @param signature - Value of `X-Authon-Signature` header (format: `v1=<hex>`)
|
|
56
|
+
* @param timestamp - Value of `X-Authon-Timestamp` header (ISO 8601)
|
|
57
|
+
* @param secret - Your webhook signing secret
|
|
58
|
+
* @returns Parsed payload object
|
|
59
|
+
*/
|
|
60
|
+
verify: (payload: string | Buffer, signature: string, timestamp: string, secret: string) => Record<string, unknown>;
|
|
41
61
|
};
|
|
42
62
|
private request;
|
|
43
63
|
}
|
package/dist/index.js
CHANGED
|
@@ -19,32 +19,44 @@ var AuthonBackend = class {
|
|
|
19
19
|
if (options?.limit) params.set("limit", String(options.limit));
|
|
20
20
|
if (options?.search) params.set("search", options.search);
|
|
21
21
|
const qs = params.toString();
|
|
22
|
-
return this.request("GET", `/v1/users${qs ? `?${qs}` : ""}`);
|
|
22
|
+
return this.request("GET", `/v1/backend/users${qs ? `?${qs}` : ""}`);
|
|
23
23
|
},
|
|
24
24
|
get: (userId) => {
|
|
25
|
-
return this.request("GET", `/v1/users/${userId}`);
|
|
25
|
+
return this.request("GET", `/v1/backend/users/${userId}`);
|
|
26
|
+
},
|
|
27
|
+
getByExternalId: (externalId) => {
|
|
28
|
+
return this.request("GET", `/v1/backend/users/by-external-id/${externalId}`);
|
|
26
29
|
},
|
|
27
30
|
create: (data) => {
|
|
28
|
-
return this.request("POST", "/v1/users", data);
|
|
31
|
+
return this.request("POST", "/v1/backend/users", data);
|
|
29
32
|
},
|
|
30
33
|
update: (userId, data) => {
|
|
31
|
-
return this.request("PATCH", `/v1/users/${userId}`, data);
|
|
34
|
+
return this.request("PATCH", `/v1/backend/users/${userId}`, data);
|
|
32
35
|
},
|
|
33
36
|
delete: (userId) => {
|
|
34
|
-
return this.request("DELETE", `/v1/users/${userId}`);
|
|
37
|
+
return this.request("DELETE", `/v1/backend/users/${userId}`);
|
|
35
38
|
},
|
|
36
39
|
ban: (userId, reason) => {
|
|
37
|
-
return this.request("POST", `/v1/users/${userId}/ban`, { reason });
|
|
40
|
+
return this.request("POST", `/v1/backend/users/${userId}/ban`, { reason });
|
|
38
41
|
},
|
|
39
42
|
unban: (userId) => {
|
|
40
|
-
return this.request("POST", `/v1/users/${userId}/unban`);
|
|
43
|
+
return this.request("POST", `/v1/backend/users/${userId}/unban`);
|
|
41
44
|
}
|
|
42
45
|
};
|
|
43
46
|
webhooks = {
|
|
44
|
-
|
|
47
|
+
/**
|
|
48
|
+
* Verify an Authon webhook signature.
|
|
49
|
+
* @param payload - Raw request body (string or Buffer)
|
|
50
|
+
* @param signature - Value of `X-Authon-Signature` header (format: `v1=<hex>`)
|
|
51
|
+
* @param timestamp - Value of `X-Authon-Timestamp` header (ISO 8601)
|
|
52
|
+
* @param secret - Your webhook signing secret
|
|
53
|
+
* @returns Parsed payload object
|
|
54
|
+
*/
|
|
55
|
+
verify: (payload, signature, timestamp, secret) => {
|
|
45
56
|
const body = typeof payload === "string" ? payload : payload.toString("utf8");
|
|
46
|
-
const
|
|
47
|
-
const
|
|
57
|
+
const signedPayload = `${timestamp}.${body}`;
|
|
58
|
+
const expected = createHmac("sha256", secret).update(signedPayload).digest("hex");
|
|
59
|
+
const actual = signature.replace("v1=", "");
|
|
48
60
|
const expectedBuf = Buffer.from(expected, "hex");
|
|
49
61
|
const actualBuf = Buffer.from(actual, "hex");
|
|
50
62
|
if (expectedBuf.length !== actualBuf.length || !timingSafeEqual(expectedBuf, actualBuf)) {
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/authon.ts","../src/middleware.ts"],"sourcesContent":["import type { AuthonUser } from '@authon/shared';\nimport { createHmac, timingSafeEqual } from 'crypto';\n\ninterface AuthonBackendConfig {\n apiUrl?: string;\n}\n\ninterface ListOptions {\n page?: number;\n limit?: number;\n search?: string;\n}\n\ninterface ListResult<T> {\n data: T[];\n total: number;\n page: number;\n limit: number;\n}\n\nexport class AuthonBackend {\n private secretKey: string;\n private apiUrl: string;\n\n constructor(secretKey: string, config?: AuthonBackendConfig) {\n this.secretKey = secretKey;\n this.apiUrl = config?.apiUrl || 'https://api.authon.dev';\n }\n\n async verifyToken(accessToken: string): Promise<AuthonUser> {\n return this.request<AuthonUser>('GET', '/v1/auth/token/verify', undefined, {\n Authorization: `Bearer ${accessToken}`,\n });\n }\n\n users = {\n list: (options?: ListOptions): Promise<ListResult<AuthonUser>> => {\n const params = new URLSearchParams();\n if (options?.page) params.set('page', String(options.page));\n if (options?.limit) params.set('limit', String(options.limit));\n if (options?.search) params.set('search', options.search);\n const qs = params.toString();\n return this.request('GET', `/v1/users${qs ? `?${qs}` : ''}`);\n },\n\n get: (userId: string): Promise<AuthonUser> => {\n return this.request('GET', `/v1/users/${userId}`);\n },\n\n create: (data: {\n email: string;\n password?: string;\n displayName?: string;\n }): Promise<AuthonUser> => {\n return this.request('POST', '/v1/users', data);\n },\n\n update: (\n userId: string,\n data: Partial<{
|
|
1
|
+
{"version":3,"sources":["../src/authon.ts","../src/middleware.ts"],"sourcesContent":["import type { AuthonUser } from '@authon/shared';\nimport { createHmac, timingSafeEqual } from 'crypto';\n\ninterface AuthonBackendConfig {\n apiUrl?: string;\n}\n\ninterface ListOptions {\n page?: number;\n limit?: number;\n search?: string;\n}\n\ninterface ListResult<T> {\n data: T[];\n total: number;\n page: number;\n limit: number;\n}\n\nexport class AuthonBackend {\n private secretKey: string;\n private apiUrl: string;\n\n constructor(secretKey: string, config?: AuthonBackendConfig) {\n this.secretKey = secretKey;\n this.apiUrl = config?.apiUrl || 'https://api.authon.dev';\n }\n\n async verifyToken(accessToken: string): Promise<AuthonUser> {\n return this.request<AuthonUser>('GET', '/v1/auth/token/verify', undefined, {\n Authorization: `Bearer ${accessToken}`,\n });\n }\n\n users = {\n list: (options?: ListOptions): Promise<ListResult<AuthonUser>> => {\n const params = new URLSearchParams();\n if (options?.page) params.set('page', String(options.page));\n if (options?.limit) params.set('limit', String(options.limit));\n if (options?.search) params.set('search', options.search);\n const qs = params.toString();\n return this.request('GET', `/v1/backend/users${qs ? `?${qs}` : ''}`);\n },\n\n get: (userId: string): Promise<AuthonUser> => {\n return this.request('GET', `/v1/backend/users/${userId}`);\n },\n\n getByExternalId: (externalId: string): Promise<AuthonUser> => {\n return this.request('GET', `/v1/backend/users/by-external-id/${externalId}`);\n },\n\n create: (data: {\n email: string;\n password?: string;\n displayName?: string;\n externalId?: string;\n provider?: string;\n avatarUrl?: string;\n phone?: string;\n emailVerified?: boolean;\n publicMetadata?: Record<string, unknown>;\n privateMetadata?: Record<string, unknown>;\n }): Promise<AuthonUser> => {\n return this.request('POST', '/v1/backend/users', data);\n },\n\n update: (\n userId: string,\n data: Partial<{\n displayName: string;\n externalId: string;\n avatarUrl: string;\n phone: string;\n emailVerified: boolean;\n publicMetadata: Record<string, unknown>;\n privateMetadata: Record<string, unknown>;\n }>,\n ): Promise<AuthonUser> => {\n return this.request('PATCH', `/v1/backend/users/${userId}`, data);\n },\n\n delete: (userId: string): Promise<void> => {\n return this.request('DELETE', `/v1/backend/users/${userId}`);\n },\n\n ban: (userId: string, reason?: string): Promise<AuthonUser> => {\n return this.request('POST', `/v1/backend/users/${userId}/ban`, { reason });\n },\n\n unban: (userId: string): Promise<AuthonUser> => {\n return this.request('POST', `/v1/backend/users/${userId}/unban`);\n },\n };\n\n webhooks = {\n /**\n * Verify an Authon webhook signature.\n * @param payload - Raw request body (string or Buffer)\n * @param signature - Value of `X-Authon-Signature` header (format: `v1=<hex>`)\n * @param timestamp - Value of `X-Authon-Timestamp` header (ISO 8601)\n * @param secret - Your webhook signing secret\n * @returns Parsed payload object\n */\n verify: (\n payload: string | Buffer,\n signature: string,\n timestamp: string,\n secret: string,\n ): Record<string, unknown> => {\n const body = typeof payload === 'string' ? payload : payload.toString('utf8');\n const signedPayload = `${timestamp}.${body}`;\n const expected = createHmac('sha256', secret).update(signedPayload).digest('hex');\n const actual = signature.replace('v1=', '');\n\n const expectedBuf = Buffer.from(expected, 'hex');\n const actualBuf = Buffer.from(actual, 'hex');\n\n if (expectedBuf.length !== actualBuf.length || !timingSafeEqual(expectedBuf, actualBuf)) {\n throw new Error('Invalid webhook signature');\n }\n\n return JSON.parse(body);\n },\n };\n\n private async request<T>(\n method: string,\n path: string,\n body?: unknown,\n extraHeaders?: Record<string, string>,\n ): Promise<T> {\n const res = await fetch(`${this.apiUrl}${path}`, {\n method,\n headers: {\n 'Content-Type': 'application/json',\n 'x-api-key': this.secretKey,\n ...extraHeaders,\n },\n body: body ? JSON.stringify(body) : undefined,\n });\n\n if (!res.ok) {\n const text = await res.text();\n throw new Error(`Authon API error ${res.status}: ${text}`);\n }\n\n if (res.status === 204) return undefined as T;\n return res.json() as Promise<T>;\n }\n}\n","import type { AuthonUser } from '@authon/shared';\nimport { AuthonBackend } from './authon';\n\nexport interface AuthonMiddlewareOptions {\n secretKey: string;\n apiUrl?: string;\n onError?: (error: Error) => void;\n}\n\nexport function expressMiddleware(options: AuthonMiddlewareOptions) {\n const client = new AuthonBackend(options.secretKey, { apiUrl: options.apiUrl });\n\n return async (\n req: { headers: Record<string, string | string[] | undefined>; auth?: AuthonUser },\n res: { status: (code: number) => { json: (body: unknown) => void } },\n next: (err?: unknown) => void,\n ) => {\n const authHeader = req.headers['authorization'];\n const token = typeof authHeader === 'string' ? authHeader.replace('Bearer ', '') : null;\n\n if (!token) {\n res.status(401).json({ error: 'Missing authorization header' });\n return;\n }\n\n try {\n req.auth = await client.verifyToken(token);\n next();\n } catch (err) {\n options.onError?.(err instanceof Error ? err : new Error(String(err)));\n res.status(401).json({ error: 'Invalid token' });\n }\n };\n}\n\nexport function fastifyPlugin(options: AuthonMiddlewareOptions) {\n const client = new AuthonBackend(options.secretKey, { apiUrl: options.apiUrl });\n\n return async (\n request: { headers: Record<string, string | string[] | undefined>; auth?: AuthonUser },\n reply: { code: (code: number) => { send: (body: unknown) => void } },\n ) => {\n const authHeader = request.headers['authorization'];\n const token = typeof authHeader === 'string' ? authHeader.replace('Bearer ', '') : null;\n\n if (!token) {\n reply.code(401).send({ error: 'Missing authorization header' });\n return;\n }\n\n try {\n request.auth = await client.verifyToken(token);\n } catch (err) {\n options.onError?.(err instanceof Error ? err : new Error(String(err)));\n reply.code(401).send({ error: 'Invalid token' });\n }\n };\n}\n"],"mappings":"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","names":[]}
|