@cleverclouds/auth-client 0.0.0-stage → 1.0.1
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/AGENTS.md +379 -0
- package/README.md +450 -2
- package/dist/client.d.ts +61 -0
- package/dist/client.d.ts.map +1 -0
- package/dist/client.js +226 -0
- package/dist/client.js.map +1 -0
- package/dist/crypto.d.ts +12 -0
- package/dist/crypto.d.ts.map +1 -0
- package/dist/crypto.js +66 -0
- package/dist/crypto.js.map +1 -0
- package/dist/errors.d.ts +22 -0
- package/dist/errors.d.ts.map +1 -0
- package/dist/errors.js +49 -0
- package/dist/errors.js.map +1 -0
- package/dist/express/index.d.ts +18 -0
- package/dist/express/index.d.ts.map +1 -0
- package/dist/express/index.js +296 -0
- package/dist/express/index.js.map +1 -0
- package/dist/express/types.d.ts +70 -0
- package/dist/express/types.d.ts.map +1 -0
- package/dist/express/types.js +3 -0
- package/dist/express/types.js.map +1 -0
- package/dist/index.d.ts +6 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +24 -0
- package/dist/index.js.map +1 -0
- package/dist/nextjs/index.d.ts +33 -0
- package/dist/nextjs/index.d.ts.map +1 -0
- package/dist/nextjs/index.js +178 -0
- package/dist/nextjs/index.js.map +1 -0
- package/dist/nextjs/types.d.ts +51 -0
- package/dist/nextjs/types.d.ts.map +1 -0
- package/dist/nextjs/types.js +3 -0
- package/dist/nextjs/types.js.map +1 -0
- package/dist/permissions.d.ts +25 -0
- package/dist/permissions.d.ts.map +1 -0
- package/dist/permissions.js +62 -0
- package/dist/permissions.js.map +1 -0
- package/dist/types.d.ts +53 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +6 -0
- package/dist/types.js.map +1 -0
- package/package.json +86 -4
|
@@ -0,0 +1,296 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.createAuthMiddleware = createAuthMiddleware;
|
|
18
|
+
__exportStar(require("./types.js"), exports);
|
|
19
|
+
function parseCookies(cookieHeader) {
|
|
20
|
+
const list = {};
|
|
21
|
+
if (!cookieHeader)
|
|
22
|
+
return list;
|
|
23
|
+
for (const cookie of cookieHeader.split(';')) {
|
|
24
|
+
const parts = cookie.split('=');
|
|
25
|
+
const name = parts[0]?.trim();
|
|
26
|
+
const val = parts.slice(1).join('=').trim();
|
|
27
|
+
if (name) {
|
|
28
|
+
try {
|
|
29
|
+
list[name] = decodeURIComponent(val);
|
|
30
|
+
}
|
|
31
|
+
catch {
|
|
32
|
+
list[name] = val;
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
return list;
|
|
37
|
+
}
|
|
38
|
+
/**
|
|
39
|
+
* Creates Express authentication and authorization middlewares bound to a CleverCloudsAuthClient instance.
|
|
40
|
+
*/
|
|
41
|
+
function createAuthMiddleware(client, options = {}) {
|
|
42
|
+
const cookieName = options.cookieName || 'cc_session';
|
|
43
|
+
const cookieOptions = {
|
|
44
|
+
httpOnly: options.cookieOptions?.httpOnly ?? true,
|
|
45
|
+
secure: options.cookieOptions?.secure ?? (process.env.NODE_ENV === 'production'),
|
|
46
|
+
sameSite: options.cookieOptions?.sameSite ?? 'lax',
|
|
47
|
+
path: options.cookieOptions?.path ?? '/',
|
|
48
|
+
maxAge: options.cookieOptions?.maxAge ?? 24 * 60 * 60 * 1000,
|
|
49
|
+
};
|
|
50
|
+
/**
|
|
51
|
+
* Helper to resolve the authenticated session from cookies or Bearer Authorization header.
|
|
52
|
+
*/
|
|
53
|
+
async function resolveSession(req) {
|
|
54
|
+
if (req.auth) {
|
|
55
|
+
return req.auth;
|
|
56
|
+
}
|
|
57
|
+
// 1. Check cookies (Express cookie-parser or raw Cookie header fallback)
|
|
58
|
+
const cookies = req.cookies || parseCookies(req.headers.cookie);
|
|
59
|
+
const sessionCookie = cookies[cookieName];
|
|
60
|
+
if (sessionCookie) {
|
|
61
|
+
const verified = client.verifySessionCookie(sessionCookie);
|
|
62
|
+
if (verified)
|
|
63
|
+
return verified;
|
|
64
|
+
// Fallback: verify directly with Identity if sessionToken string was stored
|
|
65
|
+
const remote = await client.verifySession(sessionCookie);
|
|
66
|
+
if (remote)
|
|
67
|
+
return remote;
|
|
68
|
+
}
|
|
69
|
+
// 2. Check Authorization Bearer header (for direct API / service-to-service calls)
|
|
70
|
+
const authHeader = req.headers.authorization;
|
|
71
|
+
if (authHeader && authHeader.startsWith('Bearer ')) {
|
|
72
|
+
const token = authHeader.slice(7).trim();
|
|
73
|
+
if (token) {
|
|
74
|
+
const verified = client.verifySessionCookie(token);
|
|
75
|
+
if (verified)
|
|
76
|
+
return verified;
|
|
77
|
+
const remote = await client.verifySession(token);
|
|
78
|
+
if (remote)
|
|
79
|
+
return remote;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
return null;
|
|
83
|
+
}
|
|
84
|
+
/**
|
|
85
|
+
* Middleware requiring a valid authenticated session.
|
|
86
|
+
*/
|
|
87
|
+
function requireAuth(authOptions = {}) {
|
|
88
|
+
return async (req, res, next) => {
|
|
89
|
+
try {
|
|
90
|
+
const session = await resolveSession(req);
|
|
91
|
+
if (session) {
|
|
92
|
+
req.auth = session;
|
|
93
|
+
return next();
|
|
94
|
+
}
|
|
95
|
+
const wantsHtml = authOptions.redirectToLogin !== false &&
|
|
96
|
+
(authOptions.redirectToLogin || (req.headers.accept && req.headers.accept.includes('text/html')));
|
|
97
|
+
if (wantsHtml) {
|
|
98
|
+
const returnTo = req.originalUrl || req.url || '/';
|
|
99
|
+
res.redirect(client.getLoginUrl({ returnTo }));
|
|
100
|
+
return;
|
|
101
|
+
}
|
|
102
|
+
res.status(401).json({
|
|
103
|
+
error: 'Unauthorized',
|
|
104
|
+
message: 'Authentication required. Please sign in.',
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
next(err);
|
|
109
|
+
}
|
|
110
|
+
};
|
|
111
|
+
}
|
|
112
|
+
/**
|
|
113
|
+
* Middleware requiring one or more application-scoped permissions.
|
|
114
|
+
*/
|
|
115
|
+
function requirePermission(permission, permOptions = {}) {
|
|
116
|
+
return async (req, res, next) => {
|
|
117
|
+
try {
|
|
118
|
+
const session = await resolveSession(req);
|
|
119
|
+
if (!session) {
|
|
120
|
+
const wantsHtml = req.headers.accept && req.headers.accept.includes('text/html');
|
|
121
|
+
if (wantsHtml) {
|
|
122
|
+
res.redirect(client.getLoginUrl({ returnTo: req.originalUrl || req.url }));
|
|
123
|
+
return;
|
|
124
|
+
}
|
|
125
|
+
res.status(401).json({
|
|
126
|
+
error: 'Unauthorized',
|
|
127
|
+
message: 'Authentication required. Please sign in.',
|
|
128
|
+
});
|
|
129
|
+
return;
|
|
130
|
+
}
|
|
131
|
+
req.auth = session;
|
|
132
|
+
const granted = session.permissions || [];
|
|
133
|
+
let allowed = false;
|
|
134
|
+
if (Array.isArray(permission)) {
|
|
135
|
+
allowed =
|
|
136
|
+
permOptions.requireAll !== false
|
|
137
|
+
? client.hasAllPermissions(granted, permission)
|
|
138
|
+
: client.hasAnyPermission(granted, permission);
|
|
139
|
+
}
|
|
140
|
+
else {
|
|
141
|
+
allowed = client.hasPermission(granted, permission);
|
|
142
|
+
}
|
|
143
|
+
if (!allowed) {
|
|
144
|
+
res.status(403).json({
|
|
145
|
+
error: 'Forbidden',
|
|
146
|
+
message: `Missing required permission: ${Array.isArray(permission) ? permission.join(', ') : permission}`,
|
|
147
|
+
required: permission,
|
|
148
|
+
granted,
|
|
149
|
+
});
|
|
150
|
+
return;
|
|
151
|
+
}
|
|
152
|
+
next();
|
|
153
|
+
}
|
|
154
|
+
catch (err) {
|
|
155
|
+
next(err);
|
|
156
|
+
}
|
|
157
|
+
};
|
|
158
|
+
}
|
|
159
|
+
/**
|
|
160
|
+
* Middleware requiring one or more application roles.
|
|
161
|
+
*/
|
|
162
|
+
function requireRole(role) {
|
|
163
|
+
return async (req, res, next) => {
|
|
164
|
+
try {
|
|
165
|
+
const session = await resolveSession(req);
|
|
166
|
+
if (!session) {
|
|
167
|
+
const wantsHtml = req.headers.accept && req.headers.accept.includes('text/html');
|
|
168
|
+
if (wantsHtml) {
|
|
169
|
+
res.redirect(client.getLoginUrl({ returnTo: req.originalUrl || req.url }));
|
|
170
|
+
return;
|
|
171
|
+
}
|
|
172
|
+
res.status(401).json({
|
|
173
|
+
error: 'Unauthorized',
|
|
174
|
+
message: 'Authentication required. Please sign in.',
|
|
175
|
+
});
|
|
176
|
+
return;
|
|
177
|
+
}
|
|
178
|
+
req.auth = session;
|
|
179
|
+
const grantedRoles = session.roles || [];
|
|
180
|
+
const allowed = Array.isArray(role)
|
|
181
|
+
? client.hasAnyRole(grantedRoles, role)
|
|
182
|
+
: client.hasRole(grantedRoles, role);
|
|
183
|
+
if (!allowed) {
|
|
184
|
+
res.status(403).json({
|
|
185
|
+
error: 'Forbidden',
|
|
186
|
+
message: `Missing required role: ${Array.isArray(role) ? role.join(', ') : role}`,
|
|
187
|
+
required: role,
|
|
188
|
+
granted: grantedRoles,
|
|
189
|
+
});
|
|
190
|
+
return;
|
|
191
|
+
}
|
|
192
|
+
next();
|
|
193
|
+
}
|
|
194
|
+
catch (err) {
|
|
195
|
+
next(err);
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* SSO Callback Route Handler: exchanges single-use ticket, signs session cookie, and redirects user.
|
|
201
|
+
*/
|
|
202
|
+
function handleCallback(callbackOptions = {}) {
|
|
203
|
+
return async (req, res) => {
|
|
204
|
+
const ticket = req.query.ticket;
|
|
205
|
+
if (!ticket) {
|
|
206
|
+
if (callbackOptions.onError) {
|
|
207
|
+
await callbackOptions.onError(req, res, new Error('No authorization ticket found in query parameters'));
|
|
208
|
+
return;
|
|
209
|
+
}
|
|
210
|
+
res.status(400).json({
|
|
211
|
+
error: 'Bad Request',
|
|
212
|
+
message: 'No authorization ticket provided',
|
|
213
|
+
});
|
|
214
|
+
return;
|
|
215
|
+
}
|
|
216
|
+
try {
|
|
217
|
+
const exchange = await client.exchangeTicketDetailed(ticket);
|
|
218
|
+
if (!exchange.success) {
|
|
219
|
+
if (callbackOptions.onError) {
|
|
220
|
+
await callbackOptions.onError(req, res, exchange.error);
|
|
221
|
+
return;
|
|
222
|
+
}
|
|
223
|
+
const statusCode = exchange.error.statusCode || 401;
|
|
224
|
+
res.status(statusCode).json({
|
|
225
|
+
error: exchange.error.code,
|
|
226
|
+
message: exchange.error.message,
|
|
227
|
+
});
|
|
228
|
+
return;
|
|
229
|
+
}
|
|
230
|
+
const authResult = exchange.data;
|
|
231
|
+
const signedValue = client.signSessionCookie(authResult);
|
|
232
|
+
res.cookie(cookieName, signedValue, {
|
|
233
|
+
httpOnly: cookieOptions.httpOnly,
|
|
234
|
+
secure: cookieOptions.secure,
|
|
235
|
+
sameSite: cookieOptions.sameSite,
|
|
236
|
+
path: cookieOptions.path,
|
|
237
|
+
maxAge: cookieOptions.maxAge,
|
|
238
|
+
});
|
|
239
|
+
if (callbackOptions.onSuccess) {
|
|
240
|
+
await callbackOptions.onSuccess(req, res, authResult);
|
|
241
|
+
}
|
|
242
|
+
// Open Redirect Prevention: Ensure redirect target is a safe relative URL path
|
|
243
|
+
const isSafeRelativeUrl = (url) => {
|
|
244
|
+
if (!url || typeof url !== 'string')
|
|
245
|
+
return false;
|
|
246
|
+
return url.startsWith('/') && !url.startsWith('//') && !url.includes('\\');
|
|
247
|
+
};
|
|
248
|
+
const candidateTarget = req.query.state || req.query.returnTo;
|
|
249
|
+
const defaultTarget = isSafeRelativeUrl(callbackOptions.defaultReturnTo)
|
|
250
|
+
? callbackOptions.defaultReturnTo
|
|
251
|
+
: '/';
|
|
252
|
+
const target = isSafeRelativeUrl(candidateTarget) ? candidateTarget : defaultTarget;
|
|
253
|
+
res.redirect(target);
|
|
254
|
+
}
|
|
255
|
+
catch (err) {
|
|
256
|
+
if (callbackOptions.onError) {
|
|
257
|
+
await callbackOptions.onError(req, res, err);
|
|
258
|
+
return;
|
|
259
|
+
}
|
|
260
|
+
res.status(500).json({
|
|
261
|
+
error: 'Internal Server Error',
|
|
262
|
+
message: err?.message || 'Authentication ticket exchange failed',
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
};
|
|
266
|
+
}
|
|
267
|
+
/**
|
|
268
|
+
* Logout Route Handler: clears local session cookie and optionally redirects to Identity.
|
|
269
|
+
*/
|
|
270
|
+
function handleLogout(logoutOptions = {}) {
|
|
271
|
+
return (_req, res) => {
|
|
272
|
+
res.clearCookie(cookieName, {
|
|
273
|
+
path: cookieOptions.path,
|
|
274
|
+
});
|
|
275
|
+
if (logoutOptions.redirectToIdentity !== false) {
|
|
276
|
+
const returnTarget = logoutOptions.returnTo || _req.query?.returnTo;
|
|
277
|
+
res.redirect(client.getLogoutUrl(returnTarget));
|
|
278
|
+
return;
|
|
279
|
+
}
|
|
280
|
+
res.status(200).json({
|
|
281
|
+
success: true,
|
|
282
|
+
message: 'Logged out successfully',
|
|
283
|
+
});
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
return {
|
|
287
|
+
cookieName,
|
|
288
|
+
resolveSession,
|
|
289
|
+
requireAuth,
|
|
290
|
+
requirePermission,
|
|
291
|
+
requireRole,
|
|
292
|
+
handleCallback,
|
|
293
|
+
handleLogout,
|
|
294
|
+
};
|
|
295
|
+
}
|
|
296
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/express/index.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
import type { VerificationResult } from '../types.js';
|
|
2
|
+
export interface AuthMiddlewareOptions {
|
|
3
|
+
/**
|
|
4
|
+
* Name of the cookie storing the session token.
|
|
5
|
+
* Default: 'cc_session'
|
|
6
|
+
*/
|
|
7
|
+
cookieName?: string;
|
|
8
|
+
/**
|
|
9
|
+
* Cookie options when setting the session cookie in handleCallback.
|
|
10
|
+
*/
|
|
11
|
+
cookieOptions?: {
|
|
12
|
+
httpOnly?: boolean;
|
|
13
|
+
secure?: boolean;
|
|
14
|
+
sameSite?: 'lax' | 'strict' | 'none' | boolean;
|
|
15
|
+
maxAge?: number;
|
|
16
|
+
path?: string;
|
|
17
|
+
};
|
|
18
|
+
}
|
|
19
|
+
export interface RequireAuthOptions {
|
|
20
|
+
/**
|
|
21
|
+
* If true, unauthenticated browser requests are redirected to the Identity login page.
|
|
22
|
+
* If false, a 401 Unauthorized JSON response is returned.
|
|
23
|
+
* Default: true for HTML navigation requests (Accept: text/html), false for API calls.
|
|
24
|
+
*/
|
|
25
|
+
redirectToLogin?: boolean;
|
|
26
|
+
}
|
|
27
|
+
export interface RequirePermissionOptions {
|
|
28
|
+
/**
|
|
29
|
+
* If true, user must have all specified permissions when an array is passed.
|
|
30
|
+
* If false, user must have at least one of the specified permissions.
|
|
31
|
+
* Default: true
|
|
32
|
+
*/
|
|
33
|
+
requireAll?: boolean;
|
|
34
|
+
}
|
|
35
|
+
export interface HandleCallbackOptions {
|
|
36
|
+
/**
|
|
37
|
+
* Default redirect target if no `state` or `returnTo` is provided in query params.
|
|
38
|
+
* Default: '/'
|
|
39
|
+
*/
|
|
40
|
+
defaultReturnTo?: string;
|
|
41
|
+
/**
|
|
42
|
+
* Hook invoked after successful ticket exchange and cookie setting, before sending redirect.
|
|
43
|
+
*/
|
|
44
|
+
onSuccess?: (req: any, res: any, authResult: VerificationResult) => void | Promise<void>;
|
|
45
|
+
/**
|
|
46
|
+
* Hook invoked when ticket exchange fails.
|
|
47
|
+
*/
|
|
48
|
+
onError?: (req: any, res: any, error: Error) => void | Promise<void>;
|
|
49
|
+
}
|
|
50
|
+
export interface HandleLogoutOptions {
|
|
51
|
+
/**
|
|
52
|
+
* Redirect URL after clearing the local session.
|
|
53
|
+
* If true (or undefined), redirects to Identity login/logout URL.
|
|
54
|
+
* If false, does not redirect and returns 200 OK JSON.
|
|
55
|
+
* Default: true
|
|
56
|
+
*/
|
|
57
|
+
redirectToIdentity?: boolean;
|
|
58
|
+
/**
|
|
59
|
+
* Return target after Identity finishes logging out.
|
|
60
|
+
*/
|
|
61
|
+
returnTo?: string;
|
|
62
|
+
}
|
|
63
|
+
declare global {
|
|
64
|
+
namespace Express {
|
|
65
|
+
interface Request {
|
|
66
|
+
auth?: VerificationResult;
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
//# sourceMappingURL=types.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../src/express/types.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEtD,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IAEpB;;OAEG;IACH,aAAa,CAAC,EAAE;QACd,QAAQ,CAAC,EAAE,OAAO,CAAC;QACnB,MAAM,CAAC,EAAE,OAAO,CAAC;QACjB,QAAQ,CAAC,EAAE,KAAK,GAAG,QAAQ,GAAG,MAAM,GAAG,OAAO,CAAC;QAC/C,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;KACf,CAAC;CACH;AAED,MAAM,WAAW,kBAAkB;IACjC;;;;OAIG;IACH,eAAe,CAAC,EAAE,OAAO,CAAC;CAC3B;AAED,MAAM,WAAW,wBAAwB;IACvC;;;;OAIG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB;AAED,MAAM,WAAW,qBAAqB;IACpC;;;OAGG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC;IAEzB;;OAEG;IACH,SAAS,CAAC,EAAE,CACV,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,GAAG,EACR,UAAU,EAAE,kBAAkB,KAC3B,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAE1B;;OAEG;IACH,OAAO,CAAC,EAAE,CACR,GAAG,EAAE,GAAG,EACR,GAAG,EAAE,GAAG,EACR,KAAK,EAAE,KAAK,KACT,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;CAC3B;AAED,MAAM,WAAW,mBAAmB;IAClC;;;;;OAKG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAE7B;;OAEG;IACH,QAAQ,CAAC,EAAE,MAAM,CAAC;CACnB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,OAAO,CAAC;QAChB,UAAU,OAAO;YACf,IAAI,CAAC,EAAE,kBAAkB,CAAC;SAC3B;KACF;CACF"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"types.js","sourceRoot":"","sources":["../../src/express/types.ts"],"names":[],"mappings":""}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,aAAa,CAAC;AACrD,cAAc,YAAY,CAAC;AAC3B,cAAc,kBAAkB,CAAC;AACjC,cAAc,aAAa,CAAC;AAC5B,cAAc,aAAa,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.CleverCloudsAuthClient = void 0;
|
|
18
|
+
var client_js_1 = require("./client.js");
|
|
19
|
+
Object.defineProperty(exports, "CleverCloudsAuthClient", { enumerable: true, get: function () { return client_js_1.CleverCloudsAuthClient; } });
|
|
20
|
+
__exportStar(require("./types.js"), exports);
|
|
21
|
+
__exportStar(require("./permissions.js"), exports);
|
|
22
|
+
__exportStar(require("./crypto.js"), exports);
|
|
23
|
+
__exportStar(require("./errors.js"), exports);
|
|
24
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;;;;;;AAAA,yCAAqD;AAA5C,mHAAA,sBAAsB,OAAA;AAC/B,6CAA2B;AAC3B,mDAAiC;AACjC,8CAA4B;AAC5B,8CAA4B"}
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import { CleverCloudsAuthClient } from '../client.js';
|
|
2
|
+
import type { VerificationResult } from '../types.js';
|
|
3
|
+
import type { NextAuthOptions, ProtectRouteOptions } from './types.js';
|
|
4
|
+
export * from './types.js';
|
|
5
|
+
/**
|
|
6
|
+
* Retrieves and validates the current user session in Next.js Server Components,
|
|
7
|
+
* Server Actions, or Route Handlers.
|
|
8
|
+
*/
|
|
9
|
+
export declare function getServerSession(client: CleverCloudsAuthClient, options?: NextAuthOptions): Promise<VerificationResult | null>;
|
|
10
|
+
/**
|
|
11
|
+
* Guard utility for Next.js Route Handlers and Server Actions.
|
|
12
|
+
* Returns { authorized: true, session } or { authorized: false, response }.
|
|
13
|
+
*/
|
|
14
|
+
export declare function protectRoute(client: CleverCloudsAuthClient, options?: ProtectRouteOptions): Promise<{
|
|
15
|
+
authorized: boolean;
|
|
16
|
+
session: VerificationResult | null;
|
|
17
|
+
response?: Response;
|
|
18
|
+
}>;
|
|
19
|
+
/**
|
|
20
|
+
* Creates a configured Next.js Auth helper instance.
|
|
21
|
+
*/
|
|
22
|
+
export declare function createNextAuth(client: CleverCloudsAuthClient, defaultOptions?: NextAuthOptions): {
|
|
23
|
+
client: CleverCloudsAuthClient;
|
|
24
|
+
getServerSession: (options?: NextAuthOptions) => Promise<VerificationResult | null>;
|
|
25
|
+
protectRoute: (options?: ProtectRouteOptions) => Promise<{
|
|
26
|
+
authorized: boolean;
|
|
27
|
+
session: VerificationResult | null;
|
|
28
|
+
response?: Response;
|
|
29
|
+
}>;
|
|
30
|
+
getLoginUrl: (options?: any) => string;
|
|
31
|
+
getLogoutUrl: (returnTo?: string) => string;
|
|
32
|
+
};
|
|
33
|
+
//# sourceMappingURL=index.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/nextjs/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,KAAK,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AACtD,OAAO,KAAK,EAAE,eAAe,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AAEvE,cAAc,YAAY,CAAC;AAgB3B;;;GAGG;AACH,wBAAsB,gBAAgB,CACpC,MAAM,EAAE,sBAAsB,EAC9B,OAAO,GAAE,eAAoB,GAC5B,OAAO,CAAC,kBAAkB,GAAG,IAAI,CAAC,CAkEpC;AAED;;;GAGG;AACH,wBAAsB,YAAY,CAChC,MAAM,EAAE,sBAAsB,EAC9B,OAAO,GAAE,mBAAwB,GAChC,OAAO,CAAC;IACT,UAAU,EAAE,OAAO,CAAC;IACpB,OAAO,EAAE,kBAAkB,GAAG,IAAI,CAAC;IACnC,QAAQ,CAAC,EAAE,QAAQ,CAAC;CACrB,CAAC,CAgFD;AAED;;GAEG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,sBAAsB,EAAE,cAAc,CAAC,EAAE,eAAe;;iCAG9D,eAAe;6BAEnB,mBAAmB;oBA7FlC,OAAO;iBACV,kBAAkB,GAAG,IAAI;mBACvB,QAAQ;;4BA6FO,GAAG;8BACD,MAAM;EAEnC"}
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
exports.getServerSession = getServerSession;
|
|
18
|
+
exports.protectRoute = protectRoute;
|
|
19
|
+
exports.createNextAuth = createNextAuth;
|
|
20
|
+
__exportStar(require("./types.js"), exports);
|
|
21
|
+
function parseCookieHeader(cookieHeader) {
|
|
22
|
+
const map = {};
|
|
23
|
+
if (!cookieHeader)
|
|
24
|
+
return map;
|
|
25
|
+
for (const part of cookieHeader.split(';')) {
|
|
26
|
+
const [name, ...val] = part.split('=');
|
|
27
|
+
const key = name?.trim();
|
|
28
|
+
if (key) {
|
|
29
|
+
map[key] = decodeURIComponent(val.join('=').trim());
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
return map;
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Retrieves and validates the current user session in Next.js Server Components,
|
|
36
|
+
* Server Actions, or Route Handlers.
|
|
37
|
+
*/
|
|
38
|
+
async function getServerSession(client, options = {}) {
|
|
39
|
+
const cookieName = options.cookieName || 'cc_session';
|
|
40
|
+
let token;
|
|
41
|
+
// 1. Explicit cookie store passed in
|
|
42
|
+
if (options.cookieStore) {
|
|
43
|
+
token = options.cookieStore.get(cookieName)?.value;
|
|
44
|
+
}
|
|
45
|
+
// 2. Request object passed in
|
|
46
|
+
if (!token && options.request) {
|
|
47
|
+
if ('cookies' in options.request && typeof options.request.cookies?.get === 'function') {
|
|
48
|
+
token = options.request.cookies.get(cookieName)?.value;
|
|
49
|
+
}
|
|
50
|
+
if (!token && options.request.headers) {
|
|
51
|
+
const headers = options.request.headers;
|
|
52
|
+
let rawCookie;
|
|
53
|
+
let authHeader;
|
|
54
|
+
if ('get' in headers && typeof headers.get === 'function') {
|
|
55
|
+
rawCookie = headers.get('cookie');
|
|
56
|
+
authHeader = headers.get('authorization');
|
|
57
|
+
}
|
|
58
|
+
else {
|
|
59
|
+
const record = headers;
|
|
60
|
+
rawCookie = record['cookie'];
|
|
61
|
+
authHeader = record['authorization'];
|
|
62
|
+
}
|
|
63
|
+
if (rawCookie) {
|
|
64
|
+
token = parseCookieHeader(rawCookie)[cookieName];
|
|
65
|
+
}
|
|
66
|
+
if (!token && authHeader && authHeader.startsWith('Bearer ')) {
|
|
67
|
+
token = authHeader.slice(7).trim();
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
// 3. Dynamic next/headers import fallback (for Next.js App Router server components)
|
|
72
|
+
if (!token) {
|
|
73
|
+
try {
|
|
74
|
+
// Dynamic import to avoid hard dependency on next
|
|
75
|
+
// @ts-ignore
|
|
76
|
+
const nextHeaders = await import('next/headers');
|
|
77
|
+
if (typeof nextHeaders.cookies === 'function') {
|
|
78
|
+
const cookies = await nextHeaders.cookies();
|
|
79
|
+
token = cookies?.get?.(cookieName)?.value;
|
|
80
|
+
}
|
|
81
|
+
}
|
|
82
|
+
catch {
|
|
83
|
+
// Ignored if outside of Next.js server execution context
|
|
84
|
+
}
|
|
85
|
+
}
|
|
86
|
+
if (!token) {
|
|
87
|
+
return null;
|
|
88
|
+
}
|
|
89
|
+
// Verify HMAC-signed or base64 cookie
|
|
90
|
+
const verified = client.verifySessionCookie(token);
|
|
91
|
+
if (verified) {
|
|
92
|
+
return verified;
|
|
93
|
+
}
|
|
94
|
+
// Remote verification fallback with Identity server
|
|
95
|
+
return await client.verifySession(token);
|
|
96
|
+
}
|
|
97
|
+
/**
|
|
98
|
+
* Guard utility for Next.js Route Handlers and Server Actions.
|
|
99
|
+
* Returns { authorized: true, session } or { authorized: false, response }.
|
|
100
|
+
*/
|
|
101
|
+
async function protectRoute(client, options = {}) {
|
|
102
|
+
const session = await getServerSession(client, options);
|
|
103
|
+
if (!session) {
|
|
104
|
+
if (options.redirectOnUnauthorized) {
|
|
105
|
+
const returnTo = options.returnTo || '/';
|
|
106
|
+
const redirectUrl = client.getLoginUrl({ returnTo });
|
|
107
|
+
return {
|
|
108
|
+
authorized: false,
|
|
109
|
+
session: null,
|
|
110
|
+
response: Response.redirect(redirectUrl, 307),
|
|
111
|
+
};
|
|
112
|
+
}
|
|
113
|
+
return {
|
|
114
|
+
authorized: false,
|
|
115
|
+
session: null,
|
|
116
|
+
response: new Response(JSON.stringify({ error: 'Unauthorized', message: 'Authentication required' }), { status: 401, headers: { 'Content-Type': 'application/json' } }),
|
|
117
|
+
};
|
|
118
|
+
}
|
|
119
|
+
// Check permissions if specified
|
|
120
|
+
if (options.permission) {
|
|
121
|
+
const granted = session.permissions || [];
|
|
122
|
+
let hasPerm = false;
|
|
123
|
+
if (Array.isArray(options.permission)) {
|
|
124
|
+
hasPerm =
|
|
125
|
+
options.requireAllPermissions !== false
|
|
126
|
+
? client.hasAllPermissions(granted, options.permission)
|
|
127
|
+
: client.hasAnyPermission(granted, options.permission);
|
|
128
|
+
}
|
|
129
|
+
else {
|
|
130
|
+
hasPerm = client.hasPermission(granted, options.permission);
|
|
131
|
+
}
|
|
132
|
+
if (!hasPerm) {
|
|
133
|
+
return {
|
|
134
|
+
authorized: false,
|
|
135
|
+
session,
|
|
136
|
+
response: new Response(JSON.stringify({
|
|
137
|
+
error: 'Forbidden',
|
|
138
|
+
message: `Missing required permission: ${Array.isArray(options.permission) ? options.permission.join(', ') : options.permission}`,
|
|
139
|
+
required: options.permission,
|
|
140
|
+
granted,
|
|
141
|
+
}), { status: 403, headers: { 'Content-Type': 'application/json' } }),
|
|
142
|
+
};
|
|
143
|
+
}
|
|
144
|
+
}
|
|
145
|
+
// Check roles if specified
|
|
146
|
+
if (options.role) {
|
|
147
|
+
const grantedRoles = session.roles || [];
|
|
148
|
+
const hasRole = Array.isArray(options.role)
|
|
149
|
+
? client.hasAnyRole(grantedRoles, options.role)
|
|
150
|
+
: client.hasRole(grantedRoles, options.role);
|
|
151
|
+
if (!hasRole) {
|
|
152
|
+
return {
|
|
153
|
+
authorized: false,
|
|
154
|
+
session,
|
|
155
|
+
response: new Response(JSON.stringify({
|
|
156
|
+
error: 'Forbidden',
|
|
157
|
+
message: `Missing required role: ${Array.isArray(options.role) ? options.role.join(', ') : options.role}`,
|
|
158
|
+
required: options.role,
|
|
159
|
+
granted: grantedRoles,
|
|
160
|
+
}), { status: 403, headers: { 'Content-Type': 'application/json' } }),
|
|
161
|
+
};
|
|
162
|
+
}
|
|
163
|
+
}
|
|
164
|
+
return { authorized: true, session };
|
|
165
|
+
}
|
|
166
|
+
/**
|
|
167
|
+
* Creates a configured Next.js Auth helper instance.
|
|
168
|
+
*/
|
|
169
|
+
function createNextAuth(client, defaultOptions) {
|
|
170
|
+
return {
|
|
171
|
+
client,
|
|
172
|
+
getServerSession: (options) => getServerSession(client, { ...defaultOptions, ...options }),
|
|
173
|
+
protectRoute: (options) => protectRoute(client, { ...defaultOptions, ...options }),
|
|
174
|
+
getLoginUrl: (options) => client.getLoginUrl(options),
|
|
175
|
+
getLogoutUrl: (returnTo) => client.getLogoutUrl(returnTo),
|
|
176
|
+
};
|
|
177
|
+
}
|
|
178
|
+
//# sourceMappingURL=index.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../src/nextjs/index.ts"],"names":[],"mappings":"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"}
|