@gneiss/client-auth 1.2.2 → 1.2.4
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/cjs/index.cjs +52 -25
- package/dist/cjs/index.cjs.map +3 -3
- package/dist/esm/index.mjs +52 -25
- package/dist/esm/index.mjs.map +3 -3
- package/dist/types/src/core/AuthGneissCore.d.ts +1 -0
- package/dist/types/src/core/AuthGneissCore.d.ts.map +1 -1
- package/dist/types/src/frameworks/express/middleware/ExpressAuthGneissClient.d.ts +3 -3
- package/dist/types/src/frameworks/express/middleware/ExpressAuthGneissClient.d.ts.map +1 -1
- package/package.json +1 -1
package/dist/cjs/index.cjs
CHANGED
|
@@ -44,7 +44,7 @@ var import_axios2 = require("axios");
|
|
|
44
44
|
// src/config.ts
|
|
45
45
|
var config = {
|
|
46
46
|
authUrl: process.env.ENV === "prod" ? "https://auth.gneiss.io" : process.env.ENV === "staging" ? "https://auth.gneiss.io/testing" : "http://localhost:5000",
|
|
47
|
-
internalAuthUrl: process.env.ENV === "prod" ? "http://auth:
|
|
47
|
+
internalAuthUrl: process.env.ENV === "prod" ? "http://auth:5000" : process.env.ENV === "staging" ? "http://auth:5000/testing" : "http://auth:5000"
|
|
48
48
|
};
|
|
49
49
|
|
|
50
50
|
// src/core/AuthGneissCore.ts
|
|
@@ -57,7 +57,7 @@ var AuthGneissCore = class {
|
|
|
57
57
|
this.authUrl = this.config.authUrl;
|
|
58
58
|
this.internalAuthUrl = this.config.internalAuthUrl;
|
|
59
59
|
this.loginUrl = `${this.authUrl}/auth/login`;
|
|
60
|
-
this.logoutUrl = `${this.
|
|
60
|
+
this.logoutUrl = `${this.internalAuthUrl}/auth/logout`;
|
|
61
61
|
this.signupUrl = `${this.authUrl}/auth/register`;
|
|
62
62
|
this.callbackUrl = `${this.config.baseClientUrl}${this.config.callbackRoute}`;
|
|
63
63
|
let errorMsgs = [];
|
|
@@ -114,6 +114,17 @@ var AuthGneissCore = class {
|
|
|
114
114
|
return null;
|
|
115
115
|
}
|
|
116
116
|
}
|
|
117
|
+
async logout(accessToken) {
|
|
118
|
+
if (!this.logoutUrl) {
|
|
119
|
+
throw new Error("Logout URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.");
|
|
120
|
+
}
|
|
121
|
+
await import_axios.default.post(this.logoutUrl, {}, {
|
|
122
|
+
// Logout
|
|
123
|
+
headers: {
|
|
124
|
+
"Authorization": `Bearer ${accessToken}`
|
|
125
|
+
}
|
|
126
|
+
});
|
|
127
|
+
}
|
|
117
128
|
/**
|
|
118
129
|
* getUserData is a method that fetches user data using the access token.
|
|
119
130
|
* @param accessToken - The access token to be used for user data fetching.
|
|
@@ -258,7 +269,6 @@ function clearCookies(res) {
|
|
|
258
269
|
|
|
259
270
|
// src/frameworks/express/middleware/ExpressAuthGneissClient.ts
|
|
260
271
|
var import_axios3 = require("axios");
|
|
261
|
-
var import_axios4 = __toESM(require("axios"), 1);
|
|
262
272
|
var ExpressAuthGneissClient = class extends AuthGneissCore_default {
|
|
263
273
|
// 10 minutes
|
|
264
274
|
constructor(config2) {
|
|
@@ -267,8 +277,8 @@ var ExpressAuthGneissClient = class extends AuthGneissCore_default {
|
|
|
267
277
|
this.URL_STORE_TTL = 10 * 60 * 1e3;
|
|
268
278
|
this.requireAuth = this.requireAuth.bind(this);
|
|
269
279
|
this.handleCallBack = this.handleCallBack.bind(this);
|
|
270
|
-
this.
|
|
271
|
-
this.
|
|
280
|
+
this.loginUser = this.loginUser.bind(this);
|
|
281
|
+
this.logoutUser = this.logoutUser.bind(this);
|
|
272
282
|
this.getUser = this.getUser.bind(this);
|
|
273
283
|
this.deleteUser = this.deleteUser.bind(this);
|
|
274
284
|
this.getUserData = this.getUserData.bind(this);
|
|
@@ -320,11 +330,20 @@ var ExpressAuthGneissClient = class extends AuthGneissCore_default {
|
|
|
320
330
|
async getUser(req, res) {
|
|
321
331
|
const cookies = parseCookies(req);
|
|
322
332
|
const accessToken = cookies?.accessToken;
|
|
323
|
-
|
|
324
|
-
|
|
333
|
+
try {
|
|
334
|
+
const userData = await this.getUserData(accessToken);
|
|
335
|
+
res.status(200).send(userData);
|
|
336
|
+
} catch (error) {
|
|
337
|
+
if (error instanceof import_axios3.AxiosError) {
|
|
338
|
+
switch (error.response?.status) {
|
|
339
|
+
case 401:
|
|
340
|
+
res.redirect(401, this.loginUrl);
|
|
341
|
+
return;
|
|
342
|
+
}
|
|
343
|
+
}
|
|
344
|
+
console.error("Error in getUser utility function:", error);
|
|
345
|
+
res.status(500).send("Internal server error");
|
|
325
346
|
}
|
|
326
|
-
const userData = await this.getUserData(accessToken);
|
|
327
|
-
res.status(200).send(userData);
|
|
328
347
|
}
|
|
329
348
|
/**
|
|
330
349
|
* handleCallBack is a middleware function that handles the callback from the authentication service.
|
|
@@ -367,7 +386,7 @@ var ExpressAuthGneissClient = class extends AuthGneissCore_default {
|
|
|
367
386
|
* @param req - The request object.
|
|
368
387
|
* @param res - The response object.
|
|
369
388
|
*/
|
|
370
|
-
|
|
389
|
+
loginUser(req, res) {
|
|
371
390
|
try {
|
|
372
391
|
if (!this.loginUrl) {
|
|
373
392
|
throw new Error("Login URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.");
|
|
@@ -385,27 +404,23 @@ var ExpressAuthGneissClient = class extends AuthGneissCore_default {
|
|
|
385
404
|
}
|
|
386
405
|
}
|
|
387
406
|
/**
|
|
388
|
-
*
|
|
407
|
+
* logoutUser is a function that redirects the user to the Gneiss logout service.
|
|
389
408
|
* @param req - The request object.
|
|
390
409
|
* @param res - The response object.
|
|
391
410
|
*/
|
|
392
|
-
|
|
411
|
+
logoutUser(req, res) {
|
|
393
412
|
const cookies = parseCookies(req);
|
|
394
413
|
try {
|
|
395
|
-
|
|
396
|
-
throw new Error("Logout URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.");
|
|
397
|
-
}
|
|
398
|
-
if (cookies?.accessToken) {
|
|
399
|
-
import_axios4.default.post(this.logoutUrl, {}, {
|
|
400
|
-
// Logout
|
|
401
|
-
headers: {
|
|
402
|
-
"Authorization": `Bearer ${cookies?.accessToken}`
|
|
403
|
-
}
|
|
404
|
-
});
|
|
405
|
-
}
|
|
414
|
+
this.logout(cookies?.accessToken);
|
|
406
415
|
clearCookies(res);
|
|
407
416
|
res.redirect("/");
|
|
408
417
|
} catch (error) {
|
|
418
|
+
if (error instanceof import_axios3.AxiosError) {
|
|
419
|
+
switch (error.response?.status) {
|
|
420
|
+
case 401:
|
|
421
|
+
res.redirect(401, this.loginUrl);
|
|
422
|
+
}
|
|
423
|
+
}
|
|
409
424
|
console.error("Error in logout middleware:", error);
|
|
410
425
|
res.status(500).send("Internal server error");
|
|
411
426
|
}
|
|
@@ -420,8 +435,20 @@ var ExpressAuthGneissClient = class extends AuthGneissCore_default {
|
|
|
420
435
|
*/
|
|
421
436
|
deleteUser(req, res) {
|
|
422
437
|
const cookies = parseCookies(req);
|
|
423
|
-
|
|
424
|
-
|
|
438
|
+
try {
|
|
439
|
+
this.logoutUser(req, res);
|
|
440
|
+
this.deleteUserData(cookies?.accessToken);
|
|
441
|
+
} catch (error) {
|
|
442
|
+
if (error instanceof import_axios3.AxiosError) {
|
|
443
|
+
switch (error.response?.status) {
|
|
444
|
+
case 401:
|
|
445
|
+
res.redirect(401, this.loginUrl);
|
|
446
|
+
return;
|
|
447
|
+
}
|
|
448
|
+
}
|
|
449
|
+
console.error("Error in deleteUser utility function:", error);
|
|
450
|
+
res.status(500).send("Internal server error");
|
|
451
|
+
}
|
|
425
452
|
}
|
|
426
453
|
};
|
|
427
454
|
var ExpressAuthGneissClient_default = ExpressAuthGneissClient;
|
package/dist/cjs/index.cjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/index.ts", "../../src/core/AuthGneissCore.ts", "../../src/config.ts", "../../src/utils/storage/cookieHandling.ts", "../../src/frameworks/express/middleware/ExpressAuthGneissClient.ts"],
|
|
4
|
-
"sourcesContent": ["export { ExpressAuthGneissClient } from \"./frameworks\";\nexport { AuthGneissCore } from \"./core\";\nexport { parseCookies } from \"@utils\"\nexport type { AuthGneissCoreConfig, AuthenticatedRequest } from \"./core\";\n\n", "import { AuthGneissCoreConfig } from \"@core/types\";\nimport axios, { AxiosResponse } from \"axios\";\nimport { Tokens } from \"@core/types\";\nimport dotenv from \"dotenv\";\nimport { AxiosError } from \"axios\";\nimport { config as genConfig } from \"@/config\";\nimport { AuthGneissGeneralConfig } from \"@/config\";\n\n//load environment variables if not already set\nif (!process.env.ENV) {\n dotenv.config();\n}\n\n/**\n * AuthGneissCore provides core functionality for OAuth2 authentication flow with Gneiss authentication service.\n * It handles token exchange, token refresh, user data fetching, and token validation.\n * \n * This class serves as a base class that can be extended by framework-specific implementations\n * to provide authentication middleware and handlers.\n */\nclass AuthGneissCore {\n protected config: AuthGneissCoreConfig & AuthGneissGeneralConfig; // Configuration object\n protected authUrl : string;\n protected loginUrl : string;\n protected logoutUrl : string;\n protected signupUrl : string;\n protected callbackUrl : string;\n protected internalAuthUrl : string;\n\n constructor(\n devConfig: AuthGneissCoreConfig,\n generalConfig: AuthGneissGeneralConfig = genConfig\n ) {\n\n this.config = {...devConfig, ...generalConfig};\n this.authUrl = this.config.authUrl; // Gneiss endpoint\n this.internalAuthUrl = this.config.internalAuthUrl;\n this.loginUrl = `${this.authUrl}/auth/login` // Login URL\n this.logoutUrl = `${this.authUrl}/auth/logout` // Logout URL\n this.signupUrl = `${this.authUrl}/auth/register` // Signup/register URL\n this.callbackUrl = `${this.config.baseClientUrl}${this.config.callbackRoute}`\n\n //check if environment variables are set\n let errorMsgs = [];\n if (!process.env.ENV) {\n errorMsgs.push(\"ENV is not set in environment variables\");\n }\n if (errorMsgs.length > 0) {\n throw new Error(errorMsgs.join(\"\\n\"));\n }\n }\n\n public getBase64EncodedCallbackUrl(): string {\n return Buffer.from(this.callbackUrl).toString('base64')\n }\n\n /**\n * getTokens is a method that exchanges an authentication code for access and refresh tokens.\n * The client id and secret are passed as basic auth headers to authenticate the client itself.\n * @param authCode - The authentication code received from the Gneiss authentication service.\n * @returns A promise that resolves to an object containing the access and refresh tokens.\n */\n protected async getTokens(authCode : string) : Promise<Tokens> {\n try {\n const url : string = `${this.internalAuthUrl}/auth/access_token?auth_code=${authCode}`;\n //Encode in base64 before transport\n const encodedClientId = btoa(this.config.clientId);\n const encodedClientSecret = btoa(this.config.clientSecret);\n const response : AxiosResponse = await axios.post(url, {}, {\n headers: {\n \"Authorization\": `Basic ${encodedClientId}:${encodedClientSecret}`\n }\n });\n return {\n accessToken: response.data.access_token,\n refreshToken: response.data.refresh_token,\n tokenType: response.data.token_type\n } as Tokens;\n } catch (error) {\n // console.error(\"Error in getTokens:\", error);\n throw error;\n }\n }\n \n /**\n * refreshToken is a method that refreshes the access token using the refresh token.\n * @param refreshToken - The refresh token to be used for token refresh.\n * @returns A promise that resolves to the refreshed access token.\n */\n protected async refreshToken(refreshToken: string): Promise<string | null> {\n try {\n const url : string = `${this.internalAuthUrl}/auth/refresh`;\n const response : AxiosResponse = await axios.post(url, {}, {\n headers: {\n \"Authorization\": `Bearer ${refreshToken}`\n }\n });\n return response.data.access_token as string;\n } catch (error) {\n // console.error(\"Error in refreshToken:\", error);\n return null;\n }\n }\n \n /**\n * getUserData is a method that fetches user data using the access token.\n * @param accessToken - The access token to be used for user data fetching.\n * @returns A promise that resolves to the user data.\n */\n public async getUserData(accessToken: string) {\n const url : string = `${this.internalAuthUrl}/resource/user_data`;\n const response : AxiosResponse = await axios.get(url, {\n headers: {\n \"Authorization\": `Bearer ${accessToken}`\n }\n });\n if (response.status === 200) {\n return response.data;\n }\n throw new Error(\"Failed to fetch user data\");\n }\n \n /**\n * validateToken is a method that validates the access token.\n * @param token - The access token to be validated.\n * @returns A promise that resolves to a boolean indicating the validity of the token.\n */\n protected async validateToken(token: string): Promise<boolean> {\n try {\n console.log(\"DEBUG: token\", token);\n // Token validation logic\n if (!token) {\n return false;\n }\n const url : string = `${this.internalAuthUrl}/auth/validate_token`;\n const response : AxiosResponse = await axios.get(url, {\n headers: {\n \"Authorization\": `Bearer ${token}`\n }\n });\n return response.status === 200;\n } catch (error) {\n // console.error(\"Error in validateToken:\", error);\n if (error instanceof AxiosError && error.response?.status === 401) {\n return false;\n } else {\n throw error;\n }\n }\n }\n\n /**\n * getLoginUrl is a method that returns the login URL.\n * @returns The login URL.\n */\n public getLoginUrl() : string | undefined {\n return this.loginUrl;\n }\n\n /**\n * Returns the base auth URL.\n * @returns The base auth URL.\n */\n public getAuthUrl(): string | undefined {\n return this.authUrl;\n }\n\n /**\n * Returns the logout URL.\n * @returns The logout URL.\n */\n public getLogoutUrl(): string | undefined {\n return this.logoutUrl;\n }\n\n /**\n * Returns the signup URL.\n * @returns The signup URL.\n */\n public getSignupUrl(): string | undefined {\n return this.signupUrl;\n }\n\n /**\n * deleteUser deletes the user\n * */\n protected async deleteUserData(accessToken : string) : Promise<object> {\n const response : AxiosResponse = await axios.post(`${this.internalAuthUrl}/resource/delete_user`, {}, {\n headers: {\n \"Authorization\": `Bearer ${accessToken}`\n } \n });\n return response.data;\n }\n}\n\nexport default AuthGneissCore;\n", "export type AuthGneissGeneralConfig = {\n authUrl: string // used by the browser\n internalAuthUrl: string // used internally within the same docker network\n}\n\nexport const config : AuthGneissGeneralConfig = {\n authUrl: process.env.ENV === \"prod\" ? \"https://auth.gneiss.io\" : \n process.env.ENV === \"staging\" ? \"https://auth.gneiss.io/testing\" : \"http://localhost:5000\",\n internalAuthUrl: process.env.ENV === \"prod\" ? \"http://auth:45443\" : \n process.env.ENV === \"staging\" ? \"http://auth:44443/testing\" : \"http://auth:5000\"\n}", "import { Response } from \"express\";\nimport { JwtPayload, decode } from \"jsonwebtoken\";\nimport { Request } from \"express\";\n\n// Helper to determine if we're in production\nconst isProduction = process.env.ENV === 'prod' || process.env.ENV === 'staging';\n\n// Cookie configuration\n// Note: SameSite=None requires Secure=true (HTTPS)\n// In dev, use SameSite=Lax with Angular proxy to avoid cross-origin issues\nconst cookieConfig = {\n httpOnly: true,\n secure: isProduction, // Only secure in production (HTTPS)\n sameSite: 'lax' as const, // Lax works for same-origin (Angular proxy in dev, Nginx in prod)\n};\n\n/**\n * Set the access token in the response cookies.\n * @param res - The response object.\n * @param accessToken - The access token to set.\n */\nfunction setAccessToken(res: Response, accessToken: string) {\n\n const decodedToken = decode(accessToken) as JwtPayload;\n \n // decoded.exp is in seconds since epoch\n // Date.now() returns milliseconds since epoch\n // maxAge needs milliseconds remaining\n if (!decodedToken.exp) {\n throw new Error(\"Access token does not contain an expiration time\");\n }\n \n res.cookie('accessToken', accessToken, {\n ...cookieConfig,\n maxAge: (decodedToken.exp * 1000) - Date.now()\n });\n}\n\n/**\n * Set the refresh token in the response cookies.\n * @param res - The response object.\n * @param refreshToken - The refresh token to set.\n */\nfunction setRefreshToken(res: Response, refreshToken: string) {\n\n const decodedToken = decode(refreshToken) as JwtPayload;\n\n if (!decodedToken.exp) {\n throw new Error(\"Refresh token does not contain an expiration time\");\n }\n\n res.cookie('refreshToken', refreshToken, {\n ...cookieConfig,\n maxAge: (decodedToken.exp * 1000) - Date.now()\n });\n}\n\nfunction parseCookies(req: Request) : { [key: string]: string } {\n const cookies = req.headers.cookie;\n if (!cookies) {\n return {};\n }\n return cookies.split(';').reduce((acc: { [key: string]: string }, cookie) => {\n const [key, value] = cookie.split('=').map(s => s.trim());\n acc[key] = value;\n return acc;\n }, {});\n}\n\n/**\n * Set the state token in the response cookies.\n * @param res - The response object.\n * @param stateToken - The state token to set.\n */\nfunction setUrlToken(res: Response, stateToken: string, exp: number) {\n\n\n res.cookie('urlToken', stateToken, {\n ...cookieConfig,\n maxAge: exp\n });\n}\n\nfunction clearCookies(res: Response) {\n const clearConfig = {\n ...cookieConfig,\n path: '/'\n };\n \n res.clearCookie(\"accessToken\", clearConfig);\n res.clearCookie(\"refreshToken\", clearConfig);\n res.clearCookie(\"urlToken\", clearConfig);\n}\n\nexport { setAccessToken, setRefreshToken, parseCookies, clearCookies, setUrlToken};\n", "import { AuthGneissCore, AuthGneissCoreConfig } from \"@core\";\nimport { Request, Response, NextFunction } from \"express\";\nimport { AuthenticatedRequest, Tokens } from \"@core/types\";\nimport { setAccessToken, setRefreshToken, parseCookies, setUrlToken} from \"@utils\";\nimport { AxiosError } from \"axios\";\nimport axios from \"axios\";\nimport { clearCookies } from \"@/utils/storage/cookieHandling\";\n\n\n/**\n * ExpressAuthGneissClient extends AuthGneissCore to provide Express-specific authentication middleware\n * and functionality for handling OAuth2 authentication flow with Gneiss authentication service.\n * \n * @extends AuthGneissCore\n * @example\n * const authClient = new ExpressAuthGneissClient({\n * clientId: 'your-client-id',\n * clientSecret: 'your-client-secret',\n * redirectUrl: 'your-redirect-url'\n * });\n */\nclass ExpressAuthGneissClient extends AuthGneissCore {\n\n private returnUrlStore = new Map<string, string>();\n private readonly URL_STORE_TTL = 10 * 60 * 1000; // 10 minutes\n\n constructor(\n config: AuthGneissCoreConfig\n ) {\n super(config);\n \n // Bind the methods in constructor\n this.requireAuth = this.requireAuth.bind(this);\n this.handleCallBack = this.handleCallBack.bind(this);\n this.login = this.login.bind(this);\n this.logout = this.logout.bind(this);\n this.getUser = this.getUser.bind(this);\n this.deleteUser = this.deleteUser.bind(this);\n this.getUserData = this.getUserData.bind(this);\n this.getLoginUrl = this.getLoginUrl.bind(this);\n this.getLogoutUrl = this.getLogoutUrl.bind(this);\n this.getSignupUrl = this.getSignupUrl.bind(this);\n this.getAuthUrl = this.getAuthUrl.bind(this);\n }\n\n /**\n /**\n * requireAuth is a middleware function that checks if the access token is valid.\n * If the access token is not valid, it attempts to refresh the token using the refresh token.\n * If the refresh token is not valid, it redirects the user to the login page.\n * @template UserT - The type of the user object to attach to the request.\n * @param req - The request object.\n * @param res - The response object.\n * @param next - The next middleware function.\n */\n public async requireAuth<UserT>(req: Request, res: Response, next: NextFunction): Promise<void> {\n const cookies = parseCookies(req);\n //Check for the existence of the access token\n // console.log(\"DEBUG: cookies\", cookies);\n try {\n const isAccessTokenValid : boolean = await this.validateToken(cookies?.accessToken);\n if (!isAccessTokenValid) { //if the access token is not valid\n //try to refresh the token\n const newAccessToken : string | null = await this.refreshToken(cookies?.refreshToken);\n if (newAccessToken) { // set access token and then call next to proceed to the next middleware/handler\n setAccessToken(res, newAccessToken);\n next()\n }\n else {\n // no access token or valid refresh token, redirect to login with 401 requires login credentials\n res.redirect(401, `${this.loginUrl}?redirect_url=${this.getBase64EncodedCallbackUrl()}`);\n }\n }\n else {\n // access token is valid, continue to the next middleware or route handler after adding user to req\n (req as AuthenticatedRequest<UserT>).user = await this.getUserData(cookies.accessToken);\n next();\n }\n } catch (error) {\n // console.error('Error in requireAuth middleware:', error);\n if (error instanceof AxiosError) {\n res.status((error as AxiosError).response?.status || 500).send((error as AxiosError).response?.data || 'Internal server error');\n } else {\n res.status(500).send('Internal server error');\n }\n }\n }\n\n /**\n * getUserData is a middleware function that fetches user data using the access token.\n * @param req - The request object.\n * @param res - The response object.\n * @param next - The next middleware function.\n */\n public async getUser(req: Request, res: Response): Promise<void> {\n const cookies = parseCookies(req);\n const accessToken = cookies?.accessToken;\n if (!accessToken) {\n throw new Error(\"No access token found in request cookies\");\n }\n const userData = await this.getUserData(accessToken);\n res.status(200).send(userData);\n }\n\n /**\n * handleCallBack is a middleware function that handles the callback from the authentication service.\n * It extracts the auth code from the request URL parameters, exchanges it for tokens, and sets the access and refresh tokens in the response cookies.\n * @param req - The request object.\n * @param res - The response object.\n * @param next - The next middleware function.\n */\n public async handleCallBack(\n req: Request,\n res: Response,\n next: NextFunction\n ): Promise<void> {\n\n const cookies = parseCookies(req);\n const returnToToken = cookies?.urlToken\n\n try {\n const authCode: string | undefined = req.query.auth_code as string;\n const returnToUrl = this.returnUrlStore.get(returnToToken);\n\n if (!authCode) {\n throw new Error(\"No auth code found in request url parameters\");\n }\n\n const tokens: Tokens = await this.getTokens(authCode);\n \n // Set the access and refresh tokens in the response cookies\n setAccessToken(res, tokens.accessToken);\n setRefreshToken(res, tokens.refreshToken);\n\n if (returnToUrl) {\n // Go to the original request url\n res.redirect(returnToUrl);\n }\n else {\n // Go to the root url\n res.redirect(\"/\")\n }\n } catch (error) {\n // console.error('Error in handleCallBack middleware:', error);\n if (error instanceof AxiosError) {\n res.status((error as AxiosError).response?.status || 500).send((error as AxiosError).response?.data || 'Internal server error');\n console.error(\"DEBUG: error\", error);\n } else {\n res.status(500).send('Internal server error');\n console.error(\"DEBUG: error\", error);\n }\n }\n }\n\n /**\n * login is a function that redirects the user to the Gneiss authentication service for authentication.\n * Accepts an optional returnTo query parameter to specify where to redirect after successful login.\n * Falls back to referer header if no returnTo is provided.\n * @param req - The request object.\n * @param res - The response object.\n */\n public login(req: Request, res: Response): void {\n try {\n if (!this.loginUrl) {\n throw new Error('Login URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.');\n }\n\n // Priority: query param > referer header > environment variable\n // In dev with proxy, referer will be the frontend URL (e.g., http://localhost:4200)\n // In staging, FRONTEND_URL should be set to staging frontend URL\n const returnToUrl = \n (req.query.returnTo as string) || \n req.get('referer') || \n process.env.FRONTEND_URL || \n '/'; // Fallback to root path (same origin)\n \n const urlToken = crypto.randomUUID();\n\n // Store the returnToUrl with auto-expiration\n this.returnUrlStore.set(urlToken, returnToUrl);\n setUrlToken(res, urlToken, this.URL_STORE_TTL);\n setTimeout(() => this.returnUrlStore.delete(urlToken), this.URL_STORE_TTL);\n\n //Base64 encode callback url\n const callbackUrl = this.getBase64EncodedCallbackUrl();\n\n res.redirect(this.loginUrl + `?redirect_url=${callbackUrl}`);\n } catch (error) {\n console.error('Error in login middleware:', error);\n res.status(500).send('Internal server error');\n }\n }\n\n /**\n * logout is a function that redirects the user to the Gneiss logout service.\n * @param req - The request object.\n * @param res - The response object.\n */\n public logout(req: Request, res: Response): void {\n const cookies = parseCookies(req);\n try {\n if (!this.logoutUrl) {\n throw new Error('Logout URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.');\n }\n if (cookies?.accessToken) { // Only logout if the access token exists\n axios.post(this.logoutUrl, {}, { // Logout\n headers: {\n \"Authorization\": `Bearer ${cookies?.accessToken}`\n }\n });\n }\n clearCookies(res); // clear the access and refresh cookies\n res.redirect(\"/\") // Redirect back to home after logout\n } catch (error) {\n console.error('Error in logout middleware:', error);\n res.status(500).send('Internal server error');\n }\n }\n\n /**\n * Utility route handler for deleting a user\n * This ensures that the user is fully logged out before \n * deleting the user's data\n * \n * @param req - The request object.\n * @param res - The response object.\n */\n public deleteUser(req: Request, res: Response) {\n const cookies = parseCookies(req);\n this.logout(req, res)\n this.deleteUserData(cookies?.accessToken)\n }\n}\n\nexport default ExpressAuthGneissClient;\n"],
|
|
5
|
-
"mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCA,mBAAqC;AAErC,oBAAmB;AACnB,IAAAA,gBAA2B;;;ACCpB,IAAM,SAAmC;AAAA,EAC5C,SAAS,QAAQ,IAAI,QAAQ,SAAS,2BACtC,QAAQ,IAAI,QAAQ,YAAY,mCAAmC;AAAA,EACnE,iBAAiB,QAAQ,IAAI,QAAQ,SAAS,
|
|
6
|
-
"names": ["import_axios", "dotenv", "axios", "import_axios", "config"
|
|
4
|
+
"sourcesContent": ["export { ExpressAuthGneissClient } from \"./frameworks\";\nexport { AuthGneissCore } from \"./core\";\nexport { parseCookies } from \"@utils\"\nexport type { AuthGneissCoreConfig, AuthenticatedRequest } from \"./core\";\n\n", "import { AuthGneissCoreConfig } from \"@core/types\";\nimport axios, { AxiosResponse } from \"axios\";\nimport { Tokens } from \"@core/types\";\nimport dotenv from \"dotenv\";\nimport { AxiosError } from \"axios\";\nimport { config as genConfig } from \"@/config\";\nimport { AuthGneissGeneralConfig } from \"@/config\";\n\n//load environment variables if not already set\nif (!process.env.ENV) {\n dotenv.config();\n}\n\n/**\n * AuthGneissCore provides core functionality for OAuth2 authentication flow with Gneiss authentication service.\n * It handles token exchange, token refresh, user data fetching, and token validation.\n * \n * This class serves as a base class that can be extended by framework-specific implementations\n * to provide authentication middleware and handlers.\n */\nclass AuthGneissCore {\n protected config: AuthGneissCoreConfig & AuthGneissGeneralConfig; // Configuration object\n protected authUrl : string;\n protected loginUrl : string;\n protected logoutUrl : string;\n protected signupUrl : string;\n protected callbackUrl : string;\n protected internalAuthUrl : string;\n\n constructor(\n devConfig: AuthGneissCoreConfig,\n generalConfig: AuthGneissGeneralConfig = genConfig\n ) {\n\n this.config = {...devConfig, ...generalConfig};\n this.authUrl = this.config.authUrl; // Gneiss endpoint\n this.internalAuthUrl = this.config.internalAuthUrl;\n this.loginUrl = `${this.authUrl}/auth/login` // Login URL\n this.logoutUrl = `${this.internalAuthUrl}/auth/logout` // Logout URL\n this.signupUrl = `${this.authUrl}/auth/register` // Signup/register URL\n this.callbackUrl = `${this.config.baseClientUrl}${this.config.callbackRoute}`\n\n //check if environment variables are set\n let errorMsgs = [];\n if (!process.env.ENV) {\n errorMsgs.push(\"ENV is not set in environment variables\");\n }\n if (errorMsgs.length > 0) {\n throw new Error(errorMsgs.join(\"\\n\"));\n }\n }\n\n public getBase64EncodedCallbackUrl(): string {\n return Buffer.from(this.callbackUrl).toString('base64')\n }\n\n /**\n * getTokens is a method that exchanges an authentication code for access and refresh tokens.\n * The client id and secret are passed as basic auth headers to authenticate the client itself.\n * @param authCode - The authentication code received from the Gneiss authentication service.\n * @returns A promise that resolves to an object containing the access and refresh tokens.\n */\n protected async getTokens(authCode : string) : Promise<Tokens> {\n try {\n const url : string = `${this.internalAuthUrl}/auth/access_token?auth_code=${authCode}`;\n //Encode in base64 before transport\n const encodedClientId = btoa(this.config.clientId);\n const encodedClientSecret = btoa(this.config.clientSecret);\n const response : AxiosResponse = await axios.post(url, {}, {\n headers: {\n \"Authorization\": `Basic ${encodedClientId}:${encodedClientSecret}`\n }\n });\n return {\n accessToken: response.data.access_token,\n refreshToken: response.data.refresh_token,\n tokenType: response.data.token_type\n } as Tokens;\n } catch (error) {\n // console.error(\"Error in getTokens:\", error);\n throw error;\n }\n }\n \n /**\n * refreshToken is a method that refreshes the access token using the refresh token.\n * @param refreshToken - The refresh token to be used for token refresh.\n * @returns A promise that resolves to the refreshed access token.\n */\n protected async refreshToken(refreshToken: string): Promise<string | null> {\n try {\n const url : string = `${this.internalAuthUrl}/auth/refresh`;\n const response : AxiosResponse = await axios.post(url, {}, {\n headers: {\n \"Authorization\": `Bearer ${refreshToken}`\n }\n });\n return response.data.access_token as string;\n } catch (error) {\n // console.error(\"Error in refreshToken:\", error);\n return null;\n }\n }\n\n protected async logout(accessToken : string) {\n if (!this.logoutUrl) {\n throw new Error('Logout URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.');\n }\n await axios.post(this.logoutUrl, {}, { // Logout\n headers: {\n \"Authorization\": `Bearer ${accessToken}`\n }\n });\n }\n \n /**\n * getUserData is a method that fetches user data using the access token.\n * @param accessToken - The access token to be used for user data fetching.\n * @returns A promise that resolves to the user data.\n */\n public async getUserData(accessToken: string) {\n const url : string = `${this.internalAuthUrl}/resource/user_data`;\n const response : AxiosResponse = await axios.get(url, {\n headers: {\n \"Authorization\": `Bearer ${accessToken}`\n }\n });\n if (response.status === 200) {\n return response.data;\n }\n throw new Error(\"Failed to fetch user data\");\n }\n \n /**\n * validateToken is a method that validates the access token.\n * @param token - The access token to be validated.\n * @returns A promise that resolves to a boolean indicating the validity of the token.\n */\n protected async validateToken(token: string): Promise<boolean> {\n try {\n console.log(\"DEBUG: token\", token);\n // Token validation logic\n if (!token) {\n return false;\n }\n const url : string = `${this.internalAuthUrl}/auth/validate_token`;\n const response : AxiosResponse = await axios.get(url, {\n headers: {\n \"Authorization\": `Bearer ${token}`\n }\n });\n return response.status === 200;\n } catch (error) {\n // console.error(\"Error in validateToken:\", error);\n if (error instanceof AxiosError && error.response?.status === 401) {\n return false;\n } else {\n throw error;\n }\n }\n }\n\n /**\n * getLoginUrl is a method that returns the login URL.\n * @returns The login URL.\n */\n public getLoginUrl() : string | undefined {\n return this.loginUrl;\n }\n\n /**\n * Returns the base auth URL.\n * @returns The base auth URL.\n */\n public getAuthUrl(): string | undefined {\n return this.authUrl;\n }\n\n /**\n * Returns the logout URL.\n * @returns The logout URL.\n */\n public getLogoutUrl(): string | undefined {\n return this.logoutUrl;\n }\n\n /**\n * Returns the signup URL.\n * @returns The signup URL.\n */\n public getSignupUrl(): string | undefined {\n return this.signupUrl;\n }\n\n /**\n * deleteUser deletes the user\n * */\n protected async deleteUserData(accessToken : string) : Promise<object> {\n const response : AxiosResponse = await axios.post(`${this.internalAuthUrl}/resource/delete_user`, {}, {\n headers: {\n \"Authorization\": `Bearer ${accessToken}`\n } \n });\n return response.data;\n }\n}\n\nexport default AuthGneissCore;\n", "export type AuthGneissGeneralConfig = {\n authUrl: string // used by the browser\n internalAuthUrl: string // used internally within the same docker network\n}\n\nexport const config : AuthGneissGeneralConfig = {\n authUrl: process.env.ENV === \"prod\" ? \"https://auth.gneiss.io\" : \n process.env.ENV === \"staging\" ? \"https://auth.gneiss.io/testing\" : \"http://localhost:5000\",\n internalAuthUrl: process.env.ENV === \"prod\" ? \"http://auth:5000\" : \n process.env.ENV === \"staging\" ? \"http://auth:5000/testing\" : \"http://auth:5000\"\n}", "import { Response } from \"express\";\nimport { JwtPayload, decode } from \"jsonwebtoken\";\nimport { Request } from \"express\";\n\n// Helper to determine if we're in production\nconst isProduction = process.env.ENV === 'prod' || process.env.ENV === 'staging';\n\n// Cookie configuration\n// Note: SameSite=None requires Secure=true (HTTPS)\n// In dev, use SameSite=Lax with Angular proxy to avoid cross-origin issues\nconst cookieConfig = {\n httpOnly: true,\n secure: isProduction, // Only secure in production (HTTPS)\n sameSite: 'lax' as const, // Lax works for same-origin (Angular proxy in dev, Nginx in prod)\n};\n\n/**\n * Set the access token in the response cookies.\n * @param res - The response object.\n * @param accessToken - The access token to set.\n */\nfunction setAccessToken(res: Response, accessToken: string) {\n\n const decodedToken = decode(accessToken) as JwtPayload;\n \n // decoded.exp is in seconds since epoch\n // Date.now() returns milliseconds since epoch\n // maxAge needs milliseconds remaining\n if (!decodedToken.exp) {\n throw new Error(\"Access token does not contain an expiration time\");\n }\n \n res.cookie('accessToken', accessToken, {\n ...cookieConfig,\n maxAge: (decodedToken.exp * 1000) - Date.now()\n });\n}\n\n/**\n * Set the refresh token in the response cookies.\n * @param res - The response object.\n * @param refreshToken - The refresh token to set.\n */\nfunction setRefreshToken(res: Response, refreshToken: string) {\n\n const decodedToken = decode(refreshToken) as JwtPayload;\n\n if (!decodedToken.exp) {\n throw new Error(\"Refresh token does not contain an expiration time\");\n }\n\n res.cookie('refreshToken', refreshToken, {\n ...cookieConfig,\n maxAge: (decodedToken.exp * 1000) - Date.now()\n });\n}\n\nfunction parseCookies(req: Request) : { [key: string]: string } {\n const cookies = req.headers.cookie;\n if (!cookies) {\n return {};\n }\n return cookies.split(';').reduce((acc: { [key: string]: string }, cookie) => {\n const [key, value] = cookie.split('=').map(s => s.trim());\n acc[key] = value;\n return acc;\n }, {});\n}\n\n/**\n * Set the state token in the response cookies.\n * @param res - The response object.\n * @param stateToken - The state token to set.\n */\nfunction setUrlToken(res: Response, stateToken: string, exp: number) {\n\n\n res.cookie('urlToken', stateToken, {\n ...cookieConfig,\n maxAge: exp\n });\n}\n\nfunction clearCookies(res: Response) {\n const clearConfig = {\n ...cookieConfig,\n path: '/'\n };\n \n res.clearCookie(\"accessToken\", clearConfig);\n res.clearCookie(\"refreshToken\", clearConfig);\n res.clearCookie(\"urlToken\", clearConfig);\n}\n\nexport { setAccessToken, setRefreshToken, parseCookies, clearCookies, setUrlToken};\n", "import { AuthGneissCore, AuthGneissCoreConfig } from \"@core\";\nimport { Request, Response, NextFunction } from \"express\";\nimport { AuthenticatedRequest, Tokens } from \"@core/types\";\nimport { setAccessToken, setRefreshToken, parseCookies, setUrlToken} from \"@utils\";\nimport { AxiosError } from \"axios\";\nimport axios from \"axios\";\nimport { clearCookies } from \"@/utils/storage/cookieHandling\";\n\n\n/**\n * ExpressAuthGneissClient extends AuthGneissCore to provide Express-specific authentication middleware\n * and functionality for handling OAuth2 authentication flow with Gneiss authentication service.\n * \n * @extends AuthGneissCore\n * @example\n * const authClient = new ExpressAuthGneissClient({\n * clientId: 'your-client-id',\n * clientSecret: 'your-client-secret',\n * redirectUrl: 'your-redirect-url'\n * });\n */\nclass ExpressAuthGneissClient extends AuthGneissCore {\n\n private returnUrlStore = new Map<string, string>();\n private readonly URL_STORE_TTL = 10 * 60 * 1000; // 10 minutes\n\n constructor(\n config: AuthGneissCoreConfig\n ) {\n super(config);\n \n // Bind the methods in constructor\n this.requireAuth = this.requireAuth.bind(this);\n this.handleCallBack = this.handleCallBack.bind(this);\n this.loginUser = this.loginUser.bind(this);\n this.logoutUser = this.logoutUser.bind(this);\n this.getUser = this.getUser.bind(this);\n this.deleteUser = this.deleteUser.bind(this);\n this.getUserData = this.getUserData.bind(this);\n this.getLoginUrl = this.getLoginUrl.bind(this);\n this.getLogoutUrl = this.getLogoutUrl.bind(this);\n this.getSignupUrl = this.getSignupUrl.bind(this);\n this.getAuthUrl = this.getAuthUrl.bind(this);\n }\n\n /**\n /**\n * requireAuth is a middleware function that checks if the access token is valid.\n * If the access token is not valid, it attempts to refresh the token using the refresh token.\n * If the refresh token is not valid, it redirects the user to the login page.\n * @template UserT - The type of the user object to attach to the request.\n * @param req - The request object.\n * @param res - The response object.\n * @param next - The next middleware function.\n */\n public async requireAuth<UserT>(req: Request, res: Response, next: NextFunction): Promise<void> {\n const cookies = parseCookies(req);\n //Check for the existence of the access token\n // console.log(\"DEBUG: cookies\", cookies);\n try {\n const isAccessTokenValid : boolean = await this.validateToken(cookies?.accessToken);\n if (!isAccessTokenValid) { //if the access token is not valid\n //try to refresh the token\n const newAccessToken : string | null = await this.refreshToken(cookies?.refreshToken);\n if (newAccessToken) { // set access token and then call next to proceed to the next middleware/handler\n setAccessToken(res, newAccessToken);\n next()\n }\n else {\n // no access token or valid refresh token, redirect to login with 401 requires login credentials\n res.redirect(401, `${this.loginUrl}?redirect_url=${this.getBase64EncodedCallbackUrl()}`);\n }\n }\n else {\n // access token is valid, continue to the next middleware or route handler after adding user to req\n (req as AuthenticatedRequest<UserT>).user = await this.getUserData(cookies.accessToken);\n next();\n }\n } catch (error) {\n // console.error('Error in requireAuth middleware:', error);\n if (error instanceof AxiosError) {\n res.status((error as AxiosError).response?.status || 500).send((error as AxiosError).response?.data || 'Internal server error');\n } else {\n res.status(500).send('Internal server error');\n }\n }\n }\n\n /**\n * getUserData is a middleware function that fetches user data using the access token.\n * @param req - The request object.\n * @param res - The response object.\n * @param next - The next middleware function.\n */\n public async getUser(req: Request, res: Response): Promise<void> {\n const cookies = parseCookies(req);\n const accessToken = cookies?.accessToken;\n try {\n const userData = await this.getUserData(accessToken);\n res.status(200).send(userData);\n } catch (error) {\n if (error instanceof AxiosError) {\n switch (error.response?.status) {\n case 401:\n res.redirect(401, this.loginUrl);\n return;\n }\n }\n console.error('Error in getUser utility function:', error);\n res.status(500).send('Internal server error');\n }\n }\n\n /**\n * handleCallBack is a middleware function that handles the callback from the authentication service.\n * It extracts the auth code from the request URL parameters, exchanges it for tokens, and sets the access and refresh tokens in the response cookies.\n * @param req - The request object.\n * @param res - The response object.\n * @param next - The next middleware function.\n */\n public async handleCallBack(\n req: Request,\n res: Response,\n next: NextFunction\n ): Promise<void> {\n\n const cookies = parseCookies(req);\n const returnToToken = cookies?.urlToken\n\n try {\n const authCode: string | undefined = req.query.auth_code as string;\n const returnToUrl = this.returnUrlStore.get(returnToToken);\n\n if (!authCode) {\n throw new Error(\"No auth code found in request url parameters\");\n }\n\n const tokens: Tokens = await this.getTokens(authCode);\n \n // Set the access and refresh tokens in the response cookies\n setAccessToken(res, tokens.accessToken);\n setRefreshToken(res, tokens.refreshToken);\n\n if (returnToUrl) {\n // Go to the original request url\n res.redirect(returnToUrl);\n }\n else {\n // Go to the root url\n res.redirect(\"/\")\n }\n } catch (error) {\n // console.error('Error in handleCallBack middleware:', error);\n if (error instanceof AxiosError) {\n res.status((error as AxiosError).response?.status || 500).send((error as AxiosError).response?.data || 'Internal server error');\n console.error(\"DEBUG: error\", error);\n } else {\n res.status(500).send('Internal server error');\n console.error(\"DEBUG: error\", error);\n }\n }\n }\n\n /**\n * login is a function that redirects the user to the Gneiss authentication service for authentication.\n * Accepts an optional returnTo query parameter to specify where to redirect after successful login.\n * Falls back to referer header if no returnTo is provided.\n * @param req - The request object.\n * @param res - The response object.\n */\n public loginUser(req: Request, res: Response): void {\n try {\n if (!this.loginUrl) {\n throw new Error('Login URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.');\n }\n\n // Priority: query param > referer header > environment variable\n // In dev with proxy, referer will be the frontend URL (e.g., http://localhost:4200)\n // In staging, FRONTEND_URL should be set to staging frontend URL\n const returnToUrl = \n (req.query.returnTo as string) || \n req.get('referer') || \n process.env.FRONTEND_URL || \n '/'; // Fallback to root path (same origin)\n \n const urlToken = crypto.randomUUID();\n\n // Store the returnToUrl with auto-expiration\n this.returnUrlStore.set(urlToken, returnToUrl);\n setUrlToken(res, urlToken, this.URL_STORE_TTL);\n setTimeout(() => this.returnUrlStore.delete(urlToken), this.URL_STORE_TTL);\n\n //Base64 encode callback url\n const callbackUrl = this.getBase64EncodedCallbackUrl();\n\n res.redirect(this.loginUrl + `?redirect_url=${callbackUrl}`);\n } catch (error) {\n console.error('Error in login middleware:', error);\n res.status(500).send('Internal server error');\n }\n }\n\n /**\n * logoutUser is a function that redirects the user to the Gneiss logout service.\n * @param req - The request object.\n * @param res - The response object.\n */\n public logoutUser(req: Request, res: Response): void {\n const cookies = parseCookies(req);\n try {\n this.logout(cookies?.accessToken)\n clearCookies(res); // clear the access and refresh cookies\n res.redirect(\"/\") // Redirect back to home after logout\n } catch (error) {\n if (error instanceof AxiosError) {\n switch (error.response?.status) {\n case 401:\n res.redirect(401, this.loginUrl)\n }\n }\n console.error('Error in logout middleware:', error);\n res.status(500).send('Internal server error');\n }\n }\n\n /**\n * Utility route handler for deleting a user\n * This ensures that the user is fully logged out before \n * deleting the user's data\n * \n * @param req - The request object.\n * @param res - The response object.\n */\n public deleteUser(req: Request, res: Response) {\n const cookies = parseCookies(req);\n try {\n this.logoutUser(req, res);\n this.deleteUserData(cookies?.accessToken);\n } catch (error) {\n if (error instanceof AxiosError) {\n switch (error.response?.status) {\n case 401:\n res.redirect(401, this.loginUrl);\n return;\n }\n }\n console.error('Error in deleteUser utility function:', error);\n res.status(500).send('Internal server error');\n }\n }\n}\n\nexport default ExpressAuthGneissClient;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["import_axios", "dotenv", "axios", "import_axios", "config"]
|
|
7
7
|
}
|
package/dist/esm/index.mjs
CHANGED
|
@@ -6,7 +6,7 @@ import { AxiosError } from "axios";
|
|
|
6
6
|
// src/config.ts
|
|
7
7
|
var config = {
|
|
8
8
|
authUrl: process.env.ENV === "prod" ? "https://auth.gneiss.io" : process.env.ENV === "staging" ? "https://auth.gneiss.io/testing" : "http://localhost:5000",
|
|
9
|
-
internalAuthUrl: process.env.ENV === "prod" ? "http://auth:
|
|
9
|
+
internalAuthUrl: process.env.ENV === "prod" ? "http://auth:5000" : process.env.ENV === "staging" ? "http://auth:5000/testing" : "http://auth:5000"
|
|
10
10
|
};
|
|
11
11
|
|
|
12
12
|
// src/core/AuthGneissCore.ts
|
|
@@ -19,7 +19,7 @@ var AuthGneissCore = class {
|
|
|
19
19
|
this.authUrl = this.config.authUrl;
|
|
20
20
|
this.internalAuthUrl = this.config.internalAuthUrl;
|
|
21
21
|
this.loginUrl = `${this.authUrl}/auth/login`;
|
|
22
|
-
this.logoutUrl = `${this.
|
|
22
|
+
this.logoutUrl = `${this.internalAuthUrl}/auth/logout`;
|
|
23
23
|
this.signupUrl = `${this.authUrl}/auth/register`;
|
|
24
24
|
this.callbackUrl = `${this.config.baseClientUrl}${this.config.callbackRoute}`;
|
|
25
25
|
let errorMsgs = [];
|
|
@@ -76,6 +76,17 @@ var AuthGneissCore = class {
|
|
|
76
76
|
return null;
|
|
77
77
|
}
|
|
78
78
|
}
|
|
79
|
+
async logout(accessToken) {
|
|
80
|
+
if (!this.logoutUrl) {
|
|
81
|
+
throw new Error("Logout URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.");
|
|
82
|
+
}
|
|
83
|
+
await axios.post(this.logoutUrl, {}, {
|
|
84
|
+
// Logout
|
|
85
|
+
headers: {
|
|
86
|
+
"Authorization": `Bearer ${accessToken}`
|
|
87
|
+
}
|
|
88
|
+
});
|
|
89
|
+
}
|
|
79
90
|
/**
|
|
80
91
|
* getUserData is a method that fetches user data using the access token.
|
|
81
92
|
* @param accessToken - The access token to be used for user data fetching.
|
|
@@ -220,7 +231,6 @@ function clearCookies(res) {
|
|
|
220
231
|
|
|
221
232
|
// src/frameworks/express/middleware/ExpressAuthGneissClient.ts
|
|
222
233
|
import { AxiosError as AxiosError2 } from "axios";
|
|
223
|
-
import axios2 from "axios";
|
|
224
234
|
var ExpressAuthGneissClient = class extends AuthGneissCore_default {
|
|
225
235
|
// 10 minutes
|
|
226
236
|
constructor(config2) {
|
|
@@ -229,8 +239,8 @@ var ExpressAuthGneissClient = class extends AuthGneissCore_default {
|
|
|
229
239
|
this.URL_STORE_TTL = 10 * 60 * 1e3;
|
|
230
240
|
this.requireAuth = this.requireAuth.bind(this);
|
|
231
241
|
this.handleCallBack = this.handleCallBack.bind(this);
|
|
232
|
-
this.
|
|
233
|
-
this.
|
|
242
|
+
this.loginUser = this.loginUser.bind(this);
|
|
243
|
+
this.logoutUser = this.logoutUser.bind(this);
|
|
234
244
|
this.getUser = this.getUser.bind(this);
|
|
235
245
|
this.deleteUser = this.deleteUser.bind(this);
|
|
236
246
|
this.getUserData = this.getUserData.bind(this);
|
|
@@ -282,11 +292,20 @@ var ExpressAuthGneissClient = class extends AuthGneissCore_default {
|
|
|
282
292
|
async getUser(req, res) {
|
|
283
293
|
const cookies = parseCookies(req);
|
|
284
294
|
const accessToken = cookies?.accessToken;
|
|
285
|
-
|
|
286
|
-
|
|
295
|
+
try {
|
|
296
|
+
const userData = await this.getUserData(accessToken);
|
|
297
|
+
res.status(200).send(userData);
|
|
298
|
+
} catch (error) {
|
|
299
|
+
if (error instanceof AxiosError2) {
|
|
300
|
+
switch (error.response?.status) {
|
|
301
|
+
case 401:
|
|
302
|
+
res.redirect(401, this.loginUrl);
|
|
303
|
+
return;
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
console.error("Error in getUser utility function:", error);
|
|
307
|
+
res.status(500).send("Internal server error");
|
|
287
308
|
}
|
|
288
|
-
const userData = await this.getUserData(accessToken);
|
|
289
|
-
res.status(200).send(userData);
|
|
290
309
|
}
|
|
291
310
|
/**
|
|
292
311
|
* handleCallBack is a middleware function that handles the callback from the authentication service.
|
|
@@ -329,7 +348,7 @@ var ExpressAuthGneissClient = class extends AuthGneissCore_default {
|
|
|
329
348
|
* @param req - The request object.
|
|
330
349
|
* @param res - The response object.
|
|
331
350
|
*/
|
|
332
|
-
|
|
351
|
+
loginUser(req, res) {
|
|
333
352
|
try {
|
|
334
353
|
if (!this.loginUrl) {
|
|
335
354
|
throw new Error("Login URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.");
|
|
@@ -347,27 +366,23 @@ var ExpressAuthGneissClient = class extends AuthGneissCore_default {
|
|
|
347
366
|
}
|
|
348
367
|
}
|
|
349
368
|
/**
|
|
350
|
-
*
|
|
369
|
+
* logoutUser is a function that redirects the user to the Gneiss logout service.
|
|
351
370
|
* @param req - The request object.
|
|
352
371
|
* @param res - The response object.
|
|
353
372
|
*/
|
|
354
|
-
|
|
373
|
+
logoutUser(req, res) {
|
|
355
374
|
const cookies = parseCookies(req);
|
|
356
375
|
try {
|
|
357
|
-
|
|
358
|
-
throw new Error("Logout URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.");
|
|
359
|
-
}
|
|
360
|
-
if (cookies?.accessToken) {
|
|
361
|
-
axios2.post(this.logoutUrl, {}, {
|
|
362
|
-
// Logout
|
|
363
|
-
headers: {
|
|
364
|
-
"Authorization": `Bearer ${cookies?.accessToken}`
|
|
365
|
-
}
|
|
366
|
-
});
|
|
367
|
-
}
|
|
376
|
+
this.logout(cookies?.accessToken);
|
|
368
377
|
clearCookies(res);
|
|
369
378
|
res.redirect("/");
|
|
370
379
|
} catch (error) {
|
|
380
|
+
if (error instanceof AxiosError2) {
|
|
381
|
+
switch (error.response?.status) {
|
|
382
|
+
case 401:
|
|
383
|
+
res.redirect(401, this.loginUrl);
|
|
384
|
+
}
|
|
385
|
+
}
|
|
371
386
|
console.error("Error in logout middleware:", error);
|
|
372
387
|
res.status(500).send("Internal server error");
|
|
373
388
|
}
|
|
@@ -382,8 +397,20 @@ var ExpressAuthGneissClient = class extends AuthGneissCore_default {
|
|
|
382
397
|
*/
|
|
383
398
|
deleteUser(req, res) {
|
|
384
399
|
const cookies = parseCookies(req);
|
|
385
|
-
|
|
386
|
-
|
|
400
|
+
try {
|
|
401
|
+
this.logoutUser(req, res);
|
|
402
|
+
this.deleteUserData(cookies?.accessToken);
|
|
403
|
+
} catch (error) {
|
|
404
|
+
if (error instanceof AxiosError2) {
|
|
405
|
+
switch (error.response?.status) {
|
|
406
|
+
case 401:
|
|
407
|
+
res.redirect(401, this.loginUrl);
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
console.error("Error in deleteUser utility function:", error);
|
|
412
|
+
res.status(500).send("Internal server error");
|
|
413
|
+
}
|
|
387
414
|
}
|
|
388
415
|
};
|
|
389
416
|
var ExpressAuthGneissClient_default = ExpressAuthGneissClient;
|
package/dist/esm/index.mjs.map
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"version": 3,
|
|
3
3
|
"sources": ["../../src/core/AuthGneissCore.ts", "../../src/config.ts", "../../src/utils/storage/cookieHandling.ts", "../../src/frameworks/express/middleware/ExpressAuthGneissClient.ts"],
|
|
4
|
-
"sourcesContent": ["import { AuthGneissCoreConfig } from \"@core/types\";\nimport axios, { AxiosResponse } from \"axios\";\nimport { Tokens } from \"@core/types\";\nimport dotenv from \"dotenv\";\nimport { AxiosError } from \"axios\";\nimport { config as genConfig } from \"@/config\";\nimport { AuthGneissGeneralConfig } from \"@/config\";\n\n//load environment variables if not already set\nif (!process.env.ENV) {\n dotenv.config();\n}\n\n/**\n * AuthGneissCore provides core functionality for OAuth2 authentication flow with Gneiss authentication service.\n * It handles token exchange, token refresh, user data fetching, and token validation.\n * \n * This class serves as a base class that can be extended by framework-specific implementations\n * to provide authentication middleware and handlers.\n */\nclass AuthGneissCore {\n protected config: AuthGneissCoreConfig & AuthGneissGeneralConfig; // Configuration object\n protected authUrl : string;\n protected loginUrl : string;\n protected logoutUrl : string;\n protected signupUrl : string;\n protected callbackUrl : string;\n protected internalAuthUrl : string;\n\n constructor(\n devConfig: AuthGneissCoreConfig,\n generalConfig: AuthGneissGeneralConfig = genConfig\n ) {\n\n this.config = {...devConfig, ...generalConfig};\n this.authUrl = this.config.authUrl; // Gneiss endpoint\n this.internalAuthUrl = this.config.internalAuthUrl;\n this.loginUrl = `${this.authUrl}/auth/login` // Login URL\n this.logoutUrl = `${this.authUrl}/auth/logout` // Logout URL\n this.signupUrl = `${this.authUrl}/auth/register` // Signup/register URL\n this.callbackUrl = `${this.config.baseClientUrl}${this.config.callbackRoute}`\n\n //check if environment variables are set\n let errorMsgs = [];\n if (!process.env.ENV) {\n errorMsgs.push(\"ENV is not set in environment variables\");\n }\n if (errorMsgs.length > 0) {\n throw new Error(errorMsgs.join(\"\\n\"));\n }\n }\n\n public getBase64EncodedCallbackUrl(): string {\n return Buffer.from(this.callbackUrl).toString('base64')\n }\n\n /**\n * getTokens is a method that exchanges an authentication code for access and refresh tokens.\n * The client id and secret are passed as basic auth headers to authenticate the client itself.\n * @param authCode - The authentication code received from the Gneiss authentication service.\n * @returns A promise that resolves to an object containing the access and refresh tokens.\n */\n protected async getTokens(authCode : string) : Promise<Tokens> {\n try {\n const url : string = `${this.internalAuthUrl}/auth/access_token?auth_code=${authCode}`;\n //Encode in base64 before transport\n const encodedClientId = btoa(this.config.clientId);\n const encodedClientSecret = btoa(this.config.clientSecret);\n const response : AxiosResponse = await axios.post(url, {}, {\n headers: {\n \"Authorization\": `Basic ${encodedClientId}:${encodedClientSecret}`\n }\n });\n return {\n accessToken: response.data.access_token,\n refreshToken: response.data.refresh_token,\n tokenType: response.data.token_type\n } as Tokens;\n } catch (error) {\n // console.error(\"Error in getTokens:\", error);\n throw error;\n }\n }\n \n /**\n * refreshToken is a method that refreshes the access token using the refresh token.\n * @param refreshToken - The refresh token to be used for token refresh.\n * @returns A promise that resolves to the refreshed access token.\n */\n protected async refreshToken(refreshToken: string): Promise<string | null> {\n try {\n const url : string = `${this.internalAuthUrl}/auth/refresh`;\n const response : AxiosResponse = await axios.post(url, {}, {\n headers: {\n \"Authorization\": `Bearer ${refreshToken}`\n }\n });\n return response.data.access_token as string;\n } catch (error) {\n // console.error(\"Error in refreshToken:\", error);\n return null;\n }\n }\n \n /**\n * getUserData is a method that fetches user data using the access token.\n * @param accessToken - The access token to be used for user data fetching.\n * @returns A promise that resolves to the user data.\n */\n public async getUserData(accessToken: string) {\n const url : string = `${this.internalAuthUrl}/resource/user_data`;\n const response : AxiosResponse = await axios.get(url, {\n headers: {\n \"Authorization\": `Bearer ${accessToken}`\n }\n });\n if (response.status === 200) {\n return response.data;\n }\n throw new Error(\"Failed to fetch user data\");\n }\n \n /**\n * validateToken is a method that validates the access token.\n * @param token - The access token to be validated.\n * @returns A promise that resolves to a boolean indicating the validity of the token.\n */\n protected async validateToken(token: string): Promise<boolean> {\n try {\n console.log(\"DEBUG: token\", token);\n // Token validation logic\n if (!token) {\n return false;\n }\n const url : string = `${this.internalAuthUrl}/auth/validate_token`;\n const response : AxiosResponse = await axios.get(url, {\n headers: {\n \"Authorization\": `Bearer ${token}`\n }\n });\n return response.status === 200;\n } catch (error) {\n // console.error(\"Error in validateToken:\", error);\n if (error instanceof AxiosError && error.response?.status === 401) {\n return false;\n } else {\n throw error;\n }\n }\n }\n\n /**\n * getLoginUrl is a method that returns the login URL.\n * @returns The login URL.\n */\n public getLoginUrl() : string | undefined {\n return this.loginUrl;\n }\n\n /**\n * Returns the base auth URL.\n * @returns The base auth URL.\n */\n public getAuthUrl(): string | undefined {\n return this.authUrl;\n }\n\n /**\n * Returns the logout URL.\n * @returns The logout URL.\n */\n public getLogoutUrl(): string | undefined {\n return this.logoutUrl;\n }\n\n /**\n * Returns the signup URL.\n * @returns The signup URL.\n */\n public getSignupUrl(): string | undefined {\n return this.signupUrl;\n }\n\n /**\n * deleteUser deletes the user\n * */\n protected async deleteUserData(accessToken : string) : Promise<object> {\n const response : AxiosResponse = await axios.post(`${this.internalAuthUrl}/resource/delete_user`, {}, {\n headers: {\n \"Authorization\": `Bearer ${accessToken}`\n } \n });\n return response.data;\n }\n}\n\nexport default AuthGneissCore;\n", "export type AuthGneissGeneralConfig = {\n authUrl: string // used by the browser\n internalAuthUrl: string // used internally within the same docker network\n}\n\nexport const config : AuthGneissGeneralConfig = {\n authUrl: process.env.ENV === \"prod\" ? \"https://auth.gneiss.io\" : \n process.env.ENV === \"staging\" ? \"https://auth.gneiss.io/testing\" : \"http://localhost:5000\",\n internalAuthUrl: process.env.ENV === \"prod\" ? \"http://auth:45443\" : \n process.env.ENV === \"staging\" ? \"http://auth:44443/testing\" : \"http://auth:5000\"\n}", "import { Response } from \"express\";\nimport { JwtPayload, decode } from \"jsonwebtoken\";\nimport { Request } from \"express\";\n\n// Helper to determine if we're in production\nconst isProduction = process.env.ENV === 'prod' || process.env.ENV === 'staging';\n\n// Cookie configuration\n// Note: SameSite=None requires Secure=true (HTTPS)\n// In dev, use SameSite=Lax with Angular proxy to avoid cross-origin issues\nconst cookieConfig = {\n httpOnly: true,\n secure: isProduction, // Only secure in production (HTTPS)\n sameSite: 'lax' as const, // Lax works for same-origin (Angular proxy in dev, Nginx in prod)\n};\n\n/**\n * Set the access token in the response cookies.\n * @param res - The response object.\n * @param accessToken - The access token to set.\n */\nfunction setAccessToken(res: Response, accessToken: string) {\n\n const decodedToken = decode(accessToken) as JwtPayload;\n \n // decoded.exp is in seconds since epoch\n // Date.now() returns milliseconds since epoch\n // maxAge needs milliseconds remaining\n if (!decodedToken.exp) {\n throw new Error(\"Access token does not contain an expiration time\");\n }\n \n res.cookie('accessToken', accessToken, {\n ...cookieConfig,\n maxAge: (decodedToken.exp * 1000) - Date.now()\n });\n}\n\n/**\n * Set the refresh token in the response cookies.\n * @param res - The response object.\n * @param refreshToken - The refresh token to set.\n */\nfunction setRefreshToken(res: Response, refreshToken: string) {\n\n const decodedToken = decode(refreshToken) as JwtPayload;\n\n if (!decodedToken.exp) {\n throw new Error(\"Refresh token does not contain an expiration time\");\n }\n\n res.cookie('refreshToken', refreshToken, {\n ...cookieConfig,\n maxAge: (decodedToken.exp * 1000) - Date.now()\n });\n}\n\nfunction parseCookies(req: Request) : { [key: string]: string } {\n const cookies = req.headers.cookie;\n if (!cookies) {\n return {};\n }\n return cookies.split(';').reduce((acc: { [key: string]: string }, cookie) => {\n const [key, value] = cookie.split('=').map(s => s.trim());\n acc[key] = value;\n return acc;\n }, {});\n}\n\n/**\n * Set the state token in the response cookies.\n * @param res - The response object.\n * @param stateToken - The state token to set.\n */\nfunction setUrlToken(res: Response, stateToken: string, exp: number) {\n\n\n res.cookie('urlToken', stateToken, {\n ...cookieConfig,\n maxAge: exp\n });\n}\n\nfunction clearCookies(res: Response) {\n const clearConfig = {\n ...cookieConfig,\n path: '/'\n };\n \n res.clearCookie(\"accessToken\", clearConfig);\n res.clearCookie(\"refreshToken\", clearConfig);\n res.clearCookie(\"urlToken\", clearConfig);\n}\n\nexport { setAccessToken, setRefreshToken, parseCookies, clearCookies, setUrlToken};\n", "import { AuthGneissCore, AuthGneissCoreConfig } from \"@core\";\nimport { Request, Response, NextFunction } from \"express\";\nimport { AuthenticatedRequest, Tokens } from \"@core/types\";\nimport { setAccessToken, setRefreshToken, parseCookies, setUrlToken} from \"@utils\";\nimport { AxiosError } from \"axios\";\nimport axios from \"axios\";\nimport { clearCookies } from \"@/utils/storage/cookieHandling\";\n\n\n/**\n * ExpressAuthGneissClient extends AuthGneissCore to provide Express-specific authentication middleware\n * and functionality for handling OAuth2 authentication flow with Gneiss authentication service.\n * \n * @extends AuthGneissCore\n * @example\n * const authClient = new ExpressAuthGneissClient({\n * clientId: 'your-client-id',\n * clientSecret: 'your-client-secret',\n * redirectUrl: 'your-redirect-url'\n * });\n */\nclass ExpressAuthGneissClient extends AuthGneissCore {\n\n private returnUrlStore = new Map<string, string>();\n private readonly URL_STORE_TTL = 10 * 60 * 1000; // 10 minutes\n\n constructor(\n config: AuthGneissCoreConfig\n ) {\n super(config);\n \n // Bind the methods in constructor\n this.requireAuth = this.requireAuth.bind(this);\n this.handleCallBack = this.handleCallBack.bind(this);\n this.login = this.login.bind(this);\n this.logout = this.logout.bind(this);\n this.getUser = this.getUser.bind(this);\n this.deleteUser = this.deleteUser.bind(this);\n this.getUserData = this.getUserData.bind(this);\n this.getLoginUrl = this.getLoginUrl.bind(this);\n this.getLogoutUrl = this.getLogoutUrl.bind(this);\n this.getSignupUrl = this.getSignupUrl.bind(this);\n this.getAuthUrl = this.getAuthUrl.bind(this);\n }\n\n /**\n /**\n * requireAuth is a middleware function that checks if the access token is valid.\n * If the access token is not valid, it attempts to refresh the token using the refresh token.\n * If the refresh token is not valid, it redirects the user to the login page.\n * @template UserT - The type of the user object to attach to the request.\n * @param req - The request object.\n * @param res - The response object.\n * @param next - The next middleware function.\n */\n public async requireAuth<UserT>(req: Request, res: Response, next: NextFunction): Promise<void> {\n const cookies = parseCookies(req);\n //Check for the existence of the access token\n // console.log(\"DEBUG: cookies\", cookies);\n try {\n const isAccessTokenValid : boolean = await this.validateToken(cookies?.accessToken);\n if (!isAccessTokenValid) { //if the access token is not valid\n //try to refresh the token\n const newAccessToken : string | null = await this.refreshToken(cookies?.refreshToken);\n if (newAccessToken) { // set access token and then call next to proceed to the next middleware/handler\n setAccessToken(res, newAccessToken);\n next()\n }\n else {\n // no access token or valid refresh token, redirect to login with 401 requires login credentials\n res.redirect(401, `${this.loginUrl}?redirect_url=${this.getBase64EncodedCallbackUrl()}`);\n }\n }\n else {\n // access token is valid, continue to the next middleware or route handler after adding user to req\n (req as AuthenticatedRequest<UserT>).user = await this.getUserData(cookies.accessToken);\n next();\n }\n } catch (error) {\n // console.error('Error in requireAuth middleware:', error);\n if (error instanceof AxiosError) {\n res.status((error as AxiosError).response?.status || 500).send((error as AxiosError).response?.data || 'Internal server error');\n } else {\n res.status(500).send('Internal server error');\n }\n }\n }\n\n /**\n * getUserData is a middleware function that fetches user data using the access token.\n * @param req - The request object.\n * @param res - The response object.\n * @param next - The next middleware function.\n */\n public async getUser(req: Request, res: Response): Promise<void> {\n const cookies = parseCookies(req);\n const accessToken = cookies?.accessToken;\n if (!accessToken) {\n throw new Error(\"No access token found in request cookies\");\n }\n const userData = await this.getUserData(accessToken);\n res.status(200).send(userData);\n }\n\n /**\n * handleCallBack is a middleware function that handles the callback from the authentication service.\n * It extracts the auth code from the request URL parameters, exchanges it for tokens, and sets the access and refresh tokens in the response cookies.\n * @param req - The request object.\n * @param res - The response object.\n * @param next - The next middleware function.\n */\n public async handleCallBack(\n req: Request,\n res: Response,\n next: NextFunction\n ): Promise<void> {\n\n const cookies = parseCookies(req);\n const returnToToken = cookies?.urlToken\n\n try {\n const authCode: string | undefined = req.query.auth_code as string;\n const returnToUrl = this.returnUrlStore.get(returnToToken);\n\n if (!authCode) {\n throw new Error(\"No auth code found in request url parameters\");\n }\n\n const tokens: Tokens = await this.getTokens(authCode);\n \n // Set the access and refresh tokens in the response cookies\n setAccessToken(res, tokens.accessToken);\n setRefreshToken(res, tokens.refreshToken);\n\n if (returnToUrl) {\n // Go to the original request url\n res.redirect(returnToUrl);\n }\n else {\n // Go to the root url\n res.redirect(\"/\")\n }\n } catch (error) {\n // console.error('Error in handleCallBack middleware:', error);\n if (error instanceof AxiosError) {\n res.status((error as AxiosError).response?.status || 500).send((error as AxiosError).response?.data || 'Internal server error');\n console.error(\"DEBUG: error\", error);\n } else {\n res.status(500).send('Internal server error');\n console.error(\"DEBUG: error\", error);\n }\n }\n }\n\n /**\n * login is a function that redirects the user to the Gneiss authentication service for authentication.\n * Accepts an optional returnTo query parameter to specify where to redirect after successful login.\n * Falls back to referer header if no returnTo is provided.\n * @param req - The request object.\n * @param res - The response object.\n */\n public login(req: Request, res: Response): void {\n try {\n if (!this.loginUrl) {\n throw new Error('Login URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.');\n }\n\n // Priority: query param > referer header > environment variable\n // In dev with proxy, referer will be the frontend URL (e.g., http://localhost:4200)\n // In staging, FRONTEND_URL should be set to staging frontend URL\n const returnToUrl = \n (req.query.returnTo as string) || \n req.get('referer') || \n process.env.FRONTEND_URL || \n '/'; // Fallback to root path (same origin)\n \n const urlToken = crypto.randomUUID();\n\n // Store the returnToUrl with auto-expiration\n this.returnUrlStore.set(urlToken, returnToUrl);\n setUrlToken(res, urlToken, this.URL_STORE_TTL);\n setTimeout(() => this.returnUrlStore.delete(urlToken), this.URL_STORE_TTL);\n\n //Base64 encode callback url\n const callbackUrl = this.getBase64EncodedCallbackUrl();\n\n res.redirect(this.loginUrl + `?redirect_url=${callbackUrl}`);\n } catch (error) {\n console.error('Error in login middleware:', error);\n res.status(500).send('Internal server error');\n }\n }\n\n /**\n * logout is a function that redirects the user to the Gneiss logout service.\n * @param req - The request object.\n * @param res - The response object.\n */\n public logout(req: Request, res: Response): void {\n const cookies = parseCookies(req);\n try {\n if (!this.logoutUrl) {\n throw new Error('Logout URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.');\n }\n if (cookies?.accessToken) { // Only logout if the access token exists\n axios.post(this.logoutUrl, {}, { // Logout\n headers: {\n \"Authorization\": `Bearer ${cookies?.accessToken}`\n }\n });\n }\n clearCookies(res); // clear the access and refresh cookies\n res.redirect(\"/\") // Redirect back to home after logout\n } catch (error) {\n console.error('Error in logout middleware:', error);\n res.status(500).send('Internal server error');\n }\n }\n\n /**\n * Utility route handler for deleting a user\n * This ensures that the user is fully logged out before \n * deleting the user's data\n * \n * @param req - The request object.\n * @param res - The response object.\n */\n public deleteUser(req: Request, res: Response) {\n const cookies = parseCookies(req);\n this.logout(req, res)\n this.deleteUserData(cookies?.accessToken)\n }\n}\n\nexport default ExpressAuthGneissClient;\n"],
|
|
5
|
-
"mappings": ";AACA,OAAO,WAA8B;AAErC,OAAO,YAAY;AACnB,SAAS,kBAAkB;;;ACCpB,IAAM,SAAmC;AAAA,EAC5C,SAAS,QAAQ,IAAI,QAAQ,SAAS,2BACtC,QAAQ,IAAI,QAAQ,YAAY,mCAAmC;AAAA,EACnE,iBAAiB,QAAQ,IAAI,QAAQ,SAAS,
|
|
6
|
-
"names": ["AxiosError", "
|
|
4
|
+
"sourcesContent": ["import { AuthGneissCoreConfig } from \"@core/types\";\nimport axios, { AxiosResponse } from \"axios\";\nimport { Tokens } from \"@core/types\";\nimport dotenv from \"dotenv\";\nimport { AxiosError } from \"axios\";\nimport { config as genConfig } from \"@/config\";\nimport { AuthGneissGeneralConfig } from \"@/config\";\n\n//load environment variables if not already set\nif (!process.env.ENV) {\n dotenv.config();\n}\n\n/**\n * AuthGneissCore provides core functionality for OAuth2 authentication flow with Gneiss authentication service.\n * It handles token exchange, token refresh, user data fetching, and token validation.\n * \n * This class serves as a base class that can be extended by framework-specific implementations\n * to provide authentication middleware and handlers.\n */\nclass AuthGneissCore {\n protected config: AuthGneissCoreConfig & AuthGneissGeneralConfig; // Configuration object\n protected authUrl : string;\n protected loginUrl : string;\n protected logoutUrl : string;\n protected signupUrl : string;\n protected callbackUrl : string;\n protected internalAuthUrl : string;\n\n constructor(\n devConfig: AuthGneissCoreConfig,\n generalConfig: AuthGneissGeneralConfig = genConfig\n ) {\n\n this.config = {...devConfig, ...generalConfig};\n this.authUrl = this.config.authUrl; // Gneiss endpoint\n this.internalAuthUrl = this.config.internalAuthUrl;\n this.loginUrl = `${this.authUrl}/auth/login` // Login URL\n this.logoutUrl = `${this.internalAuthUrl}/auth/logout` // Logout URL\n this.signupUrl = `${this.authUrl}/auth/register` // Signup/register URL\n this.callbackUrl = `${this.config.baseClientUrl}${this.config.callbackRoute}`\n\n //check if environment variables are set\n let errorMsgs = [];\n if (!process.env.ENV) {\n errorMsgs.push(\"ENV is not set in environment variables\");\n }\n if (errorMsgs.length > 0) {\n throw new Error(errorMsgs.join(\"\\n\"));\n }\n }\n\n public getBase64EncodedCallbackUrl(): string {\n return Buffer.from(this.callbackUrl).toString('base64')\n }\n\n /**\n * getTokens is a method that exchanges an authentication code for access and refresh tokens.\n * The client id and secret are passed as basic auth headers to authenticate the client itself.\n * @param authCode - The authentication code received from the Gneiss authentication service.\n * @returns A promise that resolves to an object containing the access and refresh tokens.\n */\n protected async getTokens(authCode : string) : Promise<Tokens> {\n try {\n const url : string = `${this.internalAuthUrl}/auth/access_token?auth_code=${authCode}`;\n //Encode in base64 before transport\n const encodedClientId = btoa(this.config.clientId);\n const encodedClientSecret = btoa(this.config.clientSecret);\n const response : AxiosResponse = await axios.post(url, {}, {\n headers: {\n \"Authorization\": `Basic ${encodedClientId}:${encodedClientSecret}`\n }\n });\n return {\n accessToken: response.data.access_token,\n refreshToken: response.data.refresh_token,\n tokenType: response.data.token_type\n } as Tokens;\n } catch (error) {\n // console.error(\"Error in getTokens:\", error);\n throw error;\n }\n }\n \n /**\n * refreshToken is a method that refreshes the access token using the refresh token.\n * @param refreshToken - The refresh token to be used for token refresh.\n * @returns A promise that resolves to the refreshed access token.\n */\n protected async refreshToken(refreshToken: string): Promise<string | null> {\n try {\n const url : string = `${this.internalAuthUrl}/auth/refresh`;\n const response : AxiosResponse = await axios.post(url, {}, {\n headers: {\n \"Authorization\": `Bearer ${refreshToken}`\n }\n });\n return response.data.access_token as string;\n } catch (error) {\n // console.error(\"Error in refreshToken:\", error);\n return null;\n }\n }\n\n protected async logout(accessToken : string) {\n if (!this.logoutUrl) {\n throw new Error('Logout URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.');\n }\n await axios.post(this.logoutUrl, {}, { // Logout\n headers: {\n \"Authorization\": `Bearer ${accessToken}`\n }\n });\n }\n \n /**\n * getUserData is a method that fetches user data using the access token.\n * @param accessToken - The access token to be used for user data fetching.\n * @returns A promise that resolves to the user data.\n */\n public async getUserData(accessToken: string) {\n const url : string = `${this.internalAuthUrl}/resource/user_data`;\n const response : AxiosResponse = await axios.get(url, {\n headers: {\n \"Authorization\": `Bearer ${accessToken}`\n }\n });\n if (response.status === 200) {\n return response.data;\n }\n throw new Error(\"Failed to fetch user data\");\n }\n \n /**\n * validateToken is a method that validates the access token.\n * @param token - The access token to be validated.\n * @returns A promise that resolves to a boolean indicating the validity of the token.\n */\n protected async validateToken(token: string): Promise<boolean> {\n try {\n console.log(\"DEBUG: token\", token);\n // Token validation logic\n if (!token) {\n return false;\n }\n const url : string = `${this.internalAuthUrl}/auth/validate_token`;\n const response : AxiosResponse = await axios.get(url, {\n headers: {\n \"Authorization\": `Bearer ${token}`\n }\n });\n return response.status === 200;\n } catch (error) {\n // console.error(\"Error in validateToken:\", error);\n if (error instanceof AxiosError && error.response?.status === 401) {\n return false;\n } else {\n throw error;\n }\n }\n }\n\n /**\n * getLoginUrl is a method that returns the login URL.\n * @returns The login URL.\n */\n public getLoginUrl() : string | undefined {\n return this.loginUrl;\n }\n\n /**\n * Returns the base auth URL.\n * @returns The base auth URL.\n */\n public getAuthUrl(): string | undefined {\n return this.authUrl;\n }\n\n /**\n * Returns the logout URL.\n * @returns The logout URL.\n */\n public getLogoutUrl(): string | undefined {\n return this.logoutUrl;\n }\n\n /**\n * Returns the signup URL.\n * @returns The signup URL.\n */\n public getSignupUrl(): string | undefined {\n return this.signupUrl;\n }\n\n /**\n * deleteUser deletes the user\n * */\n protected async deleteUserData(accessToken : string) : Promise<object> {\n const response : AxiosResponse = await axios.post(`${this.internalAuthUrl}/resource/delete_user`, {}, {\n headers: {\n \"Authorization\": `Bearer ${accessToken}`\n } \n });\n return response.data;\n }\n}\n\nexport default AuthGneissCore;\n", "export type AuthGneissGeneralConfig = {\n authUrl: string // used by the browser\n internalAuthUrl: string // used internally within the same docker network\n}\n\nexport const config : AuthGneissGeneralConfig = {\n authUrl: process.env.ENV === \"prod\" ? \"https://auth.gneiss.io\" : \n process.env.ENV === \"staging\" ? \"https://auth.gneiss.io/testing\" : \"http://localhost:5000\",\n internalAuthUrl: process.env.ENV === \"prod\" ? \"http://auth:5000\" : \n process.env.ENV === \"staging\" ? \"http://auth:5000/testing\" : \"http://auth:5000\"\n}", "import { Response } from \"express\";\nimport { JwtPayload, decode } from \"jsonwebtoken\";\nimport { Request } from \"express\";\n\n// Helper to determine if we're in production\nconst isProduction = process.env.ENV === 'prod' || process.env.ENV === 'staging';\n\n// Cookie configuration\n// Note: SameSite=None requires Secure=true (HTTPS)\n// In dev, use SameSite=Lax with Angular proxy to avoid cross-origin issues\nconst cookieConfig = {\n httpOnly: true,\n secure: isProduction, // Only secure in production (HTTPS)\n sameSite: 'lax' as const, // Lax works for same-origin (Angular proxy in dev, Nginx in prod)\n};\n\n/**\n * Set the access token in the response cookies.\n * @param res - The response object.\n * @param accessToken - The access token to set.\n */\nfunction setAccessToken(res: Response, accessToken: string) {\n\n const decodedToken = decode(accessToken) as JwtPayload;\n \n // decoded.exp is in seconds since epoch\n // Date.now() returns milliseconds since epoch\n // maxAge needs milliseconds remaining\n if (!decodedToken.exp) {\n throw new Error(\"Access token does not contain an expiration time\");\n }\n \n res.cookie('accessToken', accessToken, {\n ...cookieConfig,\n maxAge: (decodedToken.exp * 1000) - Date.now()\n });\n}\n\n/**\n * Set the refresh token in the response cookies.\n * @param res - The response object.\n * @param refreshToken - The refresh token to set.\n */\nfunction setRefreshToken(res: Response, refreshToken: string) {\n\n const decodedToken = decode(refreshToken) as JwtPayload;\n\n if (!decodedToken.exp) {\n throw new Error(\"Refresh token does not contain an expiration time\");\n }\n\n res.cookie('refreshToken', refreshToken, {\n ...cookieConfig,\n maxAge: (decodedToken.exp * 1000) - Date.now()\n });\n}\n\nfunction parseCookies(req: Request) : { [key: string]: string } {\n const cookies = req.headers.cookie;\n if (!cookies) {\n return {};\n }\n return cookies.split(';').reduce((acc: { [key: string]: string }, cookie) => {\n const [key, value] = cookie.split('=').map(s => s.trim());\n acc[key] = value;\n return acc;\n }, {});\n}\n\n/**\n * Set the state token in the response cookies.\n * @param res - The response object.\n * @param stateToken - The state token to set.\n */\nfunction setUrlToken(res: Response, stateToken: string, exp: number) {\n\n\n res.cookie('urlToken', stateToken, {\n ...cookieConfig,\n maxAge: exp\n });\n}\n\nfunction clearCookies(res: Response) {\n const clearConfig = {\n ...cookieConfig,\n path: '/'\n };\n \n res.clearCookie(\"accessToken\", clearConfig);\n res.clearCookie(\"refreshToken\", clearConfig);\n res.clearCookie(\"urlToken\", clearConfig);\n}\n\nexport { setAccessToken, setRefreshToken, parseCookies, clearCookies, setUrlToken};\n", "import { AuthGneissCore, AuthGneissCoreConfig } from \"@core\";\nimport { Request, Response, NextFunction } from \"express\";\nimport { AuthenticatedRequest, Tokens } from \"@core/types\";\nimport { setAccessToken, setRefreshToken, parseCookies, setUrlToken} from \"@utils\";\nimport { AxiosError } from \"axios\";\nimport axios from \"axios\";\nimport { clearCookies } from \"@/utils/storage/cookieHandling\";\n\n\n/**\n * ExpressAuthGneissClient extends AuthGneissCore to provide Express-specific authentication middleware\n * and functionality for handling OAuth2 authentication flow with Gneiss authentication service.\n * \n * @extends AuthGneissCore\n * @example\n * const authClient = new ExpressAuthGneissClient({\n * clientId: 'your-client-id',\n * clientSecret: 'your-client-secret',\n * redirectUrl: 'your-redirect-url'\n * });\n */\nclass ExpressAuthGneissClient extends AuthGneissCore {\n\n private returnUrlStore = new Map<string, string>();\n private readonly URL_STORE_TTL = 10 * 60 * 1000; // 10 minutes\n\n constructor(\n config: AuthGneissCoreConfig\n ) {\n super(config);\n \n // Bind the methods in constructor\n this.requireAuth = this.requireAuth.bind(this);\n this.handleCallBack = this.handleCallBack.bind(this);\n this.loginUser = this.loginUser.bind(this);\n this.logoutUser = this.logoutUser.bind(this);\n this.getUser = this.getUser.bind(this);\n this.deleteUser = this.deleteUser.bind(this);\n this.getUserData = this.getUserData.bind(this);\n this.getLoginUrl = this.getLoginUrl.bind(this);\n this.getLogoutUrl = this.getLogoutUrl.bind(this);\n this.getSignupUrl = this.getSignupUrl.bind(this);\n this.getAuthUrl = this.getAuthUrl.bind(this);\n }\n\n /**\n /**\n * requireAuth is a middleware function that checks if the access token is valid.\n * If the access token is not valid, it attempts to refresh the token using the refresh token.\n * If the refresh token is not valid, it redirects the user to the login page.\n * @template UserT - The type of the user object to attach to the request.\n * @param req - The request object.\n * @param res - The response object.\n * @param next - The next middleware function.\n */\n public async requireAuth<UserT>(req: Request, res: Response, next: NextFunction): Promise<void> {\n const cookies = parseCookies(req);\n //Check for the existence of the access token\n // console.log(\"DEBUG: cookies\", cookies);\n try {\n const isAccessTokenValid : boolean = await this.validateToken(cookies?.accessToken);\n if (!isAccessTokenValid) { //if the access token is not valid\n //try to refresh the token\n const newAccessToken : string | null = await this.refreshToken(cookies?.refreshToken);\n if (newAccessToken) { // set access token and then call next to proceed to the next middleware/handler\n setAccessToken(res, newAccessToken);\n next()\n }\n else {\n // no access token or valid refresh token, redirect to login with 401 requires login credentials\n res.redirect(401, `${this.loginUrl}?redirect_url=${this.getBase64EncodedCallbackUrl()}`);\n }\n }\n else {\n // access token is valid, continue to the next middleware or route handler after adding user to req\n (req as AuthenticatedRequest<UserT>).user = await this.getUserData(cookies.accessToken);\n next();\n }\n } catch (error) {\n // console.error('Error in requireAuth middleware:', error);\n if (error instanceof AxiosError) {\n res.status((error as AxiosError).response?.status || 500).send((error as AxiosError).response?.data || 'Internal server error');\n } else {\n res.status(500).send('Internal server error');\n }\n }\n }\n\n /**\n * getUserData is a middleware function that fetches user data using the access token.\n * @param req - The request object.\n * @param res - The response object.\n * @param next - The next middleware function.\n */\n public async getUser(req: Request, res: Response): Promise<void> {\n const cookies = parseCookies(req);\n const accessToken = cookies?.accessToken;\n try {\n const userData = await this.getUserData(accessToken);\n res.status(200).send(userData);\n } catch (error) {\n if (error instanceof AxiosError) {\n switch (error.response?.status) {\n case 401:\n res.redirect(401, this.loginUrl);\n return;\n }\n }\n console.error('Error in getUser utility function:', error);\n res.status(500).send('Internal server error');\n }\n }\n\n /**\n * handleCallBack is a middleware function that handles the callback from the authentication service.\n * It extracts the auth code from the request URL parameters, exchanges it for tokens, and sets the access and refresh tokens in the response cookies.\n * @param req - The request object.\n * @param res - The response object.\n * @param next - The next middleware function.\n */\n public async handleCallBack(\n req: Request,\n res: Response,\n next: NextFunction\n ): Promise<void> {\n\n const cookies = parseCookies(req);\n const returnToToken = cookies?.urlToken\n\n try {\n const authCode: string | undefined = req.query.auth_code as string;\n const returnToUrl = this.returnUrlStore.get(returnToToken);\n\n if (!authCode) {\n throw new Error(\"No auth code found in request url parameters\");\n }\n\n const tokens: Tokens = await this.getTokens(authCode);\n \n // Set the access and refresh tokens in the response cookies\n setAccessToken(res, tokens.accessToken);\n setRefreshToken(res, tokens.refreshToken);\n\n if (returnToUrl) {\n // Go to the original request url\n res.redirect(returnToUrl);\n }\n else {\n // Go to the root url\n res.redirect(\"/\")\n }\n } catch (error) {\n // console.error('Error in handleCallBack middleware:', error);\n if (error instanceof AxiosError) {\n res.status((error as AxiosError).response?.status || 500).send((error as AxiosError).response?.data || 'Internal server error');\n console.error(\"DEBUG: error\", error);\n } else {\n res.status(500).send('Internal server error');\n console.error(\"DEBUG: error\", error);\n }\n }\n }\n\n /**\n * login is a function that redirects the user to the Gneiss authentication service for authentication.\n * Accepts an optional returnTo query parameter to specify where to redirect after successful login.\n * Falls back to referer header if no returnTo is provided.\n * @param req - The request object.\n * @param res - The response object.\n */\n public loginUser(req: Request, res: Response): void {\n try {\n if (!this.loginUrl) {\n throw new Error('Login URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.');\n }\n\n // Priority: query param > referer header > environment variable\n // In dev with proxy, referer will be the frontend URL (e.g., http://localhost:4200)\n // In staging, FRONTEND_URL should be set to staging frontend URL\n const returnToUrl = \n (req.query.returnTo as string) || \n req.get('referer') || \n process.env.FRONTEND_URL || \n '/'; // Fallback to root path (same origin)\n \n const urlToken = crypto.randomUUID();\n\n // Store the returnToUrl with auto-expiration\n this.returnUrlStore.set(urlToken, returnToUrl);\n setUrlToken(res, urlToken, this.URL_STORE_TTL);\n setTimeout(() => this.returnUrlStore.delete(urlToken), this.URL_STORE_TTL);\n\n //Base64 encode callback url\n const callbackUrl = this.getBase64EncodedCallbackUrl();\n\n res.redirect(this.loginUrl + `?redirect_url=${callbackUrl}`);\n } catch (error) {\n console.error('Error in login middleware:', error);\n res.status(500).send('Internal server error');\n }\n }\n\n /**\n * logoutUser is a function that redirects the user to the Gneiss logout service.\n * @param req - The request object.\n * @param res - The response object.\n */\n public logoutUser(req: Request, res: Response): void {\n const cookies = parseCookies(req);\n try {\n this.logout(cookies?.accessToken)\n clearCookies(res); // clear the access and refresh cookies\n res.redirect(\"/\") // Redirect back to home after logout\n } catch (error) {\n if (error instanceof AxiosError) {\n switch (error.response?.status) {\n case 401:\n res.redirect(401, this.loginUrl)\n }\n }\n console.error('Error in logout middleware:', error);\n res.status(500).send('Internal server error');\n }\n }\n\n /**\n * Utility route handler for deleting a user\n * This ensures that the user is fully logged out before \n * deleting the user's data\n * \n * @param req - The request object.\n * @param res - The response object.\n */\n public deleteUser(req: Request, res: Response) {\n const cookies = parseCookies(req);\n try {\n this.logoutUser(req, res);\n this.deleteUserData(cookies?.accessToken);\n } catch (error) {\n if (error instanceof AxiosError) {\n switch (error.response?.status) {\n case 401:\n res.redirect(401, this.loginUrl);\n return;\n }\n }\n console.error('Error in deleteUser utility function:', error);\n res.status(500).send('Internal server error');\n }\n }\n}\n\nexport default ExpressAuthGneissClient;\n"],
|
|
5
|
+
"mappings": "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",
|
|
6
|
+
"names": ["AxiosError", "config", "AxiosError"]
|
|
7
7
|
}
|
|
@@ -31,6 +31,7 @@ declare class AuthGneissCore {
|
|
|
31
31
|
* @returns A promise that resolves to the refreshed access token.
|
|
32
32
|
*/
|
|
33
33
|
protected refreshToken(refreshToken: string): Promise<string | null>;
|
|
34
|
+
protected logout(accessToken: string): Promise<void>;
|
|
34
35
|
/**
|
|
35
36
|
* getUserData is a method that fetches user data using the access token.
|
|
36
37
|
* @param accessToken - The access token to be used for user data fetching.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"AuthGneissCore.d.ts","sourceRoot":"","sources":["../../../../src/core/AuthGneissCore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAIrC,OAAO,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAOnD;;;;;;GAMG;AACH,cAAM,cAAc;IAChB,SAAS,CAAC,MAAM,EAAE,oBAAoB,GAAG,uBAAuB,CAAC;IACjE,SAAS,CAAC,OAAO,EAAG,MAAM,CAAC;IAC3B,SAAS,CAAC,QAAQ,EAAG,MAAM,CAAC;IAC5B,SAAS,CAAC,SAAS,EAAG,MAAM,CAAC;IAC7B,SAAS,CAAC,SAAS,EAAG,MAAM,CAAC;IAC7B,SAAS,CAAC,WAAW,EAAG,MAAM,CAAC;IAC/B,SAAS,CAAC,eAAe,EAAG,MAAM,CAAC;gBAG/B,SAAS,EAAE,oBAAoB,EAC/B,aAAa,GAAE,uBAAmC;IAqB/C,2BAA2B,IAAI,MAAM;IAI5C;;;;;OAKG;cACa,SAAS,CAAC,QAAQ,EAAG,MAAM,GAAI,OAAO,CAAC,MAAM,CAAC;IAsB9D;;;;OAIG;cACa,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"AuthGneissCore.d.ts","sourceRoot":"","sources":["../../../../src/core/AuthGneissCore.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,oBAAoB,EAAE,MAAM,aAAa,CAAC;AAEnD,OAAO,EAAE,MAAM,EAAE,MAAM,aAAa,CAAC;AAIrC,OAAO,EAAE,uBAAuB,EAAE,MAAM,UAAU,CAAC;AAOnD;;;;;;GAMG;AACH,cAAM,cAAc;IAChB,SAAS,CAAC,MAAM,EAAE,oBAAoB,GAAG,uBAAuB,CAAC;IACjE,SAAS,CAAC,OAAO,EAAG,MAAM,CAAC;IAC3B,SAAS,CAAC,QAAQ,EAAG,MAAM,CAAC;IAC5B,SAAS,CAAC,SAAS,EAAG,MAAM,CAAC;IAC7B,SAAS,CAAC,SAAS,EAAG,MAAM,CAAC;IAC7B,SAAS,CAAC,WAAW,EAAG,MAAM,CAAC;IAC/B,SAAS,CAAC,eAAe,EAAG,MAAM,CAAC;gBAG/B,SAAS,EAAE,oBAAoB,EAC/B,aAAa,GAAE,uBAAmC;IAqB/C,2BAA2B,IAAI,MAAM;IAI5C;;;;;OAKG;cACa,SAAS,CAAC,QAAQ,EAAG,MAAM,GAAI,OAAO,CAAC,MAAM,CAAC;IAsB9D;;;;OAIG;cACa,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;cAe1D,MAAM,CAAC,WAAW,EAAG,MAAM;IAW3C;;;;OAIG;IACU,WAAW,CAAC,WAAW,EAAE,MAAM;IAa5C;;;;OAIG;cACa,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAwB9D;;;OAGG;IACI,WAAW,IAAK,MAAM,GAAG,SAAS;IAIzC;;;OAGG;IACI,UAAU,IAAI,MAAM,GAAG,SAAS;IAIvC;;;OAGG;IACI,YAAY,IAAI,MAAM,GAAG,SAAS;IAIzC;;;OAGG;IACI,YAAY,IAAI,MAAM,GAAG,SAAS;IAIzC;;SAEK;cACW,cAAc,CAAC,WAAW,EAAG,MAAM,GAAI,OAAO,CAAC,MAAM,CAAC;CAQzE;AAED,eAAe,cAAc,CAAC"}
|
|
@@ -49,13 +49,13 @@ declare class ExpressAuthGneissClient extends AuthGneissCore {
|
|
|
49
49
|
* @param req - The request object.
|
|
50
50
|
* @param res - The response object.
|
|
51
51
|
*/
|
|
52
|
-
|
|
52
|
+
loginUser(req: Request, res: Response): void;
|
|
53
53
|
/**
|
|
54
|
-
*
|
|
54
|
+
* logoutUser is a function that redirects the user to the Gneiss logout service.
|
|
55
55
|
* @param req - The request object.
|
|
56
56
|
* @param res - The response object.
|
|
57
57
|
*/
|
|
58
|
-
|
|
58
|
+
logoutUser(req: Request, res: Response): void;
|
|
59
59
|
/**
|
|
60
60
|
* Utility route handler for deleting a user
|
|
61
61
|
* This ensures that the user is fully logged out before
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpressAuthGneissClient.d.ts","sourceRoot":"","sources":["../../../../../../src/frameworks/express/middleware/ExpressAuthGneissClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAC7D,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAQ1D;;;;;;;;;;;GAWG;AACH,cAAM,uBAAwB,SAAQ,cAAc;IAEhD,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAkB;gBAG5C,MAAM,EAAE,oBAAoB;IAkBhC;;;;;;;;;QASI;IACS,WAAW,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAiC/F;;;;;OAKG;IACU,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;
|
|
1
|
+
{"version":3,"file":"ExpressAuthGneissClient.d.ts","sourceRoot":"","sources":["../../../../../../src/frameworks/express/middleware/ExpressAuthGneissClient.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,oBAAoB,EAAE,MAAM,OAAO,CAAC;AAC7D,OAAO,EAAE,OAAO,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,SAAS,CAAC;AAQ1D;;;;;;;;;;;GAWG;AACH,cAAM,uBAAwB,SAAQ,cAAc;IAEhD,OAAO,CAAC,cAAc,CAA6B;IACnD,OAAO,CAAC,QAAQ,CAAC,aAAa,CAAkB;gBAG5C,MAAM,EAAE,oBAAoB;IAkBhC;;;;;;;;;QASI;IACS,WAAW,CAAC,KAAK,EAAE,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAiC/F;;;;;OAKG;IACU,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAmBhE;;;;;;OAMG;IACU,cAAc,CACvB,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,YAAY,GACnB,OAAO,CAAC,IAAI,CAAC;IAuChB;;;;;;OAMG;IACI,SAAS,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI;IAgCnD;;;;OAIG;IACI,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI;IAkBpD;;;;;;;OAOG;IACI,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ;CAiBhD;AAED,eAAe,uBAAuB,CAAC"}
|