@oneunit/auth 2.0.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/ARCHITECTURE.md +465 -0
- package/CHANGELOG.md +214 -0
- package/LICENSE +21 -0
- package/README.md +647 -0
- package/dist/adapters.d.ts +51 -0
- package/dist/adapters.d.ts.map +1 -0
- package/dist/adapters.js +301 -0
- package/dist/adapters.js.map +1 -0
- package/dist/auth.d.ts +59 -0
- package/dist/auth.d.ts.map +1 -0
- package/dist/auth.js +560 -0
- package/dist/auth.js.map +1 -0
- package/dist/errors.d.ts +39 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +65 -0
- package/dist/errors.js.map +1 -0
- package/dist/index.d.ts +11 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +10 -0
- package/dist/index.js.map +1 -0
- package/dist/jwt.d.ts +11 -0
- package/dist/jwt.d.ts.map +1 -0
- package/dist/jwt.js +125 -0
- package/dist/jwt.js.map +1 -0
- package/dist/oauth.d.ts +31 -0
- package/dist/oauth.d.ts.map +1 -0
- package/dist/oauth.js +178 -0
- package/dist/oauth.js.map +1 -0
- package/dist/password.d.ts +5 -0
- package/dist/password.d.ts.map +1 -0
- package/dist/password.js +90 -0
- package/dist/password.js.map +1 -0
- package/dist/providers.d.ts +37 -0
- package/dist/providers.d.ts.map +1 -0
- package/dist/providers.js +471 -0
- package/dist/providers.js.map +1 -0
- package/dist/rbac.d.ts +40 -0
- package/dist/rbac.d.ts.map +1 -0
- package/dist/rbac.js +240 -0
- package/dist/rbac.js.map +1 -0
- package/dist/roles.d.ts +2 -0
- package/dist/roles.d.ts.map +1 -0
- package/dist/roles.js +2 -0
- package/dist/roles.js.map +1 -0
- package/dist/token.d.ts +2 -0
- package/dist/token.d.ts.map +1 -0
- package/dist/token.js +2 -0
- package/dist/token.js.map +1 -0
- package/dist/types.d.ts +383 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +2 -0
- package/dist/types.js.map +1 -0
- package/dist/utils.d.ts +35 -0
- package/dist/utils.d.ts.map +1 -0
- package/dist/utils.js +192 -0
- package/dist/utils.js.map +1 -0
- package/examples/express.ts +111 -0
- package/examples/fastify.ts +59 -0
- package/examples/oauth-social.ts +83 -0
- package/examples/standalone.ts +67 -0
- package/examples/uwebsockets.ts +143 -0
- package/package.json +86 -0
- package/src/adapters.ts +333 -0
- package/src/auth.ts +684 -0
- package/src/errors.ts +76 -0
- package/src/index.ts +124 -0
- package/src/jwt.ts +159 -0
- package/src/oauth.ts +226 -0
- package/src/password.ts +111 -0
- package/src/providers.ts +551 -0
- package/src/rbac.ts +285 -0
- package/src/roles.ts +1 -0
- package/src/token.ts +1 -0
- package/src/types.ts +432 -0
- package/src/utils.ts +231 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"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"}
|
package/dist/types.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":""}
|
package/dist/utils.d.ts
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* True when `value` is a TTL this library can interpret unambiguously. Values
|
|
3
|
+
* jsonwebtoken accepts but this library cannot (`"1y"`, `"2 hours"`, `"-5m"`)
|
|
4
|
+
* are rejected so the signed token and any locally computed expiry never diverge.
|
|
5
|
+
*/
|
|
6
|
+
export declare function isValidExpiresIn(value: string | number | undefined | null): boolean;
|
|
7
|
+
export declare function parseExpiresIn(value: string | number | undefined | null, fallbackSeconds?: number): number;
|
|
8
|
+
export declare function randomToken(bytes?: number): string;
|
|
9
|
+
export declare function randomState(bytes?: number): string;
|
|
10
|
+
export declare function sha256(value: unknown): string;
|
|
11
|
+
export declare function timingSafeEqualString(a: unknown, b: unknown): boolean;
|
|
12
|
+
export declare function assertNonEmptyString(value: unknown, name: string): asserts value is string;
|
|
13
|
+
export declare function isPlainObject(value: unknown): value is Record<string, unknown>;
|
|
14
|
+
export declare function unique<T>(values: T[]): T[];
|
|
15
|
+
export declare function toArray(value: unknown): unknown[];
|
|
16
|
+
export declare function pick<T extends Record<string, unknown>>(object: T, keys: Array<keyof T>): Partial<T>;
|
|
17
|
+
export declare function buildUrl(base: string, path: string, query?: Record<string, unknown>): string;
|
|
18
|
+
export declare function extractBearerToken(header: string | undefined | null): string | null;
|
|
19
|
+
export declare function parseCookieHeader(header: string | undefined | null): Record<string, string>;
|
|
20
|
+
export declare function parseQueryString(value: unknown): Record<string, string>;
|
|
21
|
+
export declare function getHeader(headers: Record<string, unknown> | {
|
|
22
|
+
get?(name: string): string | null;
|
|
23
|
+
} | undefined | null, name: string): string | undefined;
|
|
24
|
+
export interface JsonRequestOptions extends RequestInit {
|
|
25
|
+
timeout?: number;
|
|
26
|
+
}
|
|
27
|
+
export interface JsonResponse {
|
|
28
|
+
ok: boolean;
|
|
29
|
+
status: number;
|
|
30
|
+
body: unknown;
|
|
31
|
+
headers: Headers;
|
|
32
|
+
}
|
|
33
|
+
export declare function requestJson(url: string, options?: JsonRequestOptions): Promise<JsonResponse>;
|
|
34
|
+
export declare function formEncode(data: Record<string, unknown>): URLSearchParams;
|
|
35
|
+
//# sourceMappingURL=utils.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.d.ts","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"AAeA;;;;GAIG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,OAAO,CAQnF;AAED,wBAAgB,cAAc,CAAC,KAAK,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,GAAG,IAAI,EAAE,eAAe,SAAe,GAAG,MAAM,CAsBhH;AAED,wBAAgB,WAAW,CAAC,KAAK,SAAK,GAAG,MAAM,CAE9C;AAED,wBAAgB,WAAW,CAAC,KAAK,SAAK,GAAG,MAAM,CAE9C;AAED,wBAAgB,MAAM,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAE7C;AAED,wBAAgB,qBAAqB,CAAC,CAAC,EAAE,OAAO,EAAE,CAAC,EAAE,OAAO,GAAG,OAAO,CAOrE;AAED,wBAAgB,oBAAoB,CAAC,KAAK,EAAE,OAAO,EAAE,IAAI,EAAE,MAAM,GAAG,OAAO,CAAC,KAAK,IAAI,MAAM,CAI1F;AAED,wBAAgB,aAAa,CAAC,KAAK,EAAE,OAAO,GAAG,KAAK,IAAI,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,CAE9E;AAED,wBAAgB,MAAM,CAAC,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,GAAG,CAAC,EAAE,CAE1C;AAED,wBAAgB,OAAO,CAAC,KAAK,EAAE,OAAO,GAAG,OAAO,EAAE,CAKjD;AAED,wBAAgB,IAAI,CAAC,CAAC,SAAS,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,EAAE,MAAM,EAAE,CAAC,EAAE,IAAI,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,CAQnG;AAED,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,GAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAM,GAAG,MAAM,CAQhG;AAED,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,GAAG,IAAI,CAMnF;AAED,wBAAgB,iBAAiB,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,GAAG,IAAI,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAmB3F;AAED,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,OAAO,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAcvE;AAED,wBAAgB,SAAS,CACvB,OAAO,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG;IAAE,GAAG,CAAC,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,IAAI,CAAA;CAAE,GAAG,SAAS,GAAG,IAAI,EAC3F,IAAI,EAAE,MAAM,GACX,MAAM,GAAG,SAAS,CAcpB;AAED,MAAM,WAAW,kBAAmB,SAAQ,WAAW;IACrD,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED,MAAM,WAAW,YAAY;IAC3B,EAAE,EAAE,OAAO,CAAC;IACZ,MAAM,EAAE,MAAM,CAAC;IACf,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,OAAO,CAAC;CAClB;AAED,wBAAsB,WAAW,CAAC,GAAG,EAAE,MAAM,EAAE,OAAO,GAAE,kBAAuB,GAAG,OAAO,CAAC,YAAY,CAAC,CA6BtG;AAED,wBAAgB,UAAU,CAAC,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,eAAe,CAQzE"}
|
package/dist/utils.js
ADDED
|
@@ -0,0 +1,192 @@
|
|
|
1
|
+
import { randomBytes, createHash, timingSafeEqual } from "node:crypto";
|
|
2
|
+
import { ValidationError } from "./errors.js";
|
|
3
|
+
const UNIT_SECONDS = Object.freeze({
|
|
4
|
+
s: 1,
|
|
5
|
+
m: 60,
|
|
6
|
+
h: 60 * 60,
|
|
7
|
+
d: 60 * 60 * 24,
|
|
8
|
+
w: 60 * 60 * 24 * 7,
|
|
9
|
+
});
|
|
10
|
+
const EXPIRES_IN_PATTERN = /^(\d+)\s*([smhdw])$/i;
|
|
11
|
+
/**
|
|
12
|
+
* True when `value` is a TTL this library can interpret unambiguously. Values
|
|
13
|
+
* jsonwebtoken accepts but this library cannot (`"1y"`, `"2 hours"`, `"-5m"`)
|
|
14
|
+
* are rejected so the signed token and any locally computed expiry never diverge.
|
|
15
|
+
*/
|
|
16
|
+
export function isValidExpiresIn(value) {
|
|
17
|
+
if (typeof value === "number") {
|
|
18
|
+
return Number.isFinite(value);
|
|
19
|
+
}
|
|
20
|
+
if (typeof value !== "string") {
|
|
21
|
+
return false;
|
|
22
|
+
}
|
|
23
|
+
return EXPIRES_IN_PATTERN.test(value.trim());
|
|
24
|
+
}
|
|
25
|
+
export function parseExpiresIn(value, fallbackSeconds = 60 * 60 * 24) {
|
|
26
|
+
if (typeof value === "number" && Number.isFinite(value)) {
|
|
27
|
+
return Math.max(0, Math.trunc(value));
|
|
28
|
+
}
|
|
29
|
+
if (typeof value !== "string") {
|
|
30
|
+
return fallbackSeconds;
|
|
31
|
+
}
|
|
32
|
+
const trimmed = value.trim();
|
|
33
|
+
if (!trimmed) {
|
|
34
|
+
return fallbackSeconds;
|
|
35
|
+
}
|
|
36
|
+
const match = trimmed.match(EXPIRES_IN_PATTERN);
|
|
37
|
+
if (!match) {
|
|
38
|
+
return fallbackSeconds;
|
|
39
|
+
}
|
|
40
|
+
const amount = Number.parseInt(match[1], 10);
|
|
41
|
+
const unit = match[2].toLowerCase();
|
|
42
|
+
return amount * UNIT_SECONDS[unit];
|
|
43
|
+
}
|
|
44
|
+
export function randomToken(bytes = 32) {
|
|
45
|
+
return randomBytes(bytes).toString("hex");
|
|
46
|
+
}
|
|
47
|
+
export function randomState(bytes = 16) {
|
|
48
|
+
return randomBytes(bytes).toString("base64url");
|
|
49
|
+
}
|
|
50
|
+
export function sha256(value) {
|
|
51
|
+
return createHash("sha256").update(String(value)).digest("hex");
|
|
52
|
+
}
|
|
53
|
+
export function timingSafeEqualString(a, b) {
|
|
54
|
+
const left = Buffer.from(String(a ?? ""), "utf8");
|
|
55
|
+
const right = Buffer.from(String(b ?? ""), "utf8");
|
|
56
|
+
if (left.length !== right.length) {
|
|
57
|
+
return false;
|
|
58
|
+
}
|
|
59
|
+
return timingSafeEqual(left, right);
|
|
60
|
+
}
|
|
61
|
+
export function assertNonEmptyString(value, name) {
|
|
62
|
+
if (typeof value !== "string" || value.length === 0) {
|
|
63
|
+
throw new ValidationError(`${name} must be a non-empty string`);
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
export function isPlainObject(value) {
|
|
67
|
+
return value !== null && typeof value === "object" && !Array.isArray(value);
|
|
68
|
+
}
|
|
69
|
+
export function unique(values) {
|
|
70
|
+
return [...new Set(values.filter((item) => item !== undefined && item !== null && item !== ""))];
|
|
71
|
+
}
|
|
72
|
+
export function toArray(value) {
|
|
73
|
+
if (value === undefined || value === null) {
|
|
74
|
+
return [];
|
|
75
|
+
}
|
|
76
|
+
return Array.isArray(value) ? value.flat(Infinity) : [value];
|
|
77
|
+
}
|
|
78
|
+
export function pick(object, keys) {
|
|
79
|
+
const result = {};
|
|
80
|
+
for (const key of keys) {
|
|
81
|
+
if (object[key] !== undefined) {
|
|
82
|
+
result[key] = object[key];
|
|
83
|
+
}
|
|
84
|
+
}
|
|
85
|
+
return result;
|
|
86
|
+
}
|
|
87
|
+
export function buildUrl(base, path, query = {}) {
|
|
88
|
+
const url = new URL(path, base);
|
|
89
|
+
for (const [key, value] of Object.entries(query)) {
|
|
90
|
+
if (value !== undefined && value !== null && value !== "") {
|
|
91
|
+
url.searchParams.set(key, String(value));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
return url.toString();
|
|
95
|
+
}
|
|
96
|
+
export function extractBearerToken(header) {
|
|
97
|
+
if (typeof header !== "string") {
|
|
98
|
+
return null;
|
|
99
|
+
}
|
|
100
|
+
const match = header.match(/^Bearer\s+(.+)$/i);
|
|
101
|
+
return match ? match[1].trim() : null;
|
|
102
|
+
}
|
|
103
|
+
export function parseCookieHeader(header) {
|
|
104
|
+
if (typeof header !== "string" || header.length === 0) {
|
|
105
|
+
return {};
|
|
106
|
+
}
|
|
107
|
+
const cookies = {};
|
|
108
|
+
for (const part of header.split(";")) {
|
|
109
|
+
const index = part.indexOf("=");
|
|
110
|
+
if (index === -1) {
|
|
111
|
+
continue;
|
|
112
|
+
}
|
|
113
|
+
const key = part.slice(0, index).trim();
|
|
114
|
+
const value = part.slice(index + 1).trim();
|
|
115
|
+
try {
|
|
116
|
+
cookies[key] = decodeURIComponent(value);
|
|
117
|
+
}
|
|
118
|
+
catch {
|
|
119
|
+
cookies[key] = value;
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
return cookies;
|
|
123
|
+
}
|
|
124
|
+
export function parseQueryString(value) {
|
|
125
|
+
if (!value) {
|
|
126
|
+
return {};
|
|
127
|
+
}
|
|
128
|
+
if (typeof value === "object" && !Array.isArray(value)) {
|
|
129
|
+
const result = {};
|
|
130
|
+
for (const [key, item] of Object.entries(value)) {
|
|
131
|
+
if (item !== undefined && item !== null) {
|
|
132
|
+
result[key] = String(Array.isArray(item) ? item[0] : item);
|
|
133
|
+
}
|
|
134
|
+
}
|
|
135
|
+
return result;
|
|
136
|
+
}
|
|
137
|
+
return Object.fromEntries(new URLSearchParams(String(value)));
|
|
138
|
+
}
|
|
139
|
+
export function getHeader(headers, name) {
|
|
140
|
+
if (!headers) {
|
|
141
|
+
return undefined;
|
|
142
|
+
}
|
|
143
|
+
if (typeof headers.get === "function") {
|
|
144
|
+
const getter = headers;
|
|
145
|
+
return getter.get(name) ?? getter.get(name.toLowerCase()) ?? undefined;
|
|
146
|
+
}
|
|
147
|
+
const map = headers;
|
|
148
|
+
const value = map[name] ?? map[name.toLowerCase()] ?? map[name.toUpperCase()];
|
|
149
|
+
if (Array.isArray(value)) {
|
|
150
|
+
return value[0] === undefined ? undefined : String(value[0]);
|
|
151
|
+
}
|
|
152
|
+
return value === undefined || value === null ? undefined : String(value);
|
|
153
|
+
}
|
|
154
|
+
export async function requestJson(url, options = {}) {
|
|
155
|
+
const { timeout = 15000, ...init } = options;
|
|
156
|
+
const controller = new AbortController();
|
|
157
|
+
const timer = setTimeout(() => controller.abort(), timeout);
|
|
158
|
+
try {
|
|
159
|
+
const response = await fetch(url, {
|
|
160
|
+
...init,
|
|
161
|
+
signal: controller.signal,
|
|
162
|
+
headers: {
|
|
163
|
+
accept: "application/json",
|
|
164
|
+
...(init.headers ?? {}),
|
|
165
|
+
},
|
|
166
|
+
});
|
|
167
|
+
const text = await response.text();
|
|
168
|
+
let body = null;
|
|
169
|
+
if (text) {
|
|
170
|
+
try {
|
|
171
|
+
body = JSON.parse(text);
|
|
172
|
+
}
|
|
173
|
+
catch {
|
|
174
|
+
body = text;
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
return { ok: response.ok, status: response.status, body, headers: response.headers };
|
|
178
|
+
}
|
|
179
|
+
finally {
|
|
180
|
+
clearTimeout(timer);
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
export function formEncode(data) {
|
|
184
|
+
const params = new URLSearchParams();
|
|
185
|
+
for (const [key, value] of Object.entries(data)) {
|
|
186
|
+
if (value !== undefined && value !== null) {
|
|
187
|
+
params.set(key, String(value));
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
return params;
|
|
191
|
+
}
|
|
192
|
+
//# sourceMappingURL=utils.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"utils.js","sourceRoot":"","sources":["../src/utils.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
import { createAuth, expressAdapter } from "@oneunit/auth";
|
|
2
|
+
import type { ExpressRequestLike, ExpressResponseLike, UserRecord } from "@oneunit/auth";
|
|
3
|
+
|
|
4
|
+
const auth = createAuth({
|
|
5
|
+
secret: process.env.AUTH_SECRET ?? "change-me-in-production",
|
|
6
|
+
rbac: {
|
|
7
|
+
roles: {
|
|
8
|
+
user: { permissions: ["me.read"] },
|
|
9
|
+
admin: { inherits: "user", permissions: ["stats.read"] },
|
|
10
|
+
},
|
|
11
|
+
},
|
|
12
|
+
oauth: {
|
|
13
|
+
redirectUri: "http://localhost:3000/auth/google/callback",
|
|
14
|
+
providers: {
|
|
15
|
+
google: {
|
|
16
|
+
clientId: process.env.GOOGLE_CLIENT_ID,
|
|
17
|
+
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
|
|
18
|
+
},
|
|
19
|
+
github: {
|
|
20
|
+
clientId: process.env.GITHUB_CLIENT_ID,
|
|
21
|
+
clientSecret: process.env.GITHUB_CLIENT_SECRET,
|
|
22
|
+
redirectUri: "http://localhost:3000/auth/github/callback",
|
|
23
|
+
},
|
|
24
|
+
},
|
|
25
|
+
},
|
|
26
|
+
});
|
|
27
|
+
|
|
28
|
+
const { authenticate, requirePermission } = expressAdapter(auth);
|
|
29
|
+
|
|
30
|
+
interface ExampleRequest extends ExpressRequestLike {
|
|
31
|
+
body?: { id?: string | number; email?: string; password?: string };
|
|
32
|
+
params?: { provider?: string };
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
interface ExampleResponse extends ExpressResponseLike {
|
|
36
|
+
json?(body: unknown): unknown;
|
|
37
|
+
redirect?(url: unknown): unknown;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
type ExampleHandler = (
|
|
41
|
+
req: ExampleRequest,
|
|
42
|
+
res: ExampleResponse,
|
|
43
|
+
next?: (error?: unknown) => void,
|
|
44
|
+
) => unknown;
|
|
45
|
+
|
|
46
|
+
interface ExampleApp {
|
|
47
|
+
post(path: string, handler: ExampleHandler): unknown;
|
|
48
|
+
get(path: string, ...handlers: ExampleHandler[]): unknown;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Stands in for your database lookup. Roles come from the store, never from
|
|
53
|
+
* the request body: `auth.login()` signs whatever record it is given, so
|
|
54
|
+
* forwarding `req.body.roles` would let the caller choose their own grants.
|
|
55
|
+
*/
|
|
56
|
+
async function findUserByEmail(email: string): Promise<UserRecord> {
|
|
57
|
+
return { id: "user_01", email, name: "Ada", roles: ["user"] };
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export function registerAuthRoutes(app: ExampleApp): void {
|
|
61
|
+
app.post("/auth/login", async (req, res) => {
|
|
62
|
+
const user = await findUserByEmail(String(req.body?.email ?? ""));
|
|
63
|
+
if (!user) {
|
|
64
|
+
res.json?.({ error: "INVALID_CREDENTIALS", message: "Unknown user" });
|
|
65
|
+
return;
|
|
66
|
+
}
|
|
67
|
+
res.json?.(await auth.login(user));
|
|
68
|
+
});
|
|
69
|
+
|
|
70
|
+
app.post("/auth/refresh", async (req, res) => {
|
|
71
|
+
const refreshToken = (req.body as { refreshToken?: string } | undefined)?.refreshToken;
|
|
72
|
+
if (!refreshToken) {
|
|
73
|
+
res.json?.({ error: "UNAUTHORIZED", message: "refreshToken is required" });
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
// Rotation: the presented token is consumed and cannot be reused. A second
|
|
77
|
+
// call with the same token fails with UNAUTHORIZED.
|
|
78
|
+
res.json?.(await auth.refresh(refreshToken));
|
|
79
|
+
});
|
|
80
|
+
|
|
81
|
+
app.post("/auth/logout", async (req, res) => {
|
|
82
|
+
const refreshToken = (req.body as { refreshToken?: string } | undefined)?.refreshToken;
|
|
83
|
+
res.json?.({ revoked: await auth.logout(refreshToken) });
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
app.get("/auth/:provider", async (req, res) => {
|
|
87
|
+
const { url } = await auth.getAuthorizationUrl(String(req.params?.provider));
|
|
88
|
+
res.redirect?.(url);
|
|
89
|
+
});
|
|
90
|
+
|
|
91
|
+
app.get("/auth/:provider/callback", async (req, res) => {
|
|
92
|
+
const session = await auth.loginWithOAuth(
|
|
93
|
+
String(req.params?.provider),
|
|
94
|
+
(req.query ?? {}) as Record<string, string>,
|
|
95
|
+
);
|
|
96
|
+
res.json?.(session);
|
|
97
|
+
});
|
|
98
|
+
|
|
99
|
+
// `optional: true` lets anonymous callers through; request.user is null.
|
|
100
|
+
app.get("/feed", authenticate({ optional: true }), (req, res) => {
|
|
101
|
+
res.json?.({ user: req.user });
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
app.get("/me", authenticate(), (req, res) => {
|
|
105
|
+
res.json?.({ user: req.user });
|
|
106
|
+
});
|
|
107
|
+
|
|
108
|
+
app.get("/stats", authenticate(), requirePermission("stats.read"), (req, res) => {
|
|
109
|
+
res.json?.({ ok: true, userId: req.user?.userId });
|
|
110
|
+
});
|
|
111
|
+
}
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import { createAuth, fastifyAdapter } from "@oneunit/auth";
|
|
2
|
+
import type { FastifyLike, FastifyRequestLike, UserRecord } from "@oneunit/auth";
|
|
3
|
+
|
|
4
|
+
interface ExampleFastify extends FastifyLike {
|
|
5
|
+
register(plugin: unknown, options?: unknown): Promise<void> | void;
|
|
6
|
+
post(path: string, handler: (request: FastifyRequestLike) => unknown): unknown;
|
|
7
|
+
get(
|
|
8
|
+
path: string,
|
|
9
|
+
options: { preHandler: unknown[] },
|
|
10
|
+
handler: (request: FastifyRequestLike) => unknown,
|
|
11
|
+
): unknown;
|
|
12
|
+
authenticate(options?: { optional?: boolean }): unknown;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
/** Stands in for your database lookup; roles are never read from the body. */
|
|
16
|
+
async function findUserByEmail(email: string): Promise<UserRecord> {
|
|
17
|
+
return { id: "user_01", email, name: "Ada", roles: ["user"] };
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
export async function registerFastifyAuth(fastify: ExampleFastify): Promise<void> {
|
|
21
|
+
const auth = createAuth({
|
|
22
|
+
secret: process.env.AUTH_SECRET ?? "change-me-in-production",
|
|
23
|
+
rbac: {
|
|
24
|
+
roles: {
|
|
25
|
+
user: { permissions: ["me.read"] },
|
|
26
|
+
admin: { inherits: "user", permissions: ["stats.read"] },
|
|
27
|
+
},
|
|
28
|
+
},
|
|
29
|
+
});
|
|
30
|
+
|
|
31
|
+
// `optional: true` here is inherited by every route, so a route that does not
|
|
32
|
+
// pass its own options still lets anonymous callers through.
|
|
33
|
+
await fastify.register(fastifyAdapter(auth), { optional: true });
|
|
34
|
+
|
|
35
|
+
fastify.post("/auth/login", async (request) => {
|
|
36
|
+
const body = (request.body ?? {}) as { email?: string };
|
|
37
|
+
const user = await findUserByEmail(String(body.email ?? ""));
|
|
38
|
+
return auth.login(user);
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
fastify.post("/auth/refresh", async (request) => {
|
|
42
|
+
const body = (request.body ?? {}) as { refreshToken?: string };
|
|
43
|
+
// Rotation: the presented token is consumed and cannot be replayed.
|
|
44
|
+
return auth.refresh(String(body.refreshToken ?? ""));
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
// Optional at the plugin level, so this route must opt back in explicitly.
|
|
48
|
+
fastify.get(
|
|
49
|
+
"/me",
|
|
50
|
+
{ preHandler: [fastify.authenticate({ optional: false })] },
|
|
51
|
+
async (request) => ({ user: request.user }),
|
|
52
|
+
);
|
|
53
|
+
|
|
54
|
+
fastify.get(
|
|
55
|
+
"/feed",
|
|
56
|
+
{ preHandler: [fastify.authenticate()] },
|
|
57
|
+
async (request) => ({ user: request.user }),
|
|
58
|
+
);
|
|
59
|
+
}
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
import { createAuth } from "@oneunit/auth";
|
|
2
|
+
|
|
3
|
+
const auth = createAuth({
|
|
4
|
+
secret: process.env.AUTH_SECRET ?? "change-me-in-production",
|
|
5
|
+
redirectUri: "http://localhost:3000/auth/callback",
|
|
6
|
+
// Roles are assigned from your rules, not from the provider profile. Without
|
|
7
|
+
// a defaultRole and no roles option, every social user signs in with none.
|
|
8
|
+
rbac: {
|
|
9
|
+
defaultRole: "member",
|
|
10
|
+
roles: {
|
|
11
|
+
member: { permissions: ["profile.read"] },
|
|
12
|
+
admin: { inherits: "member", permissions: ["user.manage"] },
|
|
13
|
+
},
|
|
14
|
+
},
|
|
15
|
+
providers: {
|
|
16
|
+
// Public clients should set `pkce: true`. State alone is not enough to bind
|
|
17
|
+
// the callback to the browser that started the flow.
|
|
18
|
+
google: {
|
|
19
|
+
clientId: process.env.GOOGLE_CLIENT_ID,
|
|
20
|
+
clientSecret: process.env.GOOGLE_CLIENT_SECRET,
|
|
21
|
+
redirectUri: "http://localhost:3000/auth/google/callback",
|
|
22
|
+
pkce: true,
|
|
23
|
+
},
|
|
24
|
+
github: {
|
|
25
|
+
clientId: process.env.GITHUB_CLIENT_ID,
|
|
26
|
+
clientSecret: process.env.GITHUB_CLIENT_SECRET,
|
|
27
|
+
redirectUri: "http://localhost:3000/auth/github/callback",
|
|
28
|
+
},
|
|
29
|
+
instagram: {
|
|
30
|
+
clientId: process.env.INSTAGRAM_CLIENT_ID,
|
|
31
|
+
clientSecret: process.env.INSTAGRAM_CLIENT_SECRET,
|
|
32
|
+
redirectUri: "http://localhost:3000/auth/instagram/callback",
|
|
33
|
+
},
|
|
34
|
+
discord: {
|
|
35
|
+
clientId: process.env.DISCORD_CLIENT_ID,
|
|
36
|
+
clientSecret: process.env.DISCORD_CLIENT_SECRET,
|
|
37
|
+
redirectUri: "http://localhost:3000/auth/discord/callback",
|
|
38
|
+
},
|
|
39
|
+
twitter: {
|
|
40
|
+
clientId: process.env.TWITTER_CLIENT_ID,
|
|
41
|
+
clientSecret: process.env.TWITTER_CLIENT_SECRET,
|
|
42
|
+
redirectUri: "http://localhost:3000/auth/twitter/callback",
|
|
43
|
+
},
|
|
44
|
+
facebook: {
|
|
45
|
+
clientId: process.env.FACEBOOK_CLIENT_ID,
|
|
46
|
+
clientSecret: process.env.FACEBOOK_CLIENT_SECRET,
|
|
47
|
+
redirectUri: "http://localhost:3000/auth/facebook/callback",
|
|
48
|
+
},
|
|
49
|
+
apple: {
|
|
50
|
+
clientId: process.env.APPLE_CLIENT_ID,
|
|
51
|
+
clientSecret: process.env.APPLE_CLIENT_SECRET,
|
|
52
|
+
redirectUri: "http://localhost:3000/auth/apple/callback",
|
|
53
|
+
},
|
|
54
|
+
},
|
|
55
|
+
});
|
|
56
|
+
|
|
57
|
+
// Building the authorization URL requires a real client id. Provider
|
|
58
|
+
// configuration is validated lazily, so nothing above throws until this call.
|
|
59
|
+
if (!process.env.GOOGLE_CLIENT_ID) {
|
|
60
|
+
console.log("Set GOOGLE_CLIENT_ID and GOOGLE_CLIENT_SECRET to run this example.");
|
|
61
|
+
console.log("Provider config is validated at authorize() time, not at createAuth() time.");
|
|
62
|
+
process.exit(0);
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
const { url, state, codeVerifier } = await auth.getAuthorizationUrl("google");
|
|
66
|
+
console.log("Redirect users to:", url);
|
|
67
|
+
console.log("Store this state in a cookie or session:", state);
|
|
68
|
+
if (codeVerifier) {
|
|
69
|
+
console.log("Keep the PKCE verifier for the callback:", codeVerifier);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
// The state store is in-memory by default, so it works for a single instance.
|
|
73
|
+
// Behind more than one instance, supply a Redis- or session-backed StateStore.
|
|
74
|
+
|
|
75
|
+
const fakeCallbackQuery = { code: "AUTH_CODE_FROM_PROVIDER", state };
|
|
76
|
+
console.log("On callback, exchange the code with auth.loginWithOAuth('google', query)");
|
|
77
|
+
console.log("State is single-use: a replayed callback throws OAuthError.");
|
|
78
|
+
console.log(fakeCallbackQuery);
|
|
79
|
+
|
|
80
|
+
// With a userStore providing findByProvider / findByEmail / createFromProvider,
|
|
81
|
+
// loginWithOAuth links the social account to an existing user instead of
|
|
82
|
+
// creating a duplicate for every provider.
|
|
83
|
+
|
|
@@ -0,0 +1,67 @@
|
|
|
1
|
+
import { createAuth, encode, decode } from "@oneunit/auth";
|
|
2
|
+
|
|
3
|
+
const auth = createAuth({
|
|
4
|
+
secret: process.env.AUTH_SECRET ?? "change-me-in-production",
|
|
5
|
+
issuer: "example-app",
|
|
6
|
+
accessTokenTtl: "15m",
|
|
7
|
+
refreshTokenTtl: "7d",
|
|
8
|
+
rbac: {
|
|
9
|
+
defaultRole: "member",
|
|
10
|
+
roles: {
|
|
11
|
+
member: { permissions: ["profile.read"] },
|
|
12
|
+
billing: { permissions: ["invoice.read", "invoice.pay"] },
|
|
13
|
+
admin: { inherits: ["member", "billing"], permissions: ["user.manage"] },
|
|
14
|
+
// `**` spans any depth; `*` stays within one segment.
|
|
15
|
+
reporter: { permissions: ["ticket.*", "audit.**"] },
|
|
16
|
+
},
|
|
17
|
+
},
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
const session = await auth.login({
|
|
21
|
+
id: "user_01",
|
|
22
|
+
email: "ada@example.com",
|
|
23
|
+
name: "Ada",
|
|
24
|
+
roles: ["admin"],
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
console.log("access token ", session.accessToken);
|
|
28
|
+
console.log("refresh token", session.refreshToken);
|
|
29
|
+
console.log("permissions ", session.payload.permissions);
|
|
30
|
+
|
|
31
|
+
const claims = await auth.verify(session.accessToken);
|
|
32
|
+
console.log("verified subject", claims.sub);
|
|
33
|
+
|
|
34
|
+
// A refresh token is not an access token, even though both are signed with the
|
|
35
|
+
// same secret and differ only by the `typ` claim.
|
|
36
|
+
try {
|
|
37
|
+
await auth.verify(session.refreshToken!);
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.log("refresh token rejected by verify():", (error as Error).message);
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
// Rotation consumes the presented token. A second attempt fails.
|
|
43
|
+
const rotated = await auth.refresh(session.refreshToken!);
|
|
44
|
+
console.log("rotated refresh token differs:", rotated.refreshToken !== session.refreshToken);
|
|
45
|
+
try {
|
|
46
|
+
await auth.refresh(session.refreshToken!);
|
|
47
|
+
} catch (error) {
|
|
48
|
+
console.log("replayed refresh token rejected:", (error as Error).message);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
// Wildcard matching.
|
|
52
|
+
const reporter = { roles: ["reporter"] };
|
|
53
|
+
console.log("reporter can read ticket.42: ", auth.can(reporter, "ticket.42"));
|
|
54
|
+
console.log("reporter can read audit.a.b: ", auth.can(reporter, "audit.a.b"));
|
|
55
|
+
console.log("reporter can read audit: ", auth.can(reporter, "audit"));
|
|
56
|
+
|
|
57
|
+
const raw = encode({ job: "export" }, auth.secret, { expiresIn: "5m" });
|
|
58
|
+
console.log("ad-hoc token", decode(raw, auth.secret).job);
|
|
59
|
+
|
|
60
|
+
// An unparsable TTL throws instead of silently defaulting to 24 hours.
|
|
61
|
+
try {
|
|
62
|
+
encode({ job: "export" }, auth.secret, { expiresIn: "1y" });
|
|
63
|
+
} catch (error) {
|
|
64
|
+
console.log("invalid expiresIn rejected:", (error as Error).message);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
console.log("can manage users?", auth.can(session.payload, "user.manage"));
|