@tonycodes/auth-express 1.1.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/dist/index.d.ts +82 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +448 -0
- package/dist/index.js.map +1 -0
- package/package.json +52 -0
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import type { RequestHandler } from 'express';
|
|
3
|
+
export interface AuthConfig {
|
|
4
|
+
/** Client ID for this app (e.g., "rag-platform") */
|
|
5
|
+
clientId: string;
|
|
6
|
+
/** Client secret for token exchange (plaintext, NOT the hash) */
|
|
7
|
+
clientSecret: string;
|
|
8
|
+
/** Auth service URL. Defaults to https://auth.tony.codes */
|
|
9
|
+
authUrl?: string;
|
|
10
|
+
/**
|
|
11
|
+
* Cookie domain for refresh tokens.
|
|
12
|
+
* If not specified, auto-derived from request hostname:
|
|
13
|
+
* - *.tony.codes → .tony.codes (shared SSO)
|
|
14
|
+
* - myapp.test → .myapp.test
|
|
15
|
+
* - api.myapp.test → .myapp.test
|
|
16
|
+
*/
|
|
17
|
+
cookieDomain?: string;
|
|
18
|
+
/** Frontend app URL — required when API and frontend are on different hosts (e.g., api.autopilot.test vs autopilot.test) */
|
|
19
|
+
appUrl?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface AuthUser {
|
|
22
|
+
userId: string;
|
|
23
|
+
email: string;
|
|
24
|
+
name: string | null;
|
|
25
|
+
avatarUrl: string | null;
|
|
26
|
+
orgId: string | null;
|
|
27
|
+
orgName: string | null;
|
|
28
|
+
orgSlug: string | null;
|
|
29
|
+
orgRole: string | null;
|
|
30
|
+
isSuperAdmin: boolean;
|
|
31
|
+
}
|
|
32
|
+
declare global {
|
|
33
|
+
namespace Express {
|
|
34
|
+
interface Request {
|
|
35
|
+
auth?: AuthUser;
|
|
36
|
+
apiKey?: {
|
|
37
|
+
id: string;
|
|
38
|
+
name: string;
|
|
39
|
+
scopes: string[];
|
|
40
|
+
};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
}
|
|
44
|
+
export declare function createAuthMiddleware(config: AuthConfig): {
|
|
45
|
+
middleware: () => RequestHandler;
|
|
46
|
+
requireOrg: () => RequestHandler;
|
|
47
|
+
requireSuperAdmin: () => RequestHandler;
|
|
48
|
+
requireOrgRole: (...roles: string[]) => RequestHandler;
|
|
49
|
+
requireScope: (...scopes: string[]) => RequestHandler;
|
|
50
|
+
callbackHandler: () => RequestHandler;
|
|
51
|
+
refreshProxy: () => RequestHandler;
|
|
52
|
+
switchOrgProxy: () => RequestHandler;
|
|
53
|
+
logoutProxy: () => RequestHandler;
|
|
54
|
+
routes: () => Router;
|
|
55
|
+
config: {
|
|
56
|
+
authUrl: string;
|
|
57
|
+
clientId: string;
|
|
58
|
+
};
|
|
59
|
+
};
|
|
60
|
+
interface CallbackPageConfig {
|
|
61
|
+
/** Client ID for token exchange */
|
|
62
|
+
clientId: string;
|
|
63
|
+
/** Client secret for token exchange */
|
|
64
|
+
clientSecret: string;
|
|
65
|
+
/** Auth service URL. Defaults to https://auth.tony.codes */
|
|
66
|
+
authUrl?: string;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Standalone callback handler for hosted login page mode.
|
|
70
|
+
* Exchanges the authorization code for tokens, sets cookies, and redirects.
|
|
71
|
+
*
|
|
72
|
+
* Use this when you don't need the full SDK — just redirect to /authorize
|
|
73
|
+
* and mount this single route:
|
|
74
|
+
*
|
|
75
|
+
* app.get('/auth/callback', createCallbackPage({
|
|
76
|
+
* clientId: 'my-app',
|
|
77
|
+
* clientSecret: process.env.AUTH_SECRET!,
|
|
78
|
+
* }));
|
|
79
|
+
*/
|
|
80
|
+
export declare function createCallbackPage(config: CallbackPageConfig): RequestHandler;
|
|
81
|
+
export {};
|
|
82
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AACjC,OAAO,KAAK,EAAmC,cAAc,EAAE,MAAM,SAAS,CAAC;AAK/E,MAAM,WAAW,UAAU;IACzB,oDAAoD;IACpD,QAAQ,EAAE,MAAM,CAAC;IACjB,iEAAiE;IACjE,YAAY,EAAE,MAAM,CAAC;IACrB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB;;;;;;OAMG;IACH,YAAY,CAAC,EAAE,MAAM,CAAC;IACtB,4HAA4H;IAC5H,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB;AAgCD,MAAM,WAAW,QAAQ;IACvB,MAAM,EAAE,MAAM,CAAC;IACf,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,GAAG,IAAI,CAAC;IACpB,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;IACzB,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACrB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,OAAO,EAAE,MAAM,GAAG,IAAI,CAAC;IACvB,YAAY,EAAE,OAAO,CAAC;CACvB;AAGD,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO,CAAC;QAChB,UAAU,OAAO;YACf,IAAI,CAAC,EAAE,QAAQ,CAAC;YAChB,MAAM,CAAC,EAAE;gBACP,EAAE,EAAE,MAAM,CAAC;gBACX,IAAI,EAAE,MAAM,CAAC;gBACb,MAAM,EAAE,MAAM,EAAE,CAAC;aAClB,CAAC;SACH;KACF;CACF;AAoCD,wBAAgB,oBAAoB,CAAC,MAAM,EAAE,UAAU;sBAuB9B,cAAc;sBAkCd,cAAc;6BA2BP,cAAc;+BA0BV,MAAM,EAAE,KAAG,cAAc;8BAiB1B,MAAM,EAAE,KAAG,cAAc;2BAkB9B,cAAc;wBAiEjB,cAAc;0BAiDZ,cAAc;uBAmDjB,cAAc;kBAgCnB,MAAM;;;;;EAsB1B;AAID,UAAU,kBAAkB;IAC1B,mCAAmC;IACnC,QAAQ,EAAE,MAAM,CAAC;IACjB,uCAAuC;IACvC,YAAY,EAAE,MAAM,CAAC;IACrB,4DAA4D;IAC5D,OAAO,CAAC,EAAE,MAAM,CAAC;CAClB;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,kBAAkB,CAAC,MAAM,EAAE,kBAAkB,GAAG,cAAc,CA+E7E"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,448 @@
|
|
|
1
|
+
import { Router } from 'express';
|
|
2
|
+
import * as jose from 'jose';
|
|
3
|
+
// ─── Cookie Domain Helper ─────────────────────────────────────────────────
|
|
4
|
+
/**
|
|
5
|
+
* Derive cookie domain from hostname if not explicitly configured.
|
|
6
|
+
* - Production: *.tony.codes → .tony.codes (shared SSO)
|
|
7
|
+
* - Local: myapp.test → .myapp.test (isolated per app)
|
|
8
|
+
* - Subdomains: api.myapp.test → .myapp.test
|
|
9
|
+
*/
|
|
10
|
+
function deriveCookieDomain(hostname) {
|
|
11
|
+
// Production: use shared .tony.codes domain
|
|
12
|
+
if (hostname.endsWith('.tony.codes') || hostname === 'tony.codes') {
|
|
13
|
+
return '.tony.codes';
|
|
14
|
+
}
|
|
15
|
+
// Local .test domains: derive app-specific domain
|
|
16
|
+
if (hostname.endsWith('.test')) {
|
|
17
|
+
const parts = hostname.split('.');
|
|
18
|
+
// myapp.test → .myapp.test
|
|
19
|
+
// api.myapp.test → .myapp.test
|
|
20
|
+
if (parts.length >= 2) {
|
|
21
|
+
// Get the last two parts before .test (or just the app name)
|
|
22
|
+
const appPart = parts.length === 2 ? parts[0] : parts[parts.length - 2];
|
|
23
|
+
return `.${appPart}.test`;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
// Unknown domain structure — don't set domain (browser default)
|
|
27
|
+
return undefined;
|
|
28
|
+
}
|
|
29
|
+
// ─── JWKS Cache ──────────────────────────────────────────────────────────
|
|
30
|
+
let jwksCache = null;
|
|
31
|
+
let jwksCacheExpiry = 0;
|
|
32
|
+
const JWKS_CACHE_TTL = 5 * 60 * 1000; // 5 minutes
|
|
33
|
+
async function getJWKS(authUrl) {
|
|
34
|
+
const now = Date.now();
|
|
35
|
+
if (jwksCache && now < jwksCacheExpiry) {
|
|
36
|
+
return jwksCache;
|
|
37
|
+
}
|
|
38
|
+
const res = await fetch(`${authUrl}/.well-known/jwks.json`);
|
|
39
|
+
if (!res.ok) {
|
|
40
|
+
throw new Error(`Failed to fetch JWKS: ${res.status}`);
|
|
41
|
+
}
|
|
42
|
+
jwksCache = (await res.json());
|
|
43
|
+
jwksCacheExpiry = now + JWKS_CACHE_TTL;
|
|
44
|
+
return jwksCache;
|
|
45
|
+
}
|
|
46
|
+
async function verifyToken(token, authUrl) {
|
|
47
|
+
const jwks = await getJWKS(authUrl);
|
|
48
|
+
const JWKS = jose.createLocalJWKSet(jwks);
|
|
49
|
+
const { payload } = await jose.jwtVerify(token, JWKS, {
|
|
50
|
+
issuer: 'auth.tony.codes',
|
|
51
|
+
audience: 'tony.codes',
|
|
52
|
+
});
|
|
53
|
+
return payload;
|
|
54
|
+
}
|
|
55
|
+
// ─── Middleware Factory ──────────────────────────────────────────────────
|
|
56
|
+
export function createAuthMiddleware(config) {
|
|
57
|
+
const { authUrl = 'https://auth.tony.codes', clientId, clientSecret, cookieDomain: configuredDomain, appUrl, } = config;
|
|
58
|
+
/**
|
|
59
|
+
* Get the effective cookie domain for a request.
|
|
60
|
+
* Uses configured domain if provided, otherwise derives from hostname.
|
|
61
|
+
*/
|
|
62
|
+
function getCookieDomain(req) {
|
|
63
|
+
if (configuredDomain)
|
|
64
|
+
return configuredDomain;
|
|
65
|
+
const hostname = req.get('host')?.split(':')[0]; // Remove port if present
|
|
66
|
+
return hostname ? deriveCookieDomain(hostname) : undefined;
|
|
67
|
+
}
|
|
68
|
+
/**
|
|
69
|
+
* Base middleware — verifies JWT if present, attaches req.auth
|
|
70
|
+
* Does NOT reject unauthenticated requests
|
|
71
|
+
*/
|
|
72
|
+
function middleware() {
|
|
73
|
+
return async (req, _res, next) => {
|
|
74
|
+
const authHeader = req.headers.authorization;
|
|
75
|
+
if (!authHeader?.startsWith('Bearer ')) {
|
|
76
|
+
return next();
|
|
77
|
+
}
|
|
78
|
+
const token = authHeader.substring(7);
|
|
79
|
+
try {
|
|
80
|
+
const payload = await verifyToken(token, authUrl);
|
|
81
|
+
const org = payload.org;
|
|
82
|
+
req.auth = {
|
|
83
|
+
userId: payload.sub,
|
|
84
|
+
email: payload.email,
|
|
85
|
+
name: payload.name || null,
|
|
86
|
+
avatarUrl: payload.avatarUrl || null,
|
|
87
|
+
orgId: org?.id || null,
|
|
88
|
+
orgName: org?.name || null,
|
|
89
|
+
orgSlug: org?.slug || null,
|
|
90
|
+
orgRole: org?.role || null,
|
|
91
|
+
isSuperAdmin: payload.isSuperAdmin || false,
|
|
92
|
+
};
|
|
93
|
+
}
|
|
94
|
+
catch {
|
|
95
|
+
// Invalid token — continue without auth
|
|
96
|
+
}
|
|
97
|
+
next();
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
/**
|
|
101
|
+
* Require authenticated user with active organization
|
|
102
|
+
* Super admins can use X-Org-Id header to access any org
|
|
103
|
+
*/
|
|
104
|
+
function requireOrg() {
|
|
105
|
+
return async (req, res, next) => {
|
|
106
|
+
if (!req.auth) {
|
|
107
|
+
res.status(401).json({ error: 'Unauthorized' });
|
|
108
|
+
return;
|
|
109
|
+
}
|
|
110
|
+
// Super admins can override org via header
|
|
111
|
+
const headerOrgId = req.headers['x-org-id'];
|
|
112
|
+
if (req.auth.isSuperAdmin && headerOrgId) {
|
|
113
|
+
req.auth.orgId = headerOrgId;
|
|
114
|
+
req.auth.orgRole = 'admin';
|
|
115
|
+
return next();
|
|
116
|
+
}
|
|
117
|
+
if (!req.auth.orgId) {
|
|
118
|
+
res.status(403).json({ error: 'No organization selected' });
|
|
119
|
+
return;
|
|
120
|
+
}
|
|
121
|
+
next();
|
|
122
|
+
};
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
* Require super admin access
|
|
126
|
+
*/
|
|
127
|
+
function requireSuperAdmin() {
|
|
128
|
+
return (req, res, next) => {
|
|
129
|
+
if (!req.auth) {
|
|
130
|
+
res.status(401).json({ error: 'Unauthorized' });
|
|
131
|
+
return;
|
|
132
|
+
}
|
|
133
|
+
if (!req.auth.isSuperAdmin) {
|
|
134
|
+
res.status(403).json({ error: 'Super admin access required' });
|
|
135
|
+
return;
|
|
136
|
+
}
|
|
137
|
+
// Super admins can set org via header
|
|
138
|
+
const headerOrgId = req.headers['x-org-id'];
|
|
139
|
+
if (headerOrgId) {
|
|
140
|
+
req.auth.orgId = headerOrgId;
|
|
141
|
+
req.auth.orgRole = 'admin';
|
|
142
|
+
}
|
|
143
|
+
next();
|
|
144
|
+
};
|
|
145
|
+
}
|
|
146
|
+
/**
|
|
147
|
+
* Require specific organization role
|
|
148
|
+
*/
|
|
149
|
+
function requireOrgRole(...roles) {
|
|
150
|
+
return (req, res, next) => {
|
|
151
|
+
if (req.auth?.isSuperAdmin)
|
|
152
|
+
return next();
|
|
153
|
+
if (req.apiKey)
|
|
154
|
+
return next(); // API key auth uses scopes, not roles
|
|
155
|
+
if (!req.auth?.orgRole || !roles.includes(req.auth.orgRole)) {
|
|
156
|
+
res.status(403).json({ error: `Requires role: ${roles.join(' or ')}` });
|
|
157
|
+
return;
|
|
158
|
+
}
|
|
159
|
+
next();
|
|
160
|
+
};
|
|
161
|
+
}
|
|
162
|
+
/**
|
|
163
|
+
* Require specific API key scopes (session auth passes automatically)
|
|
164
|
+
*/
|
|
165
|
+
function requireScope(...scopes) {
|
|
166
|
+
return (req, res, next) => {
|
|
167
|
+
if (!req.apiKey)
|
|
168
|
+
return next(); // Session auth has all scopes
|
|
169
|
+
const hasScope = scopes.some((s) => req.apiKey.scopes.includes(s));
|
|
170
|
+
if (!hasScope) {
|
|
171
|
+
res.status(403).json({ error: `Requires scope: ${scopes.join(' or ')}` });
|
|
172
|
+
return;
|
|
173
|
+
}
|
|
174
|
+
next();
|
|
175
|
+
};
|
|
176
|
+
}
|
|
177
|
+
/**
|
|
178
|
+
* Handle auth callback — exchanges authorization code for tokens
|
|
179
|
+
* Mount at GET /api/auth/callback (not /auth/callback, which is for SPA routing)
|
|
180
|
+
*/
|
|
181
|
+
function callbackHandler() {
|
|
182
|
+
return async (req, res) => {
|
|
183
|
+
const { code, state } = req.query;
|
|
184
|
+
if (!code || typeof code !== 'string') {
|
|
185
|
+
res.status(400).json({ error: 'Missing authorization code' });
|
|
186
|
+
return;
|
|
187
|
+
}
|
|
188
|
+
try {
|
|
189
|
+
const redirectUri = appUrl
|
|
190
|
+
? `${appUrl}/auth/callback`
|
|
191
|
+
: `${req.protocol}://${req.get('host')}/auth/callback`;
|
|
192
|
+
const tokenRes = await fetch(`${authUrl}/api/token`, {
|
|
193
|
+
method: 'POST',
|
|
194
|
+
headers: { 'Content-Type': 'application/json' },
|
|
195
|
+
body: JSON.stringify({
|
|
196
|
+
grant_type: 'authorization_code',
|
|
197
|
+
code,
|
|
198
|
+
client_id: clientId,
|
|
199
|
+
client_secret: clientSecret,
|
|
200
|
+
redirect_uri: redirectUri,
|
|
201
|
+
}),
|
|
202
|
+
});
|
|
203
|
+
if (!tokenRes.ok) {
|
|
204
|
+
const err = (await tokenRes.json());
|
|
205
|
+
res.status(401).json({ error: err.error || 'Token exchange failed' });
|
|
206
|
+
return;
|
|
207
|
+
}
|
|
208
|
+
const tokens = (await tokenRes.json());
|
|
209
|
+
// Set refresh token as httpOnly cookie on the derived/configured domain
|
|
210
|
+
if (tokens.refresh_token) {
|
|
211
|
+
res.cookie('refresh_token', tokens.refresh_token, {
|
|
212
|
+
httpOnly: true,
|
|
213
|
+
secure: true,
|
|
214
|
+
sameSite: 'lax',
|
|
215
|
+
domain: getCookieDomain(req),
|
|
216
|
+
maxAge: 30 * 24 * 60 * 60 * 1000,
|
|
217
|
+
path: '/',
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
res.json({
|
|
221
|
+
access_token: tokens.access_token,
|
|
222
|
+
expires_in: tokens.expires_in,
|
|
223
|
+
});
|
|
224
|
+
}
|
|
225
|
+
catch (err) {
|
|
226
|
+
res.status(500).json({ error: 'Token exchange failed' });
|
|
227
|
+
}
|
|
228
|
+
};
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Proxy refresh token requests to the auth service
|
|
232
|
+
* Mount at POST /auth/refresh
|
|
233
|
+
*/
|
|
234
|
+
function refreshProxy() {
|
|
235
|
+
return async (req, res) => {
|
|
236
|
+
try {
|
|
237
|
+
const tokenRes = await fetch(`${authUrl}/api/token`, {
|
|
238
|
+
method: 'POST',
|
|
239
|
+
headers: {
|
|
240
|
+
'Content-Type': 'application/json',
|
|
241
|
+
Cookie: req.headers.cookie || '',
|
|
242
|
+
},
|
|
243
|
+
body: JSON.stringify({ grant_type: 'refresh_token' }),
|
|
244
|
+
});
|
|
245
|
+
if (!tokenRes.ok) {
|
|
246
|
+
res.status(tokenRes.status).json(await tokenRes.json());
|
|
247
|
+
return;
|
|
248
|
+
}
|
|
249
|
+
const tokens = (await tokenRes.json());
|
|
250
|
+
// Set rotated refresh token cookie
|
|
251
|
+
if (tokens.refresh_token) {
|
|
252
|
+
res.cookie('refresh_token', tokens.refresh_token, {
|
|
253
|
+
httpOnly: true,
|
|
254
|
+
secure: true,
|
|
255
|
+
sameSite: 'lax',
|
|
256
|
+
domain: getCookieDomain(req),
|
|
257
|
+
maxAge: 30 * 24 * 60 * 60 * 1000,
|
|
258
|
+
path: '/',
|
|
259
|
+
});
|
|
260
|
+
}
|
|
261
|
+
res.json({
|
|
262
|
+
access_token: tokens.access_token,
|
|
263
|
+
expires_in: tokens.expires_in,
|
|
264
|
+
});
|
|
265
|
+
}
|
|
266
|
+
catch {
|
|
267
|
+
res.status(500).json({ error: 'Refresh failed' });
|
|
268
|
+
}
|
|
269
|
+
};
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Proxy org switch requests to the auth service
|
|
273
|
+
* Mount at POST /auth/switch-org
|
|
274
|
+
*/
|
|
275
|
+
function switchOrgProxy() {
|
|
276
|
+
return async (req, res) => {
|
|
277
|
+
const { org_id } = req.body;
|
|
278
|
+
try {
|
|
279
|
+
const tokenRes = await fetch(`${authUrl}/api/token`, {
|
|
280
|
+
method: 'POST',
|
|
281
|
+
headers: {
|
|
282
|
+
'Content-Type': 'application/json',
|
|
283
|
+
Cookie: req.headers.cookie || '',
|
|
284
|
+
},
|
|
285
|
+
body: JSON.stringify({ grant_type: 'switch_organization', org_id }),
|
|
286
|
+
});
|
|
287
|
+
if (!tokenRes.ok) {
|
|
288
|
+
res.status(tokenRes.status).json(await tokenRes.json());
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
const tokens = (await tokenRes.json());
|
|
292
|
+
// Set rotated refresh token cookie
|
|
293
|
+
if (tokens.refresh_token) {
|
|
294
|
+
res.cookie('refresh_token', tokens.refresh_token, {
|
|
295
|
+
httpOnly: true,
|
|
296
|
+
secure: true,
|
|
297
|
+
sameSite: 'lax',
|
|
298
|
+
domain: getCookieDomain(req),
|
|
299
|
+
maxAge: 30 * 24 * 60 * 60 * 1000,
|
|
300
|
+
path: '/',
|
|
301
|
+
});
|
|
302
|
+
}
|
|
303
|
+
res.json({
|
|
304
|
+
access_token: tokens.access_token,
|
|
305
|
+
expires_in: tokens.expires_in,
|
|
306
|
+
});
|
|
307
|
+
}
|
|
308
|
+
catch {
|
|
309
|
+
res.status(500).json({ error: 'Organization switch failed' });
|
|
310
|
+
}
|
|
311
|
+
};
|
|
312
|
+
}
|
|
313
|
+
/**
|
|
314
|
+
* Proxy logout requests to the auth service
|
|
315
|
+
* Mount at POST /auth/logout
|
|
316
|
+
*/
|
|
317
|
+
function logoutProxy() {
|
|
318
|
+
return async (req, res) => {
|
|
319
|
+
try {
|
|
320
|
+
await fetch(`${authUrl}/api/logout`, {
|
|
321
|
+
method: 'POST',
|
|
322
|
+
headers: {
|
|
323
|
+
'Content-Type': 'application/json',
|
|
324
|
+
Cookie: req.headers.cookie || '',
|
|
325
|
+
},
|
|
326
|
+
});
|
|
327
|
+
// Clear refresh token cookie
|
|
328
|
+
res.clearCookie('refresh_token', {
|
|
329
|
+
httpOnly: true,
|
|
330
|
+
secure: true,
|
|
331
|
+
sameSite: 'lax',
|
|
332
|
+
domain: getCookieDomain(req),
|
|
333
|
+
path: '/',
|
|
334
|
+
});
|
|
335
|
+
res.json({ ok: true });
|
|
336
|
+
}
|
|
337
|
+
catch {
|
|
338
|
+
res.status(500).json({ error: 'Logout failed' });
|
|
339
|
+
}
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
/**
|
|
343
|
+
* Returns an Express Router with all auth proxy routes pre-mounted.
|
|
344
|
+
* Replaces the need to mount each handler individually:
|
|
345
|
+
* app.use(auth.routes())
|
|
346
|
+
*/
|
|
347
|
+
function routes() {
|
|
348
|
+
const router = Router();
|
|
349
|
+
router.get('/api/auth/callback', callbackHandler());
|
|
350
|
+
router.post('/auth/refresh', refreshProxy());
|
|
351
|
+
router.post('/auth/switch-org', switchOrgProxy());
|
|
352
|
+
router.post('/auth/logout', logoutProxy());
|
|
353
|
+
return router;
|
|
354
|
+
}
|
|
355
|
+
return {
|
|
356
|
+
middleware,
|
|
357
|
+
requireOrg,
|
|
358
|
+
requireSuperAdmin,
|
|
359
|
+
requireOrgRole,
|
|
360
|
+
requireScope,
|
|
361
|
+
callbackHandler,
|
|
362
|
+
refreshProxy,
|
|
363
|
+
switchOrgProxy,
|
|
364
|
+
logoutProxy,
|
|
365
|
+
routes,
|
|
366
|
+
config: { authUrl, clientId },
|
|
367
|
+
};
|
|
368
|
+
}
|
|
369
|
+
/**
|
|
370
|
+
* Standalone callback handler for hosted login page mode.
|
|
371
|
+
* Exchanges the authorization code for tokens, sets cookies, and redirects.
|
|
372
|
+
*
|
|
373
|
+
* Use this when you don't need the full SDK — just redirect to /authorize
|
|
374
|
+
* and mount this single route:
|
|
375
|
+
*
|
|
376
|
+
* app.get('/auth/callback', createCallbackPage({
|
|
377
|
+
* clientId: 'my-app',
|
|
378
|
+
* clientSecret: process.env.AUTH_SECRET!,
|
|
379
|
+
* }));
|
|
380
|
+
*/
|
|
381
|
+
export function createCallbackPage(config) {
|
|
382
|
+
const { clientId, clientSecret, authUrl = 'https://auth.tony.codes' } = config;
|
|
383
|
+
return async (req, res) => {
|
|
384
|
+
const { code, state } = req.query;
|
|
385
|
+
if (!code || typeof code !== 'string') {
|
|
386
|
+
res.status(400).send('Missing authorization code');
|
|
387
|
+
return;
|
|
388
|
+
}
|
|
389
|
+
// Derive redirect_uri from the current request URL
|
|
390
|
+
const redirectUri = `${req.protocol}://${req.get('host')}${req.path}`;
|
|
391
|
+
try {
|
|
392
|
+
const tokenRes = await fetch(`${authUrl}/api/token`, {
|
|
393
|
+
method: 'POST',
|
|
394
|
+
headers: { 'Content-Type': 'application/json' },
|
|
395
|
+
body: JSON.stringify({
|
|
396
|
+
grant_type: 'authorization_code',
|
|
397
|
+
code,
|
|
398
|
+
client_id: clientId,
|
|
399
|
+
client_secret: clientSecret,
|
|
400
|
+
redirect_uri: redirectUri,
|
|
401
|
+
}),
|
|
402
|
+
});
|
|
403
|
+
if (!tokenRes.ok) {
|
|
404
|
+
res.status(401).send('Authentication failed');
|
|
405
|
+
return;
|
|
406
|
+
}
|
|
407
|
+
const tokens = (await tokenRes.json());
|
|
408
|
+
// Set refresh token as httpOnly cookie
|
|
409
|
+
if (tokens.refresh_token) {
|
|
410
|
+
const hostname = req.get('host')?.split(':')[0];
|
|
411
|
+
const cookieDomain = hostname ? deriveCookieDomain(hostname) : undefined;
|
|
412
|
+
res.cookie('refresh_token', tokens.refresh_token, {
|
|
413
|
+
httpOnly: true,
|
|
414
|
+
secure: true,
|
|
415
|
+
sameSite: 'lax',
|
|
416
|
+
domain: cookieDomain,
|
|
417
|
+
maxAge: 30 * 24 * 60 * 60 * 1000,
|
|
418
|
+
path: '/',
|
|
419
|
+
});
|
|
420
|
+
}
|
|
421
|
+
// Set access token as a short-lived cookie for the app to read
|
|
422
|
+
res.cookie('access_token', tokens.access_token, {
|
|
423
|
+
secure: true,
|
|
424
|
+
sameSite: 'lax',
|
|
425
|
+
maxAge: tokens.expires_in * 1000,
|
|
426
|
+
path: '/',
|
|
427
|
+
});
|
|
428
|
+
// Parse returnTo from state, or default to /
|
|
429
|
+
let returnTo = '/';
|
|
430
|
+
if (state && typeof state === 'string') {
|
|
431
|
+
try {
|
|
432
|
+
const parsed = JSON.parse(atob(state));
|
|
433
|
+
if (parsed.returnTo && typeof parsed.returnTo === 'string') {
|
|
434
|
+
returnTo = parsed.returnTo;
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
catch {
|
|
438
|
+
// Invalid state — ignore
|
|
439
|
+
}
|
|
440
|
+
}
|
|
441
|
+
res.redirect(returnTo);
|
|
442
|
+
}
|
|
443
|
+
catch {
|
|
444
|
+
res.status(500).send('Authentication failed');
|
|
445
|
+
}
|
|
446
|
+
};
|
|
447
|
+
}
|
|
448
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"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"}
|
package/package.json
ADDED
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
{
|
|
2
|
+
"name": "@tonycodes/auth-express",
|
|
3
|
+
"version": "1.1.0",
|
|
4
|
+
"description": "Express middleware for Tony Auth service",
|
|
5
|
+
"type": "module",
|
|
6
|
+
"main": "dist/index.js",
|
|
7
|
+
"types": "dist/index.d.ts",
|
|
8
|
+
"exports": {
|
|
9
|
+
".": {
|
|
10
|
+
"import": "./dist/index.js",
|
|
11
|
+
"types": "./dist/index.d.ts"
|
|
12
|
+
}
|
|
13
|
+
},
|
|
14
|
+
"files": [
|
|
15
|
+
"dist"
|
|
16
|
+
],
|
|
17
|
+
"scripts": {
|
|
18
|
+
"build": "tsc",
|
|
19
|
+
"dev": "tsc --watch",
|
|
20
|
+
"prepublishOnly": "npm run build"
|
|
21
|
+
},
|
|
22
|
+
"keywords": [
|
|
23
|
+
"express",
|
|
24
|
+
"auth",
|
|
25
|
+
"authentication",
|
|
26
|
+
"middleware",
|
|
27
|
+
"sdk"
|
|
28
|
+
],
|
|
29
|
+
"author": "Tony <tony@tony.codes>",
|
|
30
|
+
"license": "MIT",
|
|
31
|
+
"repository": {
|
|
32
|
+
"type": "git",
|
|
33
|
+
"url": "git+https://github.com/tonycodes/auth-express.git"
|
|
34
|
+
},
|
|
35
|
+
"homepage": "https://github.com/tonycodes/auth-express#readme",
|
|
36
|
+
"bugs": {
|
|
37
|
+
"url": "https://github.com/tonycodes/auth-express/issues"
|
|
38
|
+
},
|
|
39
|
+
"publishConfig": {
|
|
40
|
+
"access": "public"
|
|
41
|
+
},
|
|
42
|
+
"dependencies": {
|
|
43
|
+
"jose": "^6.0.11"
|
|
44
|
+
},
|
|
45
|
+
"peerDependencies": {
|
|
46
|
+
"express": ">=4.0.0 || >=5.0.0"
|
|
47
|
+
},
|
|
48
|
+
"devDependencies": {
|
|
49
|
+
"@types/express": "^5.0.0",
|
|
50
|
+
"typescript": "^5.3.2"
|
|
51
|
+
}
|
|
52
|
+
}
|