@lanonasis/oauth-client 1.2.8 → 2.0.3

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.
@@ -0,0 +1,169 @@
1
+ "use strict";
2
+ var __defProp = Object.defineProperty;
3
+ var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
4
+ var __getOwnPropNames = Object.getOwnPropertyNames;
5
+ var __hasOwnProp = Object.prototype.hasOwnProperty;
6
+ var __export = (target, all) => {
7
+ for (var name in all)
8
+ __defProp(target, name, { get: all[name], enumerable: true });
9
+ };
10
+ var __copyProps = (to, from, except, desc) => {
11
+ if (from && typeof from === "object" || typeof from === "function") {
12
+ for (let key of __getOwnPropNames(from))
13
+ if (!__hasOwnProp.call(to, key) && key !== except)
14
+ __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
15
+ }
16
+ return to;
17
+ };
18
+ var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
19
+
20
+ // src/server/index.ts
21
+ var server_exports = {};
22
+ __export(server_exports, {
23
+ COOKIE_NAMES: () => COOKIE_NAMES,
24
+ DEFAULT_AUTH_GATEWAY: () => DEFAULT_AUTH_GATEWAY,
25
+ DEFAULT_COOKIE_DOMAIN: () => DEFAULT_COOKIE_DOMAIN,
26
+ DEFAULT_PROJECT_SCOPE: () => DEFAULT_PROJECT_SCOPE,
27
+ getSSOUserFromRequest: () => getSSOUserFromRequest,
28
+ getSessionToken: () => getSessionToken,
29
+ getSessionTokenFromRequest: () => getSessionTokenFromRequest,
30
+ hasAuthCookiesServer: () => hasAuthCookiesServer,
31
+ hasSSOfromRequest: () => hasSSOfromRequest,
32
+ hasSessionCookieServer: () => hasSessionCookieServer,
33
+ optionalAuth: () => optionalAuth,
34
+ parseCookieHeader: () => parseCookieHeader,
35
+ parseUserCookieServer: () => parseUserCookieServer,
36
+ requireAuth: () => requireAuth,
37
+ requireRole: () => requireRole,
38
+ validateSessionMiddleware: () => validateSessionMiddleware
39
+ });
40
+ module.exports = __toCommonJS(server_exports);
41
+
42
+ // src/cookies/constants.ts
43
+ var COOKIE_NAMES = {
44
+ /** HttpOnly JWT session token */
45
+ SESSION: "lanonasis_session",
46
+ /** Readable user metadata (JSON) */
47
+ USER: "lanonasis_user"
48
+ };
49
+ var DEFAULT_COOKIE_DOMAIN = ".lanonasis.com";
50
+ var DEFAULT_AUTH_GATEWAY = "https://auth.lanonasis.com";
51
+ var DEFAULT_PROJECT_SCOPE = "lanonasis-maas";
52
+
53
+ // src/server/cookie-utils.ts
54
+ function parseCookieHeader(cookieHeader) {
55
+ if (!cookieHeader) return {};
56
+ const cookies = {};
57
+ const pairs = cookieHeader.split(";");
58
+ for (const pair of pairs) {
59
+ const [name, ...valueParts] = pair.trim().split("=");
60
+ if (name) {
61
+ cookies[name.trim()] = valueParts.join("=").trim();
62
+ }
63
+ }
64
+ return cookies;
65
+ }
66
+ function getSessionToken(cookies) {
67
+ if (!cookies) return null;
68
+ const parsed = typeof cookies === "string" ? parseCookieHeader(cookies) : cookies;
69
+ const token = parsed[COOKIE_NAMES.SESSION];
70
+ return token || null;
71
+ }
72
+ function parseUserCookieServer(cookies) {
73
+ if (!cookies) return null;
74
+ try {
75
+ const parsed = typeof cookies === "string" ? parseCookieHeader(cookies) : cookies;
76
+ const userCookie = parsed[COOKIE_NAMES.USER];
77
+ if (!userCookie) return null;
78
+ const decoded = decodeURIComponent(userCookie);
79
+ const user = JSON.parse(decoded);
80
+ if (!user.id || !user.email || !user.role) {
81
+ console.warn("[oauth-client/server] Invalid user cookie: missing required fields");
82
+ return null;
83
+ }
84
+ return user;
85
+ } catch (error) {
86
+ console.warn("[oauth-client/server] Failed to parse user cookie:", error);
87
+ return null;
88
+ }
89
+ }
90
+ function hasSessionCookieServer(cookies) {
91
+ if (!cookies) return false;
92
+ const parsed = typeof cookies === "string" ? parseCookieHeader(cookies) : cookies;
93
+ return COOKIE_NAMES.SESSION in parsed && !!parsed[COOKIE_NAMES.SESSION];
94
+ }
95
+ function hasAuthCookiesServer(cookies) {
96
+ return hasSessionCookieServer(cookies) && parseUserCookieServer(cookies) !== null;
97
+ }
98
+ function getSSOUserFromRequest(req) {
99
+ if (req.cookies) {
100
+ return parseUserCookieServer(req.cookies);
101
+ }
102
+ return parseUserCookieServer(req.headers?.cookie);
103
+ }
104
+ function getSessionTokenFromRequest(req) {
105
+ if (req.cookies) {
106
+ return getSessionToken(req.cookies);
107
+ }
108
+ return getSessionToken(req.headers?.cookie);
109
+ }
110
+ function hasSSOfromRequest(req) {
111
+ if (req.cookies) {
112
+ return hasAuthCookiesServer(req.cookies);
113
+ }
114
+ return hasAuthCookiesServer(req.headers?.cookie);
115
+ }
116
+
117
+ // src/server/middleware.ts
118
+ function validateSessionMiddleware(config = {}) {
119
+ const {
120
+ cookieDomain = DEFAULT_COOKIE_DOMAIN,
121
+ allowAnonymous = false
122
+ } = config;
123
+ return (req, res, next) => {
124
+ if (hasSSOfromRequest(req)) {
125
+ const user = getSSOUserFromRequest(req);
126
+ if (user) {
127
+ req.user = user;
128
+ return next();
129
+ }
130
+ }
131
+ if (allowAnonymous) {
132
+ return next();
133
+ }
134
+ res.clearCookie(COOKIE_NAMES.SESSION, { domain: cookieDomain, path: "/" });
135
+ res.clearCookie(COOKIE_NAMES.USER, { domain: cookieDomain, path: "/" });
136
+ return res.status(401).json({
137
+ error: "Authentication required",
138
+ code: "AUTH_REQUIRED",
139
+ login_url: `${config.authGatewayUrl || DEFAULT_AUTH_GATEWAY}/web/login`
140
+ });
141
+ };
142
+ }
143
+ function requireAuth(config = {}) {
144
+ return validateSessionMiddleware({ ...config, allowAnonymous: false });
145
+ }
146
+ function optionalAuth(config = {}) {
147
+ return validateSessionMiddleware({ ...config, allowAnonymous: true });
148
+ }
149
+ function requireRole(role, config = {}) {
150
+ const roles = Array.isArray(role) ? role : [role];
151
+ return (req, res, next) => {
152
+ if (!req.user) {
153
+ return res.status(401).json({
154
+ error: "Authentication required",
155
+ code: "AUTH_REQUIRED",
156
+ login_url: `${config.authGatewayUrl || DEFAULT_AUTH_GATEWAY}/web/login`
157
+ });
158
+ }
159
+ if (!roles.includes(req.user.role)) {
160
+ return res.status(403).json({
161
+ error: "Insufficient permissions",
162
+ code: "FORBIDDEN",
163
+ required_role: roles,
164
+ current_role: req.user.role
165
+ });
166
+ }
167
+ return next();
168
+ };
169
+ }
@@ -0,0 +1,184 @@
1
+ import { d as SSOUser } from '../constants-BZPTHasL.cjs';
2
+ export { C as COOKIE_NAMES, D as DEFAULT_AUTH_GATEWAY, e as DEFAULT_COOKIE_DOMAIN, g as DEFAULT_PROJECT_SCOPE } from '../constants-BZPTHasL.cjs';
3
+
4
+ /**
5
+ * Server-side types for SSO authentication
6
+ * @module @lanonasis/oauth-client/server
7
+ */
8
+
9
+ /**
10
+ * Express-like request interface for middleware compatibility
11
+ */
12
+ interface ServerRequest {
13
+ cookies?: Record<string, string>;
14
+ headers?: {
15
+ cookie?: string;
16
+ authorization?: string;
17
+ 'x-api-key'?: string;
18
+ [key: string]: string | string[] | undefined;
19
+ };
20
+ user?: SSOUser;
21
+ }
22
+ /**
23
+ * Express-like response interface
24
+ */
25
+ interface ServerResponse {
26
+ status: (code: number) => ServerResponse;
27
+ json: (data: unknown) => void;
28
+ clearCookie: (name: string, options?: CookieOptions) => void;
29
+ }
30
+ /**
31
+ * Express-like next function
32
+ */
33
+ type NextFunction = (error?: Error) => void;
34
+ /**
35
+ * Cookie options for clearCookie
36
+ */
37
+ interface CookieOptions {
38
+ domain?: string;
39
+ path?: string;
40
+ }
41
+ /**
42
+ * Middleware configuration
43
+ */
44
+ interface MiddlewareConfig {
45
+ /** Auth gateway URL for token validation */
46
+ authGatewayUrl?: string;
47
+ /** Project scope for multi-tenant auth */
48
+ projectScope?: string;
49
+ /** Cookie domain (default: .lanonasis.com) */
50
+ cookieDomain?: string;
51
+ /** Allow unauthenticated requests to pass through */
52
+ allowAnonymous?: boolean;
53
+ }
54
+ /**
55
+ * Validation result for auth checks
56
+ */
57
+ interface AuthValidationResult {
58
+ valid: boolean;
59
+ user?: SSOUser;
60
+ error?: string;
61
+ }
62
+
63
+ /**
64
+ * Server-side cookie utilities for SSO authentication
65
+ * Use these utilities in Express/Node.js server middleware
66
+ *
67
+ * @module @lanonasis/oauth-client/server
68
+ */
69
+
70
+ /**
71
+ * Parse cookies from a cookie string (from request headers)
72
+ * @param cookieHeader - The Cookie header value (e.g., "name=value; name2=value2")
73
+ * @returns Object mapping cookie names to values
74
+ */
75
+ declare function parseCookieHeader(cookieHeader: string | undefined): Record<string, string>;
76
+ /**
77
+ * Get the session token from cookies (request.cookies or cookie header)
78
+ * @param cookies - Parsed cookies object or cookie header string
79
+ * @returns The session token or null
80
+ */
81
+ declare function getSessionToken(cookies: Record<string, string> | string | undefined): string | null;
82
+ /**
83
+ * Parse the user cookie from server-side request
84
+ * @param cookies - Parsed cookies object or cookie header string
85
+ * @returns User data or null if cookie doesn't exist or is invalid
86
+ */
87
+ declare function parseUserCookieServer(cookies: Record<string, string> | string | undefined): SSOUser | null;
88
+ /**
89
+ * Check if session cookie exists in the cookies
90
+ * @param cookies - Parsed cookies object or cookie header string
91
+ * @returns true if lanonasis_session cookie exists
92
+ */
93
+ declare function hasSessionCookieServer(cookies: Record<string, string> | string | undefined): boolean;
94
+ /**
95
+ * Check if user appears to be authenticated based on cookies (server-side)
96
+ * @param cookies - Parsed cookies object or cookie header string
97
+ * @returns true if both session and user cookies exist
98
+ */
99
+ declare function hasAuthCookiesServer(cookies: Record<string, string> | string | undefined): boolean;
100
+ /**
101
+ * Get SSO user from Express request (checks req.cookies first, then cookie header)
102
+ * @param req - Express-like request object
103
+ * @returns User data or null
104
+ */
105
+ declare function getSSOUserFromRequest(req: ServerRequest): SSOUser | null;
106
+ /**
107
+ * Get session token from Express request
108
+ * @param req - Express-like request object
109
+ * @returns Session token or null
110
+ */
111
+ declare function getSessionTokenFromRequest(req: ServerRequest): string | null;
112
+ /**
113
+ * Check if request has SSO authentication
114
+ * @param req - Express-like request object
115
+ * @returns true if SSO cookies are present
116
+ */
117
+ declare function hasSSOfromRequest(req: ServerRequest): boolean;
118
+
119
+ /**
120
+ * Express middleware for SSO authentication
121
+ * @module @lanonasis/oauth-client/server
122
+ */
123
+
124
+ /**
125
+ * Create a middleware that validates SSO session cookies
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * import { validateSessionMiddleware } from '@lanonasis/oauth-client/server';
130
+ *
131
+ * const auth = validateSessionMiddleware({
132
+ * authGatewayUrl: process.env.AUTH_GATEWAY_URL,
133
+ * projectScope: 'my-app'
134
+ * });
135
+ *
136
+ * app.use('/api', auth);
137
+ * ```
138
+ */
139
+ declare function validateSessionMiddleware(config?: MiddlewareConfig): (req: ServerRequest, res: ServerResponse, next: NextFunction) => void;
140
+ /**
141
+ * Middleware that requires authentication (returns 401 if not authenticated)
142
+ *
143
+ * @example
144
+ * ```typescript
145
+ * import { requireAuth } from '@lanonasis/oauth-client/server';
146
+ *
147
+ * app.get('/api/profile', requireAuth(), (req, res) => {
148
+ * res.json({ user: req.user });
149
+ * });
150
+ * ```
151
+ */
152
+ declare function requireAuth(config?: MiddlewareConfig): (req: ServerRequest, res: ServerResponse, next: NextFunction) => void;
153
+ /**
154
+ * Middleware that allows anonymous access but attaches user if authenticated
155
+ *
156
+ * @example
157
+ * ```typescript
158
+ * import { optionalAuth } from '@lanonasis/oauth-client/server';
159
+ *
160
+ * app.get('/api/public', optionalAuth(), (req, res) => {
161
+ * if (req.user) {
162
+ * res.json({ message: `Hello ${req.user.email}` });
163
+ * } else {
164
+ * res.json({ message: 'Hello guest' });
165
+ * }
166
+ * });
167
+ * ```
168
+ */
169
+ declare function optionalAuth(config?: MiddlewareConfig): (req: ServerRequest, res: ServerResponse, next: NextFunction) => void;
170
+ /**
171
+ * Middleware that requires a specific role
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * import { requireRole } from '@lanonasis/oauth-client/server';
176
+ *
177
+ * app.delete('/api/users/:id', requireRole('admin'), (req, res) => {
178
+ * // Only admins can delete users
179
+ * });
180
+ * ```
181
+ */
182
+ declare function requireRole(role: string | string[], config?: MiddlewareConfig): (req: ServerRequest, res: ServerResponse, next: NextFunction) => void;
183
+
184
+ export { type AuthValidationResult, type CookieOptions, type MiddlewareConfig, type NextFunction, SSOUser, type ServerRequest, type ServerResponse, getSSOUserFromRequest, getSessionToken, getSessionTokenFromRequest, hasAuthCookiesServer, hasSSOfromRequest, hasSessionCookieServer, optionalAuth, parseCookieHeader, parseUserCookieServer, requireAuth, requireRole, validateSessionMiddleware };
@@ -0,0 +1,184 @@
1
+ import { d as SSOUser } from '../constants-BZPTHasL.js';
2
+ export { C as COOKIE_NAMES, D as DEFAULT_AUTH_GATEWAY, e as DEFAULT_COOKIE_DOMAIN, g as DEFAULT_PROJECT_SCOPE } from '../constants-BZPTHasL.js';
3
+
4
+ /**
5
+ * Server-side types for SSO authentication
6
+ * @module @lanonasis/oauth-client/server
7
+ */
8
+
9
+ /**
10
+ * Express-like request interface for middleware compatibility
11
+ */
12
+ interface ServerRequest {
13
+ cookies?: Record<string, string>;
14
+ headers?: {
15
+ cookie?: string;
16
+ authorization?: string;
17
+ 'x-api-key'?: string;
18
+ [key: string]: string | string[] | undefined;
19
+ };
20
+ user?: SSOUser;
21
+ }
22
+ /**
23
+ * Express-like response interface
24
+ */
25
+ interface ServerResponse {
26
+ status: (code: number) => ServerResponse;
27
+ json: (data: unknown) => void;
28
+ clearCookie: (name: string, options?: CookieOptions) => void;
29
+ }
30
+ /**
31
+ * Express-like next function
32
+ */
33
+ type NextFunction = (error?: Error) => void;
34
+ /**
35
+ * Cookie options for clearCookie
36
+ */
37
+ interface CookieOptions {
38
+ domain?: string;
39
+ path?: string;
40
+ }
41
+ /**
42
+ * Middleware configuration
43
+ */
44
+ interface MiddlewareConfig {
45
+ /** Auth gateway URL for token validation */
46
+ authGatewayUrl?: string;
47
+ /** Project scope for multi-tenant auth */
48
+ projectScope?: string;
49
+ /** Cookie domain (default: .lanonasis.com) */
50
+ cookieDomain?: string;
51
+ /** Allow unauthenticated requests to pass through */
52
+ allowAnonymous?: boolean;
53
+ }
54
+ /**
55
+ * Validation result for auth checks
56
+ */
57
+ interface AuthValidationResult {
58
+ valid: boolean;
59
+ user?: SSOUser;
60
+ error?: string;
61
+ }
62
+
63
+ /**
64
+ * Server-side cookie utilities for SSO authentication
65
+ * Use these utilities in Express/Node.js server middleware
66
+ *
67
+ * @module @lanonasis/oauth-client/server
68
+ */
69
+
70
+ /**
71
+ * Parse cookies from a cookie string (from request headers)
72
+ * @param cookieHeader - The Cookie header value (e.g., "name=value; name2=value2")
73
+ * @returns Object mapping cookie names to values
74
+ */
75
+ declare function parseCookieHeader(cookieHeader: string | undefined): Record<string, string>;
76
+ /**
77
+ * Get the session token from cookies (request.cookies or cookie header)
78
+ * @param cookies - Parsed cookies object or cookie header string
79
+ * @returns The session token or null
80
+ */
81
+ declare function getSessionToken(cookies: Record<string, string> | string | undefined): string | null;
82
+ /**
83
+ * Parse the user cookie from server-side request
84
+ * @param cookies - Parsed cookies object or cookie header string
85
+ * @returns User data or null if cookie doesn't exist or is invalid
86
+ */
87
+ declare function parseUserCookieServer(cookies: Record<string, string> | string | undefined): SSOUser | null;
88
+ /**
89
+ * Check if session cookie exists in the cookies
90
+ * @param cookies - Parsed cookies object or cookie header string
91
+ * @returns true if lanonasis_session cookie exists
92
+ */
93
+ declare function hasSessionCookieServer(cookies: Record<string, string> | string | undefined): boolean;
94
+ /**
95
+ * Check if user appears to be authenticated based on cookies (server-side)
96
+ * @param cookies - Parsed cookies object or cookie header string
97
+ * @returns true if both session and user cookies exist
98
+ */
99
+ declare function hasAuthCookiesServer(cookies: Record<string, string> | string | undefined): boolean;
100
+ /**
101
+ * Get SSO user from Express request (checks req.cookies first, then cookie header)
102
+ * @param req - Express-like request object
103
+ * @returns User data or null
104
+ */
105
+ declare function getSSOUserFromRequest(req: ServerRequest): SSOUser | null;
106
+ /**
107
+ * Get session token from Express request
108
+ * @param req - Express-like request object
109
+ * @returns Session token or null
110
+ */
111
+ declare function getSessionTokenFromRequest(req: ServerRequest): string | null;
112
+ /**
113
+ * Check if request has SSO authentication
114
+ * @param req - Express-like request object
115
+ * @returns true if SSO cookies are present
116
+ */
117
+ declare function hasSSOfromRequest(req: ServerRequest): boolean;
118
+
119
+ /**
120
+ * Express middleware for SSO authentication
121
+ * @module @lanonasis/oauth-client/server
122
+ */
123
+
124
+ /**
125
+ * Create a middleware that validates SSO session cookies
126
+ *
127
+ * @example
128
+ * ```typescript
129
+ * import { validateSessionMiddleware } from '@lanonasis/oauth-client/server';
130
+ *
131
+ * const auth = validateSessionMiddleware({
132
+ * authGatewayUrl: process.env.AUTH_GATEWAY_URL,
133
+ * projectScope: 'my-app'
134
+ * });
135
+ *
136
+ * app.use('/api', auth);
137
+ * ```
138
+ */
139
+ declare function validateSessionMiddleware(config?: MiddlewareConfig): (req: ServerRequest, res: ServerResponse, next: NextFunction) => void;
140
+ /**
141
+ * Middleware that requires authentication (returns 401 if not authenticated)
142
+ *
143
+ * @example
144
+ * ```typescript
145
+ * import { requireAuth } from '@lanonasis/oauth-client/server';
146
+ *
147
+ * app.get('/api/profile', requireAuth(), (req, res) => {
148
+ * res.json({ user: req.user });
149
+ * });
150
+ * ```
151
+ */
152
+ declare function requireAuth(config?: MiddlewareConfig): (req: ServerRequest, res: ServerResponse, next: NextFunction) => void;
153
+ /**
154
+ * Middleware that allows anonymous access but attaches user if authenticated
155
+ *
156
+ * @example
157
+ * ```typescript
158
+ * import { optionalAuth } from '@lanonasis/oauth-client/server';
159
+ *
160
+ * app.get('/api/public', optionalAuth(), (req, res) => {
161
+ * if (req.user) {
162
+ * res.json({ message: `Hello ${req.user.email}` });
163
+ * } else {
164
+ * res.json({ message: 'Hello guest' });
165
+ * }
166
+ * });
167
+ * ```
168
+ */
169
+ declare function optionalAuth(config?: MiddlewareConfig): (req: ServerRequest, res: ServerResponse, next: NextFunction) => void;
170
+ /**
171
+ * Middleware that requires a specific role
172
+ *
173
+ * @example
174
+ * ```typescript
175
+ * import { requireRole } from '@lanonasis/oauth-client/server';
176
+ *
177
+ * app.delete('/api/users/:id', requireRole('admin'), (req, res) => {
178
+ * // Only admins can delete users
179
+ * });
180
+ * ```
181
+ */
182
+ declare function requireRole(role: string | string[], config?: MiddlewareConfig): (req: ServerRequest, res: ServerResponse, next: NextFunction) => void;
183
+
184
+ export { type AuthValidationResult, type CookieOptions, type MiddlewareConfig, type NextFunction, SSOUser, type ServerRequest, type ServerResponse, getSSOUserFromRequest, getSessionToken, getSessionTokenFromRequest, hasAuthCookiesServer, hasSSOfromRequest, hasSessionCookieServer, optionalAuth, parseCookieHeader, parseUserCookieServer, requireAuth, requireRole, validateSessionMiddleware };
@@ -0,0 +1,146 @@
1
+ // src/cookies/constants.ts
2
+ var COOKIE_NAMES = {
3
+ /** HttpOnly JWT session token */
4
+ SESSION: "lanonasis_session",
5
+ /** Readable user metadata (JSON) */
6
+ USER: "lanonasis_user"
7
+ };
8
+ var DEFAULT_COOKIE_DOMAIN = ".lanonasis.com";
9
+ var DEFAULT_AUTH_GATEWAY = "https://auth.lanonasis.com";
10
+ var DEFAULT_PROJECT_SCOPE = "lanonasis-maas";
11
+
12
+ // src/server/cookie-utils.ts
13
+ function parseCookieHeader(cookieHeader) {
14
+ if (!cookieHeader) return {};
15
+ const cookies = {};
16
+ const pairs = cookieHeader.split(";");
17
+ for (const pair of pairs) {
18
+ const [name, ...valueParts] = pair.trim().split("=");
19
+ if (name) {
20
+ cookies[name.trim()] = valueParts.join("=").trim();
21
+ }
22
+ }
23
+ return cookies;
24
+ }
25
+ function getSessionToken(cookies) {
26
+ if (!cookies) return null;
27
+ const parsed = typeof cookies === "string" ? parseCookieHeader(cookies) : cookies;
28
+ const token = parsed[COOKIE_NAMES.SESSION];
29
+ return token || null;
30
+ }
31
+ function parseUserCookieServer(cookies) {
32
+ if (!cookies) return null;
33
+ try {
34
+ const parsed = typeof cookies === "string" ? parseCookieHeader(cookies) : cookies;
35
+ const userCookie = parsed[COOKIE_NAMES.USER];
36
+ if (!userCookie) return null;
37
+ const decoded = decodeURIComponent(userCookie);
38
+ const user = JSON.parse(decoded);
39
+ if (!user.id || !user.email || !user.role) {
40
+ console.warn("[oauth-client/server] Invalid user cookie: missing required fields");
41
+ return null;
42
+ }
43
+ return user;
44
+ } catch (error) {
45
+ console.warn("[oauth-client/server] Failed to parse user cookie:", error);
46
+ return null;
47
+ }
48
+ }
49
+ function hasSessionCookieServer(cookies) {
50
+ if (!cookies) return false;
51
+ const parsed = typeof cookies === "string" ? parseCookieHeader(cookies) : cookies;
52
+ return COOKIE_NAMES.SESSION in parsed && !!parsed[COOKIE_NAMES.SESSION];
53
+ }
54
+ function hasAuthCookiesServer(cookies) {
55
+ return hasSessionCookieServer(cookies) && parseUserCookieServer(cookies) !== null;
56
+ }
57
+ function getSSOUserFromRequest(req) {
58
+ if (req.cookies) {
59
+ return parseUserCookieServer(req.cookies);
60
+ }
61
+ return parseUserCookieServer(req.headers?.cookie);
62
+ }
63
+ function getSessionTokenFromRequest(req) {
64
+ if (req.cookies) {
65
+ return getSessionToken(req.cookies);
66
+ }
67
+ return getSessionToken(req.headers?.cookie);
68
+ }
69
+ function hasSSOfromRequest(req) {
70
+ if (req.cookies) {
71
+ return hasAuthCookiesServer(req.cookies);
72
+ }
73
+ return hasAuthCookiesServer(req.headers?.cookie);
74
+ }
75
+
76
+ // src/server/middleware.ts
77
+ function validateSessionMiddleware(config = {}) {
78
+ const {
79
+ cookieDomain = DEFAULT_COOKIE_DOMAIN,
80
+ allowAnonymous = false
81
+ } = config;
82
+ return (req, res, next) => {
83
+ if (hasSSOfromRequest(req)) {
84
+ const user = getSSOUserFromRequest(req);
85
+ if (user) {
86
+ req.user = user;
87
+ return next();
88
+ }
89
+ }
90
+ if (allowAnonymous) {
91
+ return next();
92
+ }
93
+ res.clearCookie(COOKIE_NAMES.SESSION, { domain: cookieDomain, path: "/" });
94
+ res.clearCookie(COOKIE_NAMES.USER, { domain: cookieDomain, path: "/" });
95
+ return res.status(401).json({
96
+ error: "Authentication required",
97
+ code: "AUTH_REQUIRED",
98
+ login_url: `${config.authGatewayUrl || DEFAULT_AUTH_GATEWAY}/web/login`
99
+ });
100
+ };
101
+ }
102
+ function requireAuth(config = {}) {
103
+ return validateSessionMiddleware({ ...config, allowAnonymous: false });
104
+ }
105
+ function optionalAuth(config = {}) {
106
+ return validateSessionMiddleware({ ...config, allowAnonymous: true });
107
+ }
108
+ function requireRole(role, config = {}) {
109
+ const roles = Array.isArray(role) ? role : [role];
110
+ return (req, res, next) => {
111
+ if (!req.user) {
112
+ return res.status(401).json({
113
+ error: "Authentication required",
114
+ code: "AUTH_REQUIRED",
115
+ login_url: `${config.authGatewayUrl || DEFAULT_AUTH_GATEWAY}/web/login`
116
+ });
117
+ }
118
+ if (!roles.includes(req.user.role)) {
119
+ return res.status(403).json({
120
+ error: "Insufficient permissions",
121
+ code: "FORBIDDEN",
122
+ required_role: roles,
123
+ current_role: req.user.role
124
+ });
125
+ }
126
+ return next();
127
+ };
128
+ }
129
+ export {
130
+ COOKIE_NAMES,
131
+ DEFAULT_AUTH_GATEWAY,
132
+ DEFAULT_COOKIE_DOMAIN,
133
+ DEFAULT_PROJECT_SCOPE,
134
+ getSSOUserFromRequest,
135
+ getSessionToken,
136
+ getSessionTokenFromRequest,
137
+ hasAuthCookiesServer,
138
+ hasSSOfromRequest,
139
+ hasSessionCookieServer,
140
+ optionalAuth,
141
+ parseCookieHeader,
142
+ parseUserCookieServer,
143
+ requireAuth,
144
+ requireRole,
145
+ validateSessionMiddleware
146
+ };