@gneiss/client-auth 1.0.1 → 1.0.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -17,12 +17,19 @@ npm install @gneiss/client-auth
17
17
  npm install git+ssh://git@bitbucket.org:gneissrev/js-client-auth-gneiss.git<branch>
18
18
  ```
19
19
 
20
+ ## Environment
21
+ You need the following environment variables set:
22
+ ```
23
+ NODE_ENV=production
24
+ GNEISS_ENDPOINT=https://auth.gneiss.io
25
+ ```
26
+
20
27
  ## Usage
21
28
  Example for an Express.js application:
22
29
  ```typescript
23
30
  import express from 'express';
24
- import { ExpressAuthGneissClient } from "client-auth-gneiss";
25
- import { AuthGneissCoreConfig } from 'client-auth-gneiss';
31
+ import { ExpressAuthGneissClient } from "@gneiss/client-auth";
32
+ import { AuthGneissCoreConfig } from '@gneiss/client-auth';
26
33
 
27
34
  // Create express app
28
35
  const app = express();
@@ -62,6 +69,7 @@ app.get("/user", auth.requireAuth, auth.getUser);
62
69
  * `baseUrl` - This is the base url (without any endpoints) of your service/app. Note that this may be different depending on your environment (prod or dev)
63
70
  * `redirectUrl` - This is the route that the user will be redirected to for authentication. This should be the same as your callback route.
64
71
  * `auth.login` is a function that redirects the user to the Gneiss authentication service for authentication.
72
+ * `auth.logout` is a function that removes all tokens and logs the user out of the auth system.
65
73
  * `auth.handleCallBack` is a function that handles the callback from the Gneiss authentication service. 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.
66
74
  * `auth.requireAuth` is a middleware function that checks if the user is authenticated. If the user is not authenticated, it redirects the user to the login page.
67
75
  * `auth.getUser` is an included utility route to allow one to retrieve the current user's data. It is important to include the `auth.requireAuth` middleware to ensure the access token is present before accessing the user's data. If it is not, an exeption will be thrown.
package/dist/cjs/index.js CHANGED
@@ -46,7 +46,6 @@ var AuthGneissCore = class {
46
46
  this.gneissEnpoint = process.env.GNEISS_ENDPOINT;
47
47
  this.loginUrl = this.gneissEnpoint ? `${this.gneissEnpoint}/auth/login` : void 0;
48
48
  this.logoutUrl = this.gneissEnpoint ? `${this.gneissEnpoint}/auth/logout` : void 0;
49
- this.invalidateUrl = this.gneissEnpoint ? `${this.gneissEnpoint}/auth/invalidate_token` : void 0;
50
49
  let errorMsgs = [];
51
50
  if (!process.env.GNEISS_ENDPOINT) {
52
51
  errorMsgs.push("GNEISS_ENDPOINT is not set in environment variables");
@@ -91,12 +90,12 @@ var AuthGneissCore = class {
91
90
  async refreshToken(refreshToken) {
92
91
  try {
93
92
  const url = `${this.gneissEnpoint}/auth/refresh`;
94
- const response = await import_axios.default.post(url, {
93
+ const response = await import_axios.default.post(url, {}, {
95
94
  headers: {
96
95
  "Authorization": `Bearer ${refreshToken}`
97
96
  }
98
97
  });
99
- return response.data.accessToken;
98
+ return response.data.access_token;
100
99
  } catch (error) {
101
100
  return null;
102
101
  }
@@ -151,6 +150,17 @@ var AuthGneissCore = class {
151
150
  getLoginUrl() {
152
151
  return this.loginUrl;
153
152
  }
153
+ /**
154
+ * deleteUser deletes the user
155
+ * */
156
+ async deleteUserData(accessToken) {
157
+ const response = await import_axios.default.post(`${this.gneissEnpoint}/resource/delete_user`, {}, {
158
+ headers: {
159
+ "Authorization": `Bearer ${accessToken}`
160
+ }
161
+ });
162
+ return response.data;
163
+ }
154
164
  };
155
165
  var AuthGneissCore_default = AuthGneissCore;
156
166
 
@@ -164,7 +174,7 @@ function setAccessToken(res, accessToken) {
164
174
  res.cookie("accessToken", accessToken, {
165
175
  httpOnly: true,
166
176
  secure: process.env.NODE_ENV === "production",
167
- sameSite: "strict",
177
+ sameSite: "lax",
168
178
  maxAge: decodedToken.exp * 1e3 - Date.now()
169
179
  });
170
180
  }
@@ -176,7 +186,7 @@ function setRefreshToken(res, refreshToken) {
176
186
  res.cookie("refreshToken", refreshToken, {
177
187
  httpOnly: true,
178
188
  secure: process.env.NODE_ENV === "production",
179
- sameSite: "strict",
189
+ sameSite: "lax",
180
190
  maxAge: decodedToken.exp * 1e3 - Date.now()
181
191
  });
182
192
  }
@@ -217,6 +227,7 @@ var ExpressAuthGneissClient = class extends AuthGneissCore_default {
217
227
  this.login = this.login.bind(this);
218
228
  this.logout = this.logout.bind(this);
219
229
  this.getUser = this.getUser.bind(this);
230
+ this.deleteUser = this.deleteUser.bind(this);
220
231
  }
221
232
  /**
222
233
  * requireAuth is a middleware function that checks if the access token is valid.
@@ -235,6 +246,7 @@ var ExpressAuthGneissClient = class extends AuthGneissCore_default {
235
246
  const newAccessToken = await this.refreshToken(cookies?.refreshToken);
236
247
  if (newAccessToken) {
237
248
  setAccessToken(res, newAccessToken);
249
+ res.redirect(req.originalUrl);
238
250
  } else {
239
251
  const returnToUrl = req.originalUrl;
240
252
  res.redirect(`${this.loginUrl}?redirect_url=${this.config.baseUrl}${this.config.redirectUrl}&return_to_url=${returnToUrl}`);
@@ -324,24 +336,34 @@ var ExpressAuthGneissClient = class extends AuthGneissCore_default {
324
336
  if (!this.logoutUrl) {
325
337
  throw new Error("Logout URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.");
326
338
  }
327
- if (!this.invalidateUrl) {
328
- throw new Error("Invalidate URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.");
329
- }
330
339
  if (cookies?.accessToken) {
331
- import_axios4.default.post(this.invalidateUrl, {}, {
332
- // Invalidate the access token
340
+ import_axios4.default.post(this.logoutUrl, {}, {
341
+ // Logout
333
342
  headers: {
334
343
  "Authorization": `Bearer ${cookies?.accessToken}`
335
344
  }
336
345
  });
337
346
  }
338
347
  clearCookies(res);
339
- res.redirect(this.logoutUrl + `?redirect_url=${this.config.baseUrl}`);
348
+ res.redirect("/");
340
349
  } catch (error) {
341
350
  console.error("Error in logout middleware:", error);
342
351
  res.status(500).send("Internal server error");
343
352
  }
344
353
  }
354
+ /**
355
+ * Utility route handler for deleting a user
356
+ * This ensures that the user is fully logged out before
357
+ * deleting the user's data
358
+ *
359
+ * @param req - The request object.
360
+ * @param res - The response object.
361
+ */
362
+ deleteUser(req, res) {
363
+ const cookies = parseCookies(req);
364
+ this.logout(req, res);
365
+ this.deleteUserData(cookies?.accessToken);
366
+ }
345
367
  };
346
368
  var ExpressAuthGneissClient_default = ExpressAuthGneissClient;
347
369
  // Annotate the CommonJS export names for ESM import in node:
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/index.ts", "../../src/core/AuthGneissCore.ts", "../../src/utils/storage/cookieHandling.ts", "../../src/frameworks/express/middleware/ExpressAuthGneissClient.ts"],
4
- "sourcesContent": ["export { ExpressAuthGneissClient } from \"./frameworks\";\r\nexport { AuthGneissCore } from \"./core\";\r\nexport type { AuthGneissCoreConfig } from \"./core\";\r\n", "import { AuthGneissCoreConfig } from \"@core/types\";\r\nimport axios, { AxiosResponse } from \"axios\";\r\nimport { Tokens } from \"@core/types\";\r\nimport { JwtPayload } from \"jsonwebtoken\";\r\nimport dotenv from \"dotenv\";\r\nimport { AxiosError } from \"axios\";\r\n\r\n//load environment variables\r\ndotenv.config();\r\n\r\n/**\r\n * AuthGneissCore provides core functionality for OAuth2 authentication flow with Gneiss authentication service.\r\n * It handles token exchange, token refresh, user data fetching, and token validation.\r\n * \r\n * This class serves as a base class that can be extended by framework-specific implementations\r\n * to provide authentication middleware and handlers.\r\n */\r\nclass AuthGneissCore {\r\n protected config: AuthGneissCoreConfig; // Configuration object\r\n protected gneissEnpoint : string | undefined\r\n protected loginUrl : string | undefined\r\n protected logoutUrl : string | undefined\r\n protected invalidateUrl : string | undefined\r\n\r\n constructor(\r\n config: AuthGneissCoreConfig\r\n ) {\r\n this.config = config;\r\n this.gneissEnpoint = process.env.GNEISS_ENDPOINT // Gneiss endpoint\r\n this.loginUrl = this.gneissEnpoint ? `${this.gneissEnpoint}/auth/login` : undefined; // Login URL\r\n this.logoutUrl = this.gneissEnpoint ? `${this.gneissEnpoint}/auth/logout` : undefined; // Logout URL\r\n this.invalidateUrl = this.gneissEnpoint ? `${this.gneissEnpoint}/auth/invalidate_token` : undefined; // Invalidate URL\r\n\r\n //check if environment variables are set\r\n let errorMsgs = [];\r\n if (!process.env.GNEISS_ENDPOINT) {\r\n errorMsgs.push(\"GNEISS_ENDPOINT is not set in environment variables\");\r\n }\r\n if (!process.env.NODE_ENV) {\r\n errorMsgs.push(\"NODE_ENV is not set in environment variables\");\r\n }\r\n if (errorMsgs.length > 0) {\r\n throw new Error(errorMsgs.join(\"\\n\"));\r\n }\r\n }\r\n\r\n /**\r\n * getTokens is a method that exchanges an authentication code for access and refresh tokens.\r\n * The client id and secret are passed as basic auth headers to authenticate the client itself.\r\n * @param authCode - The authentication code received from the Gneiss authentication service.\r\n * @returns A promise that resolves to an object containing the access and refresh tokens.\r\n */\r\n async getTokens(authCode : string) : Promise<Tokens> {\r\n try {\r\n const url : string = `${this.gneissEnpoint}/auth/access_token?auth_code=${authCode}`;\r\n //Encode in base64 before transport\r\n const encodedClientId = btoa(this.config.clientId);\r\n const encodedClientSecret = btoa(this.config.clientSecret);\r\n const response : AxiosResponse = await axios.post(url, {}, {\r\n headers: {\r\n \"Authorization\": `Basic ${encodedClientId}:${encodedClientSecret}`\r\n }\r\n });\r\n return {\r\n accessToken: response.data.access_token,\r\n refreshToken: response.data.refresh_token,\r\n tokenType: response.data.token_type\r\n } as Tokens;\r\n } catch (error) {\r\n // console.error(\"Error in getTokens:\", error);\r\n throw error;\r\n }\r\n }\r\n \r\n /**\r\n * refreshToken is a method that refreshes the access token using the refresh token.\r\n * @param refreshToken - The refresh token to be used for token refresh.\r\n * @returns A promise that resolves to the refreshed access token.\r\n */\r\n async refreshToken(refreshToken: string): Promise<string | null> {\r\n try {\r\n const url : string = `${this.gneissEnpoint}/auth/refresh`;\r\n const response : AxiosResponse = await axios.post(url, {\r\n headers: {\r\n \"Authorization\": `Bearer ${refreshToken}`\r\n }\r\n });\r\n return response.data.accessToken as string;\r\n } catch (error) {\r\n // console.error(\"Error in refreshToken:\", error);\r\n return null;\r\n }\r\n }\r\n \r\n /**\r\n * getUserData is a method that fetches user data using the access token.\r\n * @param accessToken - The access token to be used for user data fetching.\r\n * @returns A promise that resolves to the user data.\r\n */\r\n async getUserData(accessToken: string) {\r\n const url : string = `${this.gneissEnpoint}/resource/user_data`;\r\n const response : AxiosResponse = await axios.get(url, {\r\n headers: {\r\n \"Authorization\": `Bearer ${accessToken}`\r\n }\r\n });\r\n if (response.status === 200) {\r\n return response.data;\r\n }\r\n throw new Error(\"Failed to fetch user data\");\r\n }\r\n \r\n /**\r\n * validateToken is a method that validates the access token.\r\n * @param token - The access token to be validated.\r\n * @returns A promise that resolves to a boolean indicating the validity of the token.\r\n */\r\n async validateToken(token: string): Promise<boolean> {\r\n try {\r\n console.log(\"DEBUG: token\", token);\r\n // Token validation logic\r\n if (!token) {\r\n return false;\r\n }\r\n const url : string = `${this.gneissEnpoint}/auth/validate_token`;\r\n const response : AxiosResponse = await axios.get(url, {\r\n headers: {\r\n \"Authorization\": `Bearer ${token}`\r\n }\r\n });\r\n return response.status === 200;\r\n } catch (error) {\r\n // console.error(\"Error in validateToken:\", error);\r\n if (error instanceof AxiosError && error.response?.status === 401) {\r\n return false;\r\n } else {\r\n throw error;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * getLoginUrl is a method that returns the login URL.\r\n * @returns The login URL.\r\n */\r\n public getLoginUrl() : string | undefined {\r\n return this.loginUrl;\r\n }\r\n}\r\n\r\nexport default AuthGneissCore;\r\n", "import { Response } from \"express\";\r\nimport { JwtPayload, decode } from \"jsonwebtoken\";\r\nimport { Request } from \"express\";\r\n\r\n/**\r\n * Set the access token in the response cookies.\r\n * @param res - The response object.\r\n * @param accessToken - The access token to set.\r\n */\r\nfunction setAccessToken(res: Response, accessToken: string) {\r\n\r\n const decodedToken = decode(accessToken) as JwtPayload;\r\n \r\n // decoded.exp is in seconds since epoch\r\n // Date.now() returns milliseconds since epoch\r\n // maxAge needs milliseconds remaining\r\n if (!decodedToken.exp) {\r\n throw new Error(\"Access token does not contain an expiration time\");\r\n }\r\n \r\n res.cookie('accessToken', accessToken, {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'strict',\r\n maxAge: (decodedToken.exp * 1000) - Date.now()\r\n });\r\n}\r\n\r\n/**\r\n * Set the refresh token in the response cookies.\r\n * @param res - The response object.\r\n * @param refreshToken - The refresh token to set.\r\n */\r\nfunction setRefreshToken(res: Response, refreshToken: string) {\r\n\r\n const decodedToken = decode(refreshToken) as JwtPayload;\r\n\r\n if (!decodedToken.exp) {\r\n throw new Error(\"Refresh token does not contain an expiration time\");\r\n }\r\n\r\n res.cookie('refreshToken', refreshToken, {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'strict',\r\n maxAge: (decodedToken.exp * 1000) - Date.now()\r\n });\r\n}\r\n\r\nfunction parseCookies(req: Request) : { [key: string]: string } {\r\n const cookies = req.headers.cookie;\r\n if (!cookies) {\r\n return {};\r\n }\r\n return cookies.split(';').reduce((acc: { [key: string]: string }, cookie) => {\r\n const [key, value] = cookie.split('=').map(s => s.trim());\r\n acc[key] = value;\r\n return acc;\r\n }, {});\r\n}\r\n\r\nfunction clearCookies(res: Response) {\r\n res.clearCookie(\"accessToken\", {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'strict',\r\n path: '/'\r\n });\r\n res.clearCookie(\"refreshToken\", {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'strict',\r\n path: '/'\r\n });\r\n}\r\n\r\nexport { setAccessToken, setRefreshToken, parseCookies, clearCookies };\r\n", "import { AuthGneissCore, AuthGneissCoreConfig } from \"@core\";\r\nimport { Request, Response, NextFunction } from \"express\";\r\nimport { RequestWithTokens, Tokens } from \"@core/types\";\r\nimport { setAccessToken, setRefreshToken, parseCookies } from \"@utils\";\r\nimport { JwtPayload } from \"jsonwebtoken\";\r\nimport { AxiosError } from \"axios\";\r\nimport axios from \"axios\";\r\nimport { clearCookies } from \"@/utils/storage/cookieHandling\";\r\n\r\n/**\r\n * ExpressAuthGneissClient extends AuthGneissCore to provide Express-specific authentication middleware\r\n * and functionality for handling OAuth2 authentication flow with Gneiss authentication service.\r\n * \r\n * @extends AuthGneissCore\r\n * @example\r\n * const authClient = new ExpressAuthGneissClient({\r\n * clientId: 'your-client-id',\r\n * clientSecret: 'your-client-secret',\r\n * redirectUrl: 'your-redirect-url'\r\n * });\r\n */\r\nclass ExpressAuthGneissClient extends AuthGneissCore {\r\n\r\n constructor(\r\n config: AuthGneissCoreConfig\r\n ) {\r\n super(config);\r\n \r\n // Bind the methods in constructor\r\n this.requireAuth = this.requireAuth.bind(this);\r\n this.handleCallBack = this.handleCallBack.bind(this);\r\n this.login = this.login.bind(this);\r\n this.logout = this.logout.bind(this);\r\n this.getUser = this.getUser.bind(this);\r\n }\r\n\r\n /**\r\n * requireAuth is a middleware function that checks if the access token is valid.\r\n * If the access token is not valid, it attempts to refresh the token using the refresh token.\r\n * If the refresh token is not valid, it redirects the user to the login page.\r\n * @param req - The request object.\r\n * @param res - The response object.\r\n * @param next - The next middleware function.\r\n */\r\n public async requireAuth(req: Request, res: Response, next: NextFunction): Promise<void> {\r\n const cookies = parseCookies(req);\r\n //Check for the existence of the access token\r\n console.log(\"DEBUG: cookies\", cookies);\r\n try {\r\n const isAccessTokenValid : boolean = await this.validateToken(cookies?.accessToken);\r\n if (!isAccessTokenValid) { //if the access token is not valid\r\n //try to refresh the token\r\n const newAccessToken : string | null = await this.refreshToken(cookies?.refreshToken);\r\n if (newAccessToken) { //\r\n setAccessToken(res, newAccessToken);\r\n }\r\n else {\r\n // no access token or valid refresh token, redirect to login\r\n const returnToUrl : string | undefined = req.originalUrl as string;\r\n res.redirect(`${this.loginUrl}?redirect_url=${this.config.baseUrl}${this.config.redirectUrl}&return_to_url=${returnToUrl}`);\r\n }\r\n }\r\n else {\r\n // access token is valid, continue to the next middleware or route handler\r\n next();\r\n }\r\n } catch (error) {\r\n // console.error('Error in requireAuth middleware:', error);\r\n if (error instanceof AxiosError) {\r\n res.status((error as AxiosError).response?.status || 500).send((error as AxiosError).response?.data || 'Internal server error');\r\n } else {\r\n res.status(500).send('Internal server error');\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * getUserData is a middleware function that fetches user data using the access token.\r\n * @param req - The request object.\r\n * @param res - The response object.\r\n * @param next - The next middleware function.\r\n */\r\n public async getUser(req: Request, res: Response): Promise<void> {\r\n const cookies = parseCookies(req);\r\n const accessToken = cookies?.accessToken;\r\n if (!accessToken) {\r\n throw new Error(\"No access token found in request cookies\");\r\n }\r\n const userData = await this.getUserData(accessToken);\r\n res.status(200).send(userData);\r\n }\r\n\r\n /**\r\n * handleCallBack is a middleware function that handles the callback from the authentication service.\r\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.\r\n * @param req - The request object.\r\n * @param res - The response object.\r\n * @param next - The next middleware function.\r\n */\r\n public async handleCallBack(\r\n req: Request,\r\n res: Response,\r\n next: NextFunction\r\n ): Promise<void> {\r\n try {\r\n const authCode: string | undefined = req.query.auth_code as string\r\n const returnToUrl : string | undefined = req.query.return_to_url as string;\r\n if (!authCode) {\r\n throw new Error(\"No auth code found in request url parameters\");\r\n }\r\n\r\n const tokens: Tokens = await this.getTokens(authCode);\r\n \r\n // Set the access and refresh tokens in the response cookies\r\n setAccessToken(res, tokens.accessToken);\r\n setRefreshToken(res, tokens.refreshToken);\r\n\r\n if (returnToUrl) {\r\n // Go to the original request url\r\n res.redirect(returnToUrl);\r\n }\r\n else {\r\n // Go to the root url\r\n res.redirect(\"/\")\r\n }\r\n } catch (error) {\r\n // console.error('Error in handleCallBack middleware:', error);\r\n if (error instanceof AxiosError) {\r\n res.status((error as AxiosError).response?.status || 500).send((error as AxiosError).response?.data || 'Internal server error');\r\n console.error(\"DEBUG: error\", error);\r\n } else {\r\n res.status(500).send('Internal server error');\r\n console.error(\"DEBUG: error\", error);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * login is a function that redirects the user to the Gneiss authentication service for authentication.\r\n * @param req - The request object.\r\n * @param res - The response object.\r\n */\r\n public login(req: Request, res: Response): void {\r\n try {\r\n if (!this.loginUrl) {\r\n throw new Error('Login URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.');\r\n }\r\n res.redirect(this.loginUrl + `?redirect_url=${this.config.baseUrl}${this.config.redirectUrl}`);\r\n } catch (error) {\r\n console.error('Error in login middleware:', error);\r\n res.status(500).send('Internal server error');\r\n }\r\n }\r\n\r\n /**\r\n * logout is a function that redirects the user to the Gneiss logout service.\r\n * @param req - The request object.\r\n * @param res - The response object.\r\n */\r\n public logout(req: Request, res: Response): void {\r\n const cookies = parseCookies(req);\r\n try {\r\n if (!this.logoutUrl) {\r\n throw new Error('Logout URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.');\r\n }\r\n if (!this.invalidateUrl) {\r\n throw new Error('Invalidate URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.');\r\n }\r\n if (cookies?.accessToken) { // Only invalidate the access token if it exists\r\n axios.post(this.invalidateUrl, {}, { // Invalidate the access token\r\n headers: {\r\n \"Authorization\": `Bearer ${cookies?.accessToken}`\r\n }\r\n });\r\n }\r\n clearCookies(res); // clear the access and refresh cookies\r\n res.redirect(this.logoutUrl + `?redirect_url=${this.config.baseUrl}`); // logout from Gneiss by visiting SSO logout page\r\n } catch (error) {\r\n console.error('Error in logout middleware:', error);\r\n res.status(500).send('Internal server error');\r\n }\r\n }\r\n}\r\n\r\nexport default ExpressAuthGneissClient;\r\n"],
5
- "mappings": ";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;;;ACCA,mBAAqC;AAGrC,oBAAmB;AACnB,IAAAA,gBAA2B;AAG3B,cAAAC,QAAO,OAAO;AASd,IAAM,iBAAN,MAAqB;AAAA,EAOjB,YACI,QACF;AACE,SAAK,SAAS;AACd,SAAK,gBAAgB,QAAQ,IAAI;AACjC,SAAK,WAAW,KAAK,gBAAgB,GAAG,KAAK,aAAa,gBAAgB;AAC1E,SAAK,YAAY,KAAK,gBAAgB,GAAG,KAAK,aAAa,iBAAiB;AAC5E,SAAK,gBAAgB,KAAK,gBAAgB,GAAG,KAAK,aAAa,2BAA2B;AAG1F,QAAI,YAAY,CAAC;AACjB,QAAI,CAAC,QAAQ,IAAI,iBAAiB;AAC9B,gBAAU,KAAK,qDAAqD;AAAA,IACxE;AACA,QAAI,CAAC,QAAQ,IAAI,UAAU;AACvB,gBAAU,KAAK,8CAA8C;AAAA,IACjE;AACA,QAAI,UAAU,SAAS,GAAG;AACtB,YAAM,IAAI,MAAM,UAAU,KAAK,IAAI,CAAC;AAAA,IACxC;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAM,UAAU,UAAqC;AACjD,QAAI;AACA,YAAM,MAAe,GAAG,KAAK,aAAa,gCAAgC,QAAQ;AAElF,YAAM,kBAAkB,KAAK,KAAK,OAAO,QAAQ;AACjD,YAAM,sBAAsB,KAAK,KAAK,OAAO,YAAY;AACzD,YAAM,WAA2B,MAAM,aAAAC,QAAM,KAAK,KAAK,CAAC,GAAG;AAAA,QACvD,SAAS;AAAA,UACL,iBAAiB,SAAS,eAAe,IAAI,mBAAmB;AAAA,QACpE;AAAA,MACJ,CAAC;AACD,aAAO;AAAA,QACH,aAAa,SAAS,KAAK;AAAA,QAC3B,cAAc,SAAS,KAAK;AAAA,QAC5B,WAAW,SAAS,KAAK;AAAA,MAC7B;AAAA,IACJ,SAAS,OAAO;AAEZ,YAAM;AAAA,IACV;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,aAAa,cAA8C;AAC7D,QAAI;AACA,YAAM,MAAe,GAAG,KAAK,aAAa;AAC1C,YAAM,WAA2B,MAAM,aAAAA,QAAM,KAAK,KAAK;AAAA,QACnD,SAAS;AAAA,UACT,iBAAiB,UAAU,YAAY;AAAA,QAC3C;AAAA,MACA,CAAC;AACD,aAAO,SAAS,KAAK;AAAA,IACzB,SAAS,OAAO;AAEZ,aAAO;AAAA,IACX;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,YAAY,aAAqB;AACnC,UAAM,MAAe,GAAG,KAAK,aAAa;AAC1C,UAAM,WAA2B,MAAM,aAAAA,QAAM,IAAI,KAAK;AAAA,MAClD,SAAS;AAAA,QACL,iBAAiB,UAAU,WAAW;AAAA,MAC1C;AAAA,IACJ,CAAC;AACD,QAAI,SAAS,WAAW,KAAK;AACzB,aAAO,SAAS;AAAA,IACpB;AACA,UAAM,IAAI,MAAM,2BAA2B;AAAA,EAC/C;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOA,MAAM,cAAc,OAAiC;AACjD,QAAI;AACA,cAAQ,IAAI,gBAAgB,KAAK;AAEjC,UAAI,CAAC,OAAO;AACR,eAAO;AAAA,MACX;AACA,YAAM,MAAe,GAAG,KAAK,aAAa;AAC1C,YAAM,WAA2B,MAAM,aAAAA,QAAM,IAAI,KAAK;AAAA,QAClD,SAAS;AAAA,UACL,iBAAiB,UAAU,KAAK;AAAA,QACpC;AAAA,MACJ,CAAC;AACD,aAAO,SAAS,WAAW;AAAA,IAC/B,SAAS,OAAO;AAEZ,UAAI,iBAAiB,4BAAc,MAAM,UAAU,WAAW,KAAK;AAC/D,eAAO;AAAA,MACX,OAAO;AACH,cAAM;AAAA,MACV;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA,EAMO,cAAmC;AACtC,WAAO,KAAK;AAAA,EAChB;AACJ;AAEA,IAAO,yBAAQ;;;ACrJf,0BAAmC;AAQnC,SAAS,eAAe,KAAe,aAAqB;AAExD,QAAM,mBAAe,4BAAO,WAAW;AAKvC,MAAI,CAAC,aAAa,KAAK;AACnB,UAAM,IAAI,MAAM,kDAAkD;AAAA,EACtE;AAEA,MAAI,OAAO,eAAe,aAAa;AAAA,IACnC,UAAU;AAAA,IACV,QAAQ,QAAQ,IAAI,aAAa;AAAA,IACjC,UAAU;AAAA,IACV,QAAS,aAAa,MAAM,MAAQ,KAAK,IAAI;AAAA,EACjD,CAAC;AACL;AAOA,SAAS,gBAAgB,KAAe,cAAsB;AAE1D,QAAM,mBAAe,4BAAO,YAAY;AAExC,MAAI,CAAC,aAAa,KAAK;AACnB,UAAM,IAAI,MAAM,mDAAmD;AAAA,EACvE;AAEA,MAAI,OAAO,gBAAgB,cAAc;AAAA,IACrC,UAAU;AAAA,IACV,QAAQ,QAAQ,IAAI,aAAa;AAAA,IACjC,UAAU;AAAA,IACV,QAAS,aAAa,MAAM,MAAQ,KAAK,IAAI;AAAA,EACjD,CAAC;AACL;AAEA,SAAS,aAAa,KAA0C;AAC5D,QAAM,UAAU,IAAI,QAAQ;AAC5B,MAAI,CAAC,SAAS;AACV,WAAO,CAAC;AAAA,EACZ;AACA,SAAO,QAAQ,MAAM,GAAG,EAAE,OAAO,CAAC,KAAgC,WAAW;AACzE,UAAM,CAAC,KAAK,KAAK,IAAI,OAAO,MAAM,GAAG,EAAE,IAAI,OAAK,EAAE,KAAK,CAAC;AACxD,QAAI,GAAG,IAAI;AACX,WAAO;AAAA,EACX,GAAG,CAAC,CAAC;AACT;AAEA,SAAS,aAAa,KAAe;AACjC,MAAI,YAAY,eAAe;AAAA,IAC3B,UAAU;AAAA,IACV,QAAQ,QAAQ,IAAI,aAAa;AAAA,IACjC,UAAU;AAAA,IACV,MAAM;AAAA,EACV,CAAC;AACD,MAAI,YAAY,gBAAgB;AAAA,IAC5B,UAAU;AAAA,IACV,QAAQ,QAAQ,IAAI,aAAa;AAAA,IACjC,UAAU;AAAA,IACV,MAAM;AAAA,EACV,CAAC;AACL;;;ACrEA,IAAAC,gBAA2B;AAC3B,IAAAA,gBAAkB;AAelB,IAAM,0BAAN,cAAsC,uBAAe;AAAA,EAEjD,YACI,QACF;AACE,UAAM,MAAM;AAGZ,SAAK,cAAc,KAAK,YAAY,KAAK,IAAI;AAC7C,SAAK,iBAAiB,KAAK,eAAe,KAAK,IAAI;AACnD,SAAK,QAAQ,KAAK,MAAM,KAAK,IAAI;AACjC,SAAK,SAAS,KAAK,OAAO,KAAK,IAAI;AACnC,SAAK,UAAU,KAAK,QAAQ,KAAK,IAAI;AAAA,EACzC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAUA,MAAa,YAAY,KAAc,KAAe,MAAmC;AACrF,UAAM,UAAU,aAAa,GAAG;AAEhC,YAAQ,IAAI,kBAAkB,OAAO;AACrC,QAAI;AACA,YAAM,qBAA+B,MAAM,KAAK,cAAc,SAAS,WAAW;AAClF,UAAI,CAAC,oBAAoB;AAErB,cAAM,iBAAiC,MAAM,KAAK,aAAa,SAAS,YAAY;AACpF,YAAI,gBAAgB;AAChB,yBAAe,KAAK,cAAc;AAAA,QACtC,OACK;AAED,gBAAM,cAAmC,IAAI;AAC7C,cAAI,SAAS,GAAG,KAAK,QAAQ,iBAAiB,KAAK,OAAO,OAAO,GAAG,KAAK,OAAO,WAAW,kBAAkB,WAAW,EAAE;AAAA,QAC9H;AAAA,MACJ,OACK;AAED,aAAK;AAAA,MACT;AAAA,IACJ,SAAS,OAAO;AAEZ,UAAI,iBAAiB,0BAAY;AAC7B,YAAI,OAAQ,MAAqB,UAAU,UAAU,GAAG,EAAE,KAAM,MAAqB,UAAU,QAAQ,uBAAuB;AAAA,MAClI,OAAO;AACH,YAAI,OAAO,GAAG,EAAE,KAAK,uBAAuB;AAAA,MAChD;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAQA,MAAa,QAAQ,KAAc,KAA8B;AAC7D,UAAM,UAAU,aAAa,GAAG;AAChC,UAAM,cAAc,SAAS;AAC7B,QAAI,CAAC,aAAa;AACd,YAAM,IAAI,MAAM,0CAA0C;AAAA,IAC9D;AACA,UAAM,WAAW,MAAM,KAAK,YAAY,WAAW;AACnD,QAAI,OAAO,GAAG,EAAE,KAAK,QAAQ;AAAA,EACjC;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EASA,MAAa,eACT,KACA,KACA,MACa;AACb,QAAI;AACA,YAAM,WAA+B,IAAI,MAAM;AAC/C,YAAM,cAAmC,IAAI,MAAM;AACnD,UAAI,CAAC,UAAU;AACX,cAAM,IAAI,MAAM,8CAA8C;AAAA,MAClE;AAEA,YAAM,SAAiB,MAAM,KAAK,UAAU,QAAQ;AAGpD,qBAAe,KAAK,OAAO,WAAW;AACtC,sBAAgB,KAAK,OAAO,YAAY;AAExC,UAAI,aAAa;AAEb,YAAI,SAAS,WAAW;AAAA,MAC5B,OACK;AAED,YAAI,SAAS,GAAG;AAAA,MACpB;AAAA,IACJ,SAAS,OAAO;AAEZ,UAAI,iBAAiB,0BAAY;AAC7B,YAAI,OAAQ,MAAqB,UAAU,UAAU,GAAG,EAAE,KAAM,MAAqB,UAAU,QAAQ,uBAAuB;AAC9H,gBAAQ,MAAM,gBAAgB,KAAK;AAAA,MACvC,OAAO;AACH,YAAI,OAAO,GAAG,EAAE,KAAK,uBAAuB;AAC5C,gBAAQ,MAAM,gBAAgB,KAAK;AAAA,MACvC;AAAA,IACJ;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,MAAM,KAAc,KAAqB;AAC5C,QAAI;AACA,UAAI,CAAC,KAAK,UAAU;AAChB,cAAM,IAAI,MAAM,oFAAoF;AAAA,MACxG;AACA,UAAI,SAAS,KAAK,WAAW,iBAAiB,KAAK,OAAO,OAAO,GAAG,KAAK,OAAO,WAAW,EAAE;AAAA,IACjG,SAAS,OAAO;AACZ,cAAQ,MAAM,8BAA8B,KAAK;AACjD,UAAI,OAAO,GAAG,EAAE,KAAK,uBAAuB;AAAA,IAChD;AAAA,EACJ;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,EAOO,OAAO,KAAc,KAAqB;AAC7C,UAAM,UAAU,aAAa,GAAG;AAChC,QAAI;AACA,UAAI,CAAC,KAAK,WAAW;AACjB,cAAM,IAAI,MAAM,qFAAqF;AAAA,MACzG;AACA,UAAI,CAAC,KAAK,eAAe;AACrB,cAAM,IAAI,MAAM,yFAAyF;AAAA,MAC7G;AACA,UAAI,SAAS,aAAa;AACtB,sBAAAC,QAAM,KAAK,KAAK,eAAe,CAAC,GAAG;AAAA;AAAA,UAC/B,SAAS;AAAA,YACL,iBAAiB,UAAU,SAAS,WAAW;AAAA,UACnD;AAAA,QACJ,CAAC;AAAA,MACL;AACA,mBAAa,GAAG;AAChB,UAAI,SAAS,KAAK,YAAY,iBAAiB,KAAK,OAAO,OAAO,EAAE;AAAA,IACxE,SAAS,OAAO;AACZ,cAAQ,MAAM,+BAA+B,KAAK;AAClD,UAAI,OAAO,GAAG,EAAE,KAAK,uBAAuB;AAAA,IAChD;AAAA,EACJ;AACJ;AAEA,IAAO,kCAAQ;",
4
+ "sourcesContent": ["export { ExpressAuthGneissClient } from \"./frameworks\";\r\nexport { AuthGneissCore } from \"./core\";\r\nexport type { AuthGneissCoreConfig } from \"./core\";\r\n", "import { AuthGneissCoreConfig } from \"@core/types\";\r\nimport axios, { AxiosResponse } from \"axios\";\r\nimport { Tokens } from \"@core/types\";\r\nimport dotenv from \"dotenv\";\r\nimport { AxiosError } from \"axios\";\r\n\r\n//load environment variables\r\ndotenv.config();\r\n\r\n/**\r\n * AuthGneissCore provides core functionality for OAuth2 authentication flow with Gneiss authentication service.\r\n * It handles token exchange, token refresh, user data fetching, and token validation.\r\n * \r\n * This class serves as a base class that can be extended by framework-specific implementations\r\n * to provide authentication middleware and handlers.\r\n */\r\nclass AuthGneissCore {\r\n protected config: AuthGneissCoreConfig; // Configuration object\r\n protected gneissEnpoint : string | undefined\r\n protected loginUrl : string | undefined\r\n protected logoutUrl : string | undefined\r\n\r\n constructor(\r\n config: AuthGneissCoreConfig\r\n ) {\r\n this.config = config;\r\n this.gneissEnpoint = process.env.GNEISS_ENDPOINT // Gneiss endpoint\r\n this.loginUrl = this.gneissEnpoint ? `${this.gneissEnpoint}/auth/login` : undefined; // Login URL\r\n this.logoutUrl = this.gneissEnpoint ? `${this.gneissEnpoint}/auth/logout` : undefined; // Logout URL\r\n\r\n //check if environment variables are set\r\n let errorMsgs = [];\r\n if (!process.env.GNEISS_ENDPOINT) {\r\n errorMsgs.push(\"GNEISS_ENDPOINT is not set in environment variables\");\r\n }\r\n if (!process.env.NODE_ENV) {\r\n errorMsgs.push(\"NODE_ENV is not set in environment variables\");\r\n }\r\n if (errorMsgs.length > 0) {\r\n throw new Error(errorMsgs.join(\"\\n\"));\r\n }\r\n }\r\n\r\n /**\r\n * getTokens is a method that exchanges an authentication code for access and refresh tokens.\r\n * The client id and secret are passed as basic auth headers to authenticate the client itself.\r\n * @param authCode - The authentication code received from the Gneiss authentication service.\r\n * @returns A promise that resolves to an object containing the access and refresh tokens.\r\n */\r\n protected async getTokens(authCode : string) : Promise<Tokens> {\r\n try {\r\n const url : string = `${this.gneissEnpoint}/auth/access_token?auth_code=${authCode}`;\r\n //Encode in base64 before transport\r\n const encodedClientId = btoa(this.config.clientId);\r\n const encodedClientSecret = btoa(this.config.clientSecret);\r\n const response : AxiosResponse = await axios.post(url, {}, {\r\n headers: {\r\n \"Authorization\": `Basic ${encodedClientId}:${encodedClientSecret}`\r\n }\r\n });\r\n return {\r\n accessToken: response.data.access_token,\r\n refreshToken: response.data.refresh_token,\r\n tokenType: response.data.token_type\r\n } as Tokens;\r\n } catch (error) {\r\n // console.error(\"Error in getTokens:\", error);\r\n throw error;\r\n }\r\n }\r\n \r\n /**\r\n * refreshToken is a method that refreshes the access token using the refresh token.\r\n * @param refreshToken - The refresh token to be used for token refresh.\r\n * @returns A promise that resolves to the refreshed access token.\r\n */\r\n protected async refreshToken(refreshToken: string): Promise<string | null> {\r\n try {\r\n const url : string = `${this.gneissEnpoint}/auth/refresh`;\r\n const response : AxiosResponse = await axios.post(url, {}, {\r\n headers: {\r\n \"Authorization\": `Bearer ${refreshToken}`\r\n }\r\n });\r\n return response.data.access_token as string;\r\n } catch (error) {\r\n // console.error(\"Error in refreshToken:\", error);\r\n return null;\r\n }\r\n }\r\n \r\n /**\r\n * getUserData is a method that fetches user data using the access token.\r\n * @param accessToken - The access token to be used for user data fetching.\r\n * @returns A promise that resolves to the user data.\r\n */\r\n protected async getUserData(accessToken: string) {\r\n const url : string = `${this.gneissEnpoint}/resource/user_data`;\r\n const response : AxiosResponse = await axios.get(url, {\r\n headers: {\r\n \"Authorization\": `Bearer ${accessToken}`\r\n }\r\n });\r\n if (response.status === 200) {\r\n return response.data;\r\n }\r\n throw new Error(\"Failed to fetch user data\");\r\n }\r\n \r\n /**\r\n * validateToken is a method that validates the access token.\r\n * @param token - The access token to be validated.\r\n * @returns A promise that resolves to a boolean indicating the validity of the token.\r\n */\r\n protected async validateToken(token: string): Promise<boolean> {\r\n try {\r\n console.log(\"DEBUG: token\", token);\r\n // Token validation logic\r\n if (!token) {\r\n return false;\r\n }\r\n const url : string = `${this.gneissEnpoint}/auth/validate_token`;\r\n const response : AxiosResponse = await axios.get(url, {\r\n headers: {\r\n \"Authorization\": `Bearer ${token}`\r\n }\r\n });\r\n return response.status === 200;\r\n } catch (error) {\r\n // console.error(\"Error in validateToken:\", error);\r\n if (error instanceof AxiosError && error.response?.status === 401) {\r\n return false;\r\n } else {\r\n throw error;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * getLoginUrl is a method that returns the login URL.\r\n * @returns The login URL.\r\n */\r\n public getLoginUrl() : string | undefined {\r\n return this.loginUrl;\r\n }\r\n\r\n /**\r\n * deleteUser deletes the user\r\n * */\r\n protected async deleteUserData(accessToken : string) : Promise<object> {\r\n const response : AxiosResponse = await axios.post(`${this.gneissEnpoint}/resource/delete_user`, {}, {\r\n headers: {\r\n \"Authorization\": `Bearer ${accessToken}`\r\n } \r\n });\r\n return response.data;\r\n }\r\n}\r\n\r\nexport default AuthGneissCore;\r\n", "import { Response } from \"express\";\r\nimport { JwtPayload, decode } from \"jsonwebtoken\";\r\nimport { Request } from \"express\";\r\n\r\n/**\r\n * Set the access token in the response cookies.\r\n * @param res - The response object.\r\n * @param accessToken - The access token to set.\r\n */\r\nfunction setAccessToken(res: Response, accessToken: string) {\r\n\r\n const decodedToken = decode(accessToken) as JwtPayload;\r\n \r\n // decoded.exp is in seconds since epoch\r\n // Date.now() returns milliseconds since epoch\r\n // maxAge needs milliseconds remaining\r\n if (!decodedToken.exp) {\r\n throw new Error(\"Access token does not contain an expiration time\");\r\n }\r\n \r\n res.cookie('accessToken', accessToken, {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'lax',\r\n maxAge: (decodedToken.exp * 1000) - Date.now()\r\n });\r\n}\r\n\r\n/**\r\n * Set the refresh token in the response cookies.\r\n * @param res - The response object.\r\n * @param refreshToken - The refresh token to set.\r\n */\r\nfunction setRefreshToken(res: Response, refreshToken: string) {\r\n\r\n const decodedToken = decode(refreshToken) as JwtPayload;\r\n\r\n if (!decodedToken.exp) {\r\n throw new Error(\"Refresh token does not contain an expiration time\");\r\n }\r\n\r\n res.cookie('refreshToken', refreshToken, {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'lax',\r\n maxAge: (decodedToken.exp * 1000) - Date.now()\r\n });\r\n}\r\n\r\nfunction parseCookies(req: Request) : { [key: string]: string } {\r\n const cookies = req.headers.cookie;\r\n if (!cookies) {\r\n return {};\r\n }\r\n return cookies.split(';').reduce((acc: { [key: string]: string }, cookie) => {\r\n const [key, value] = cookie.split('=').map(s => s.trim());\r\n acc[key] = value;\r\n return acc;\r\n }, {});\r\n}\r\n\r\nfunction clearCookies(res: Response) {\r\n res.clearCookie(\"accessToken\", {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'strict',\r\n path: '/'\r\n });\r\n res.clearCookie(\"refreshToken\", {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'strict',\r\n path: '/'\r\n });\r\n}\r\n\r\nexport { setAccessToken, setRefreshToken, parseCookies, clearCookies };\r\n", "import { AuthGneissCore, AuthGneissCoreConfig } from \"@core\";\r\nimport { Request, Response, NextFunction } from \"express\";\r\nimport { RequestWithTokens, Tokens } from \"@core/types\";\r\nimport { setAccessToken, setRefreshToken, parseCookies } from \"@utils\";\r\nimport { JwtPayload } from \"jsonwebtoken\";\r\nimport { AxiosError } from \"axios\";\r\nimport axios from \"axios\";\r\nimport { clearCookies } from \"@/utils/storage/cookieHandling\";\r\n\r\n/**\r\n * ExpressAuthGneissClient extends AuthGneissCore to provide Express-specific authentication middleware\r\n * and functionality for handling OAuth2 authentication flow with Gneiss authentication service.\r\n * \r\n * @extends AuthGneissCore\r\n * @example\r\n * const authClient = new ExpressAuthGneissClient({\r\n * clientId: 'your-client-id',\r\n * clientSecret: 'your-client-secret',\r\n * redirectUrl: 'your-redirect-url'\r\n * });\r\n */\r\nclass ExpressAuthGneissClient extends AuthGneissCore {\r\n\r\n constructor(\r\n config: AuthGneissCoreConfig\r\n ) {\r\n super(config);\r\n \r\n // Bind the methods in constructor\r\n this.requireAuth = this.requireAuth.bind(this);\r\n this.handleCallBack = this.handleCallBack.bind(this);\r\n this.login = this.login.bind(this);\r\n this.logout = this.logout.bind(this);\r\n this.getUser = this.getUser.bind(this);\r\n this.deleteUser = this.deleteUser.bind(this)\r\n }\r\n\r\n /**\r\n * requireAuth is a middleware function that checks if the access token is valid.\r\n * If the access token is not valid, it attempts to refresh the token using the refresh token.\r\n * If the refresh token is not valid, it redirects the user to the login page.\r\n * @param req - The request object.\r\n * @param res - The response object.\r\n * @param next - The next middleware function.\r\n */\r\n public async requireAuth(req: Request, res: Response, next: NextFunction): Promise<void> {\r\n const cookies = parseCookies(req);\r\n //Check for the existence of the access token\r\n console.log(\"DEBUG: cookies\", cookies);\r\n try {\r\n const isAccessTokenValid : boolean = await this.validateToken(cookies?.accessToken);\r\n if (!isAccessTokenValid) { //if the access token is not valid\r\n //try to refresh the token\r\n const newAccessToken : string | null = await this.refreshToken(cookies?.refreshToken);\r\n if (newAccessToken) { // set access token and then redirect to the original requested url to 'redo' the request with new access token\r\n setAccessToken(res, newAccessToken);\r\n res.redirect(req.originalUrl)\r\n }\r\n else {\r\n // no access token or valid refresh token, redirect to login\r\n const returnToUrl : string | undefined = req.originalUrl as string;\r\n res.redirect(`${this.loginUrl}?redirect_url=${this.config.baseUrl}${this.config.redirectUrl}&return_to_url=${returnToUrl}`);\r\n }\r\n }\r\n else {\r\n // access token is valid, continue to the next middleware or route handler\r\n next();\r\n }\r\n } catch (error) {\r\n // console.error('Error in requireAuth middleware:', error);\r\n if (error instanceof AxiosError) {\r\n res.status((error as AxiosError).response?.status || 500).send((error as AxiosError).response?.data || 'Internal server error');\r\n } else {\r\n res.status(500).send('Internal server error');\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * getUserData is a middleware function that fetches user data using the access token.\r\n * @param req - The request object.\r\n * @param res - The response object.\r\n * @param next - The next middleware function.\r\n */\r\n public async getUser(req: Request, res: Response): Promise<void> {\r\n const cookies = parseCookies(req);\r\n const accessToken = cookies?.accessToken;\r\n if (!accessToken) {\r\n throw new Error(\"No access token found in request cookies\");\r\n }\r\n const userData = await this.getUserData(accessToken);\r\n res.status(200).send(userData);\r\n }\r\n\r\n /**\r\n * handleCallBack is a middleware function that handles the callback from the authentication service.\r\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.\r\n * @param req - The request object.\r\n * @param res - The response object.\r\n * @param next - The next middleware function.\r\n */\r\n public async handleCallBack(\r\n req: Request,\r\n res: Response,\r\n next: NextFunction\r\n ): Promise<void> {\r\n try {\r\n const authCode: string | undefined = req.query.auth_code as string\r\n const returnToUrl : string | undefined = req.query.return_to_url as string;\r\n if (!authCode) {\r\n throw new Error(\"No auth code found in request url parameters\");\r\n }\r\n\r\n const tokens: Tokens = await this.getTokens(authCode);\r\n \r\n // Set the access and refresh tokens in the response cookies\r\n setAccessToken(res, tokens.accessToken);\r\n setRefreshToken(res, tokens.refreshToken);\r\n\r\n if (returnToUrl) {\r\n // Go to the original request url\r\n res.redirect(returnToUrl);\r\n }\r\n else {\r\n // Go to the root url\r\n res.redirect(\"/\")\r\n }\r\n } catch (error) {\r\n // console.error('Error in handleCallBack middleware:', error);\r\n if (error instanceof AxiosError) {\r\n res.status((error as AxiosError).response?.status || 500).send((error as AxiosError).response?.data || 'Internal server error');\r\n console.error(\"DEBUG: error\", error);\r\n } else {\r\n res.status(500).send('Internal server error');\r\n console.error(\"DEBUG: error\", error);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * login is a function that redirects the user to the Gneiss authentication service for authentication.\r\n * @param req - The request object.\r\n * @param res - The response object.\r\n */\r\n public login(req: Request, res: Response): void {\r\n try {\r\n if (!this.loginUrl) {\r\n throw new Error('Login URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.');\r\n }\r\n res.redirect(this.loginUrl + `?redirect_url=${this.config.baseUrl}${this.config.redirectUrl}`);\r\n } catch (error) {\r\n console.error('Error in login middleware:', error);\r\n res.status(500).send('Internal server error');\r\n }\r\n }\r\n\r\n /**\r\n * logout is a function that redirects the user to the Gneiss logout service.\r\n * @param req - The request object.\r\n * @param res - The response object.\r\n */\r\n public logout(req: Request, res: Response): void {\r\n const cookies = parseCookies(req);\r\n try {\r\n if (!this.logoutUrl) {\r\n throw new Error('Logout URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.');\r\n }\r\n if (cookies?.accessToken) { // Only logout if the access token exists\r\n axios.post(this.logoutUrl, {}, { // Logout\r\n headers: {\r\n \"Authorization\": `Bearer ${cookies?.accessToken}`\r\n }\r\n });\r\n }\r\n clearCookies(res); // clear the access and refresh cookies\r\n res.redirect(\"/\") // Redirect back to home after logout\r\n } catch (error) {\r\n console.error('Error in logout middleware:', error);\r\n res.status(500).send('Internal server error');\r\n }\r\n }\r\n\r\n /**\r\n * Utility route handler for deleting a user\r\n * This ensures that the user is fully logged out before \r\n * deleting the user's data\r\n * \r\n * @param req - The request object.\r\n * @param res - The response object.\r\n */\r\n public deleteUser(req: Request, res: Response) {\r\n const cookies = parseCookies(req);\r\n this.logout(req, res)\r\n this.deleteUserData(cookies?.accessToken)\r\n }\r\n}\r\n\r\nexport default ExpressAuthGneissClient;\r\n"],
5
+ "mappings": "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",
6
6
  "names": ["import_axios", "dotenv", "axios", "import_axios", "axios"]
7
7
  }
package/dist/esm/index.js CHANGED
@@ -9,7 +9,6 @@ var AuthGneissCore = class {
9
9
  this.gneissEnpoint = process.env.GNEISS_ENDPOINT;
10
10
  this.loginUrl = this.gneissEnpoint ? `${this.gneissEnpoint}/auth/login` : void 0;
11
11
  this.logoutUrl = this.gneissEnpoint ? `${this.gneissEnpoint}/auth/logout` : void 0;
12
- this.invalidateUrl = this.gneissEnpoint ? `${this.gneissEnpoint}/auth/invalidate_token` : void 0;
13
12
  let errorMsgs = [];
14
13
  if (!process.env.GNEISS_ENDPOINT) {
15
14
  errorMsgs.push("GNEISS_ENDPOINT is not set in environment variables");
@@ -54,12 +53,12 @@ var AuthGneissCore = class {
54
53
  async refreshToken(refreshToken) {
55
54
  try {
56
55
  const url = `${this.gneissEnpoint}/auth/refresh`;
57
- const response = await axios.post(url, {
56
+ const response = await axios.post(url, {}, {
58
57
  headers: {
59
58
  "Authorization": `Bearer ${refreshToken}`
60
59
  }
61
60
  });
62
- return response.data.accessToken;
61
+ return response.data.access_token;
63
62
  } catch (error) {
64
63
  return null;
65
64
  }
@@ -114,6 +113,17 @@ var AuthGneissCore = class {
114
113
  getLoginUrl() {
115
114
  return this.loginUrl;
116
115
  }
116
+ /**
117
+ * deleteUser deletes the user
118
+ * */
119
+ async deleteUserData(accessToken) {
120
+ const response = await axios.post(`${this.gneissEnpoint}/resource/delete_user`, {}, {
121
+ headers: {
122
+ "Authorization": `Bearer ${accessToken}`
123
+ }
124
+ });
125
+ return response.data;
126
+ }
117
127
  };
118
128
  var AuthGneissCore_default = AuthGneissCore;
119
129
 
@@ -127,7 +137,7 @@ function setAccessToken(res, accessToken) {
127
137
  res.cookie("accessToken", accessToken, {
128
138
  httpOnly: true,
129
139
  secure: process.env.NODE_ENV === "production",
130
- sameSite: "strict",
140
+ sameSite: "lax",
131
141
  maxAge: decodedToken.exp * 1e3 - Date.now()
132
142
  });
133
143
  }
@@ -139,7 +149,7 @@ function setRefreshToken(res, refreshToken) {
139
149
  res.cookie("refreshToken", refreshToken, {
140
150
  httpOnly: true,
141
151
  secure: process.env.NODE_ENV === "production",
142
- sameSite: "strict",
152
+ sameSite: "lax",
143
153
  maxAge: decodedToken.exp * 1e3 - Date.now()
144
154
  });
145
155
  }
@@ -180,6 +190,7 @@ var ExpressAuthGneissClient = class extends AuthGneissCore_default {
180
190
  this.login = this.login.bind(this);
181
191
  this.logout = this.logout.bind(this);
182
192
  this.getUser = this.getUser.bind(this);
193
+ this.deleteUser = this.deleteUser.bind(this);
183
194
  }
184
195
  /**
185
196
  * requireAuth is a middleware function that checks if the access token is valid.
@@ -198,6 +209,7 @@ var ExpressAuthGneissClient = class extends AuthGneissCore_default {
198
209
  const newAccessToken = await this.refreshToken(cookies?.refreshToken);
199
210
  if (newAccessToken) {
200
211
  setAccessToken(res, newAccessToken);
212
+ res.redirect(req.originalUrl);
201
213
  } else {
202
214
  const returnToUrl = req.originalUrl;
203
215
  res.redirect(`${this.loginUrl}?redirect_url=${this.config.baseUrl}${this.config.redirectUrl}&return_to_url=${returnToUrl}`);
@@ -287,24 +299,34 @@ var ExpressAuthGneissClient = class extends AuthGneissCore_default {
287
299
  if (!this.logoutUrl) {
288
300
  throw new Error("Logout URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.");
289
301
  }
290
- if (!this.invalidateUrl) {
291
- throw new Error("Invalidate URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.");
292
- }
293
302
  if (cookies?.accessToken) {
294
- axios2.post(this.invalidateUrl, {}, {
295
- // Invalidate the access token
303
+ axios2.post(this.logoutUrl, {}, {
304
+ // Logout
296
305
  headers: {
297
306
  "Authorization": `Bearer ${cookies?.accessToken}`
298
307
  }
299
308
  });
300
309
  }
301
310
  clearCookies(res);
302
- res.redirect(this.logoutUrl + `?redirect_url=${this.config.baseUrl}`);
311
+ res.redirect("/");
303
312
  } catch (error) {
304
313
  console.error("Error in logout middleware:", error);
305
314
  res.status(500).send("Internal server error");
306
315
  }
307
316
  }
317
+ /**
318
+ * Utility route handler for deleting a user
319
+ * This ensures that the user is fully logged out before
320
+ * deleting the user's data
321
+ *
322
+ * @param req - The request object.
323
+ * @param res - The response object.
324
+ */
325
+ deleteUser(req, res) {
326
+ const cookies = parseCookies(req);
327
+ this.logout(req, res);
328
+ this.deleteUserData(cookies?.accessToken);
329
+ }
308
330
  };
309
331
  var ExpressAuthGneissClient_default = ExpressAuthGneissClient;
310
332
  export {
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "version": 3,
3
3
  "sources": ["../../src/core/AuthGneissCore.ts", "../../src/utils/storage/cookieHandling.ts", "../../src/frameworks/express/middleware/ExpressAuthGneissClient.ts"],
4
- "sourcesContent": ["import { AuthGneissCoreConfig } from \"@core/types\";\r\nimport axios, { AxiosResponse } from \"axios\";\r\nimport { Tokens } from \"@core/types\";\r\nimport { JwtPayload } from \"jsonwebtoken\";\r\nimport dotenv from \"dotenv\";\r\nimport { AxiosError } from \"axios\";\r\n\r\n//load environment variables\r\ndotenv.config();\r\n\r\n/**\r\n * AuthGneissCore provides core functionality for OAuth2 authentication flow with Gneiss authentication service.\r\n * It handles token exchange, token refresh, user data fetching, and token validation.\r\n * \r\n * This class serves as a base class that can be extended by framework-specific implementations\r\n * to provide authentication middleware and handlers.\r\n */\r\nclass AuthGneissCore {\r\n protected config: AuthGneissCoreConfig; // Configuration object\r\n protected gneissEnpoint : string | undefined\r\n protected loginUrl : string | undefined\r\n protected logoutUrl : string | undefined\r\n protected invalidateUrl : string | undefined\r\n\r\n constructor(\r\n config: AuthGneissCoreConfig\r\n ) {\r\n this.config = config;\r\n this.gneissEnpoint = process.env.GNEISS_ENDPOINT // Gneiss endpoint\r\n this.loginUrl = this.gneissEnpoint ? `${this.gneissEnpoint}/auth/login` : undefined; // Login URL\r\n this.logoutUrl = this.gneissEnpoint ? `${this.gneissEnpoint}/auth/logout` : undefined; // Logout URL\r\n this.invalidateUrl = this.gneissEnpoint ? `${this.gneissEnpoint}/auth/invalidate_token` : undefined; // Invalidate URL\r\n\r\n //check if environment variables are set\r\n let errorMsgs = [];\r\n if (!process.env.GNEISS_ENDPOINT) {\r\n errorMsgs.push(\"GNEISS_ENDPOINT is not set in environment variables\");\r\n }\r\n if (!process.env.NODE_ENV) {\r\n errorMsgs.push(\"NODE_ENV is not set in environment variables\");\r\n }\r\n if (errorMsgs.length > 0) {\r\n throw new Error(errorMsgs.join(\"\\n\"));\r\n }\r\n }\r\n\r\n /**\r\n * getTokens is a method that exchanges an authentication code for access and refresh tokens.\r\n * The client id and secret are passed as basic auth headers to authenticate the client itself.\r\n * @param authCode - The authentication code received from the Gneiss authentication service.\r\n * @returns A promise that resolves to an object containing the access and refresh tokens.\r\n */\r\n async getTokens(authCode : string) : Promise<Tokens> {\r\n try {\r\n const url : string = `${this.gneissEnpoint}/auth/access_token?auth_code=${authCode}`;\r\n //Encode in base64 before transport\r\n const encodedClientId = btoa(this.config.clientId);\r\n const encodedClientSecret = btoa(this.config.clientSecret);\r\n const response : AxiosResponse = await axios.post(url, {}, {\r\n headers: {\r\n \"Authorization\": `Basic ${encodedClientId}:${encodedClientSecret}`\r\n }\r\n });\r\n return {\r\n accessToken: response.data.access_token,\r\n refreshToken: response.data.refresh_token,\r\n tokenType: response.data.token_type\r\n } as Tokens;\r\n } catch (error) {\r\n // console.error(\"Error in getTokens:\", error);\r\n throw error;\r\n }\r\n }\r\n \r\n /**\r\n * refreshToken is a method that refreshes the access token using the refresh token.\r\n * @param refreshToken - The refresh token to be used for token refresh.\r\n * @returns A promise that resolves to the refreshed access token.\r\n */\r\n async refreshToken(refreshToken: string): Promise<string | null> {\r\n try {\r\n const url : string = `${this.gneissEnpoint}/auth/refresh`;\r\n const response : AxiosResponse = await axios.post(url, {\r\n headers: {\r\n \"Authorization\": `Bearer ${refreshToken}`\r\n }\r\n });\r\n return response.data.accessToken as string;\r\n } catch (error) {\r\n // console.error(\"Error in refreshToken:\", error);\r\n return null;\r\n }\r\n }\r\n \r\n /**\r\n * getUserData is a method that fetches user data using the access token.\r\n * @param accessToken - The access token to be used for user data fetching.\r\n * @returns A promise that resolves to the user data.\r\n */\r\n async getUserData(accessToken: string) {\r\n const url : string = `${this.gneissEnpoint}/resource/user_data`;\r\n const response : AxiosResponse = await axios.get(url, {\r\n headers: {\r\n \"Authorization\": `Bearer ${accessToken}`\r\n }\r\n });\r\n if (response.status === 200) {\r\n return response.data;\r\n }\r\n throw new Error(\"Failed to fetch user data\");\r\n }\r\n \r\n /**\r\n * validateToken is a method that validates the access token.\r\n * @param token - The access token to be validated.\r\n * @returns A promise that resolves to a boolean indicating the validity of the token.\r\n */\r\n async validateToken(token: string): Promise<boolean> {\r\n try {\r\n console.log(\"DEBUG: token\", token);\r\n // Token validation logic\r\n if (!token) {\r\n return false;\r\n }\r\n const url : string = `${this.gneissEnpoint}/auth/validate_token`;\r\n const response : AxiosResponse = await axios.get(url, {\r\n headers: {\r\n \"Authorization\": `Bearer ${token}`\r\n }\r\n });\r\n return response.status === 200;\r\n } catch (error) {\r\n // console.error(\"Error in validateToken:\", error);\r\n if (error instanceof AxiosError && error.response?.status === 401) {\r\n return false;\r\n } else {\r\n throw error;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * getLoginUrl is a method that returns the login URL.\r\n * @returns The login URL.\r\n */\r\n public getLoginUrl() : string | undefined {\r\n return this.loginUrl;\r\n }\r\n}\r\n\r\nexport default AuthGneissCore;\r\n", "import { Response } from \"express\";\r\nimport { JwtPayload, decode } from \"jsonwebtoken\";\r\nimport { Request } from \"express\";\r\n\r\n/**\r\n * Set the access token in the response cookies.\r\n * @param res - The response object.\r\n * @param accessToken - The access token to set.\r\n */\r\nfunction setAccessToken(res: Response, accessToken: string) {\r\n\r\n const decodedToken = decode(accessToken) as JwtPayload;\r\n \r\n // decoded.exp is in seconds since epoch\r\n // Date.now() returns milliseconds since epoch\r\n // maxAge needs milliseconds remaining\r\n if (!decodedToken.exp) {\r\n throw new Error(\"Access token does not contain an expiration time\");\r\n }\r\n \r\n res.cookie('accessToken', accessToken, {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'strict',\r\n maxAge: (decodedToken.exp * 1000) - Date.now()\r\n });\r\n}\r\n\r\n/**\r\n * Set the refresh token in the response cookies.\r\n * @param res - The response object.\r\n * @param refreshToken - The refresh token to set.\r\n */\r\nfunction setRefreshToken(res: Response, refreshToken: string) {\r\n\r\n const decodedToken = decode(refreshToken) as JwtPayload;\r\n\r\n if (!decodedToken.exp) {\r\n throw new Error(\"Refresh token does not contain an expiration time\");\r\n }\r\n\r\n res.cookie('refreshToken', refreshToken, {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'strict',\r\n maxAge: (decodedToken.exp * 1000) - Date.now()\r\n });\r\n}\r\n\r\nfunction parseCookies(req: Request) : { [key: string]: string } {\r\n const cookies = req.headers.cookie;\r\n if (!cookies) {\r\n return {};\r\n }\r\n return cookies.split(';').reduce((acc: { [key: string]: string }, cookie) => {\r\n const [key, value] = cookie.split('=').map(s => s.trim());\r\n acc[key] = value;\r\n return acc;\r\n }, {});\r\n}\r\n\r\nfunction clearCookies(res: Response) {\r\n res.clearCookie(\"accessToken\", {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'strict',\r\n path: '/'\r\n });\r\n res.clearCookie(\"refreshToken\", {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'strict',\r\n path: '/'\r\n });\r\n}\r\n\r\nexport { setAccessToken, setRefreshToken, parseCookies, clearCookies };\r\n", "import { AuthGneissCore, AuthGneissCoreConfig } from \"@core\";\r\nimport { Request, Response, NextFunction } from \"express\";\r\nimport { RequestWithTokens, Tokens } from \"@core/types\";\r\nimport { setAccessToken, setRefreshToken, parseCookies } from \"@utils\";\r\nimport { JwtPayload } from \"jsonwebtoken\";\r\nimport { AxiosError } from \"axios\";\r\nimport axios from \"axios\";\r\nimport { clearCookies } from \"@/utils/storage/cookieHandling\";\r\n\r\n/**\r\n * ExpressAuthGneissClient extends AuthGneissCore to provide Express-specific authentication middleware\r\n * and functionality for handling OAuth2 authentication flow with Gneiss authentication service.\r\n * \r\n * @extends AuthGneissCore\r\n * @example\r\n * const authClient = new ExpressAuthGneissClient({\r\n * clientId: 'your-client-id',\r\n * clientSecret: 'your-client-secret',\r\n * redirectUrl: 'your-redirect-url'\r\n * });\r\n */\r\nclass ExpressAuthGneissClient extends AuthGneissCore {\r\n\r\n constructor(\r\n config: AuthGneissCoreConfig\r\n ) {\r\n super(config);\r\n \r\n // Bind the methods in constructor\r\n this.requireAuth = this.requireAuth.bind(this);\r\n this.handleCallBack = this.handleCallBack.bind(this);\r\n this.login = this.login.bind(this);\r\n this.logout = this.logout.bind(this);\r\n this.getUser = this.getUser.bind(this);\r\n }\r\n\r\n /**\r\n * requireAuth is a middleware function that checks if the access token is valid.\r\n * If the access token is not valid, it attempts to refresh the token using the refresh token.\r\n * If the refresh token is not valid, it redirects the user to the login page.\r\n * @param req - The request object.\r\n * @param res - The response object.\r\n * @param next - The next middleware function.\r\n */\r\n public async requireAuth(req: Request, res: Response, next: NextFunction): Promise<void> {\r\n const cookies = parseCookies(req);\r\n //Check for the existence of the access token\r\n console.log(\"DEBUG: cookies\", cookies);\r\n try {\r\n const isAccessTokenValid : boolean = await this.validateToken(cookies?.accessToken);\r\n if (!isAccessTokenValid) { //if the access token is not valid\r\n //try to refresh the token\r\n const newAccessToken : string | null = await this.refreshToken(cookies?.refreshToken);\r\n if (newAccessToken) { //\r\n setAccessToken(res, newAccessToken);\r\n }\r\n else {\r\n // no access token or valid refresh token, redirect to login\r\n const returnToUrl : string | undefined = req.originalUrl as string;\r\n res.redirect(`${this.loginUrl}?redirect_url=${this.config.baseUrl}${this.config.redirectUrl}&return_to_url=${returnToUrl}`);\r\n }\r\n }\r\n else {\r\n // access token is valid, continue to the next middleware or route handler\r\n next();\r\n }\r\n } catch (error) {\r\n // console.error('Error in requireAuth middleware:', error);\r\n if (error instanceof AxiosError) {\r\n res.status((error as AxiosError).response?.status || 500).send((error as AxiosError).response?.data || 'Internal server error');\r\n } else {\r\n res.status(500).send('Internal server error');\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * getUserData is a middleware function that fetches user data using the access token.\r\n * @param req - The request object.\r\n * @param res - The response object.\r\n * @param next - The next middleware function.\r\n */\r\n public async getUser(req: Request, res: Response): Promise<void> {\r\n const cookies = parseCookies(req);\r\n const accessToken = cookies?.accessToken;\r\n if (!accessToken) {\r\n throw new Error(\"No access token found in request cookies\");\r\n }\r\n const userData = await this.getUserData(accessToken);\r\n res.status(200).send(userData);\r\n }\r\n\r\n /**\r\n * handleCallBack is a middleware function that handles the callback from the authentication service.\r\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.\r\n * @param req - The request object.\r\n * @param res - The response object.\r\n * @param next - The next middleware function.\r\n */\r\n public async handleCallBack(\r\n req: Request,\r\n res: Response,\r\n next: NextFunction\r\n ): Promise<void> {\r\n try {\r\n const authCode: string | undefined = req.query.auth_code as string\r\n const returnToUrl : string | undefined = req.query.return_to_url as string;\r\n if (!authCode) {\r\n throw new Error(\"No auth code found in request url parameters\");\r\n }\r\n\r\n const tokens: Tokens = await this.getTokens(authCode);\r\n \r\n // Set the access and refresh tokens in the response cookies\r\n setAccessToken(res, tokens.accessToken);\r\n setRefreshToken(res, tokens.refreshToken);\r\n\r\n if (returnToUrl) {\r\n // Go to the original request url\r\n res.redirect(returnToUrl);\r\n }\r\n else {\r\n // Go to the root url\r\n res.redirect(\"/\")\r\n }\r\n } catch (error) {\r\n // console.error('Error in handleCallBack middleware:', error);\r\n if (error instanceof AxiosError) {\r\n res.status((error as AxiosError).response?.status || 500).send((error as AxiosError).response?.data || 'Internal server error');\r\n console.error(\"DEBUG: error\", error);\r\n } else {\r\n res.status(500).send('Internal server error');\r\n console.error(\"DEBUG: error\", error);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * login is a function that redirects the user to the Gneiss authentication service for authentication.\r\n * @param req - The request object.\r\n * @param res - The response object.\r\n */\r\n public login(req: Request, res: Response): void {\r\n try {\r\n if (!this.loginUrl) {\r\n throw new Error('Login URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.');\r\n }\r\n res.redirect(this.loginUrl + `?redirect_url=${this.config.baseUrl}${this.config.redirectUrl}`);\r\n } catch (error) {\r\n console.error('Error in login middleware:', error);\r\n res.status(500).send('Internal server error');\r\n }\r\n }\r\n\r\n /**\r\n * logout is a function that redirects the user to the Gneiss logout service.\r\n * @param req - The request object.\r\n * @param res - The response object.\r\n */\r\n public logout(req: Request, res: Response): void {\r\n const cookies = parseCookies(req);\r\n try {\r\n if (!this.logoutUrl) {\r\n throw new Error('Logout URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.');\r\n }\r\n if (!this.invalidateUrl) {\r\n throw new Error('Invalidate URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.');\r\n }\r\n if (cookies?.accessToken) { // Only invalidate the access token if it exists\r\n axios.post(this.invalidateUrl, {}, { // Invalidate the access token\r\n headers: {\r\n \"Authorization\": `Bearer ${cookies?.accessToken}`\r\n }\r\n });\r\n }\r\n clearCookies(res); // clear the access and refresh cookies\r\n res.redirect(this.logoutUrl + `?redirect_url=${this.config.baseUrl}`); // logout from Gneiss by visiting SSO logout page\r\n } catch (error) {\r\n console.error('Error in logout middleware:', error);\r\n res.status(500).send('Internal server error');\r\n }\r\n }\r\n}\r\n\r\nexport default ExpressAuthGneissClient;\r\n"],
5
- "mappings": "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",
4
+ "sourcesContent": ["import { AuthGneissCoreConfig } from \"@core/types\";\r\nimport axios, { AxiosResponse } from \"axios\";\r\nimport { Tokens } from \"@core/types\";\r\nimport dotenv from \"dotenv\";\r\nimport { AxiosError } from \"axios\";\r\n\r\n//load environment variables\r\ndotenv.config();\r\n\r\n/**\r\n * AuthGneissCore provides core functionality for OAuth2 authentication flow with Gneiss authentication service.\r\n * It handles token exchange, token refresh, user data fetching, and token validation.\r\n * \r\n * This class serves as a base class that can be extended by framework-specific implementations\r\n * to provide authentication middleware and handlers.\r\n */\r\nclass AuthGneissCore {\r\n protected config: AuthGneissCoreConfig; // Configuration object\r\n protected gneissEnpoint : string | undefined\r\n protected loginUrl : string | undefined\r\n protected logoutUrl : string | undefined\r\n\r\n constructor(\r\n config: AuthGneissCoreConfig\r\n ) {\r\n this.config = config;\r\n this.gneissEnpoint = process.env.GNEISS_ENDPOINT // Gneiss endpoint\r\n this.loginUrl = this.gneissEnpoint ? `${this.gneissEnpoint}/auth/login` : undefined; // Login URL\r\n this.logoutUrl = this.gneissEnpoint ? `${this.gneissEnpoint}/auth/logout` : undefined; // Logout URL\r\n\r\n //check if environment variables are set\r\n let errorMsgs = [];\r\n if (!process.env.GNEISS_ENDPOINT) {\r\n errorMsgs.push(\"GNEISS_ENDPOINT is not set in environment variables\");\r\n }\r\n if (!process.env.NODE_ENV) {\r\n errorMsgs.push(\"NODE_ENV is not set in environment variables\");\r\n }\r\n if (errorMsgs.length > 0) {\r\n throw new Error(errorMsgs.join(\"\\n\"));\r\n }\r\n }\r\n\r\n /**\r\n * getTokens is a method that exchanges an authentication code for access and refresh tokens.\r\n * The client id and secret are passed as basic auth headers to authenticate the client itself.\r\n * @param authCode - The authentication code received from the Gneiss authentication service.\r\n * @returns A promise that resolves to an object containing the access and refresh tokens.\r\n */\r\n protected async getTokens(authCode : string) : Promise<Tokens> {\r\n try {\r\n const url : string = `${this.gneissEnpoint}/auth/access_token?auth_code=${authCode}`;\r\n //Encode in base64 before transport\r\n const encodedClientId = btoa(this.config.clientId);\r\n const encodedClientSecret = btoa(this.config.clientSecret);\r\n const response : AxiosResponse = await axios.post(url, {}, {\r\n headers: {\r\n \"Authorization\": `Basic ${encodedClientId}:${encodedClientSecret}`\r\n }\r\n });\r\n return {\r\n accessToken: response.data.access_token,\r\n refreshToken: response.data.refresh_token,\r\n tokenType: response.data.token_type\r\n } as Tokens;\r\n } catch (error) {\r\n // console.error(\"Error in getTokens:\", error);\r\n throw error;\r\n }\r\n }\r\n \r\n /**\r\n * refreshToken is a method that refreshes the access token using the refresh token.\r\n * @param refreshToken - The refresh token to be used for token refresh.\r\n * @returns A promise that resolves to the refreshed access token.\r\n */\r\n protected async refreshToken(refreshToken: string): Promise<string | null> {\r\n try {\r\n const url : string = `${this.gneissEnpoint}/auth/refresh`;\r\n const response : AxiosResponse = await axios.post(url, {}, {\r\n headers: {\r\n \"Authorization\": `Bearer ${refreshToken}`\r\n }\r\n });\r\n return response.data.access_token as string;\r\n } catch (error) {\r\n // console.error(\"Error in refreshToken:\", error);\r\n return null;\r\n }\r\n }\r\n \r\n /**\r\n * getUserData is a method that fetches user data using the access token.\r\n * @param accessToken - The access token to be used for user data fetching.\r\n * @returns A promise that resolves to the user data.\r\n */\r\n protected async getUserData(accessToken: string) {\r\n const url : string = `${this.gneissEnpoint}/resource/user_data`;\r\n const response : AxiosResponse = await axios.get(url, {\r\n headers: {\r\n \"Authorization\": `Bearer ${accessToken}`\r\n }\r\n });\r\n if (response.status === 200) {\r\n return response.data;\r\n }\r\n throw new Error(\"Failed to fetch user data\");\r\n }\r\n \r\n /**\r\n * validateToken is a method that validates the access token.\r\n * @param token - The access token to be validated.\r\n * @returns A promise that resolves to a boolean indicating the validity of the token.\r\n */\r\n protected async validateToken(token: string): Promise<boolean> {\r\n try {\r\n console.log(\"DEBUG: token\", token);\r\n // Token validation logic\r\n if (!token) {\r\n return false;\r\n }\r\n const url : string = `${this.gneissEnpoint}/auth/validate_token`;\r\n const response : AxiosResponse = await axios.get(url, {\r\n headers: {\r\n \"Authorization\": `Bearer ${token}`\r\n }\r\n });\r\n return response.status === 200;\r\n } catch (error) {\r\n // console.error(\"Error in validateToken:\", error);\r\n if (error instanceof AxiosError && error.response?.status === 401) {\r\n return false;\r\n } else {\r\n throw error;\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * getLoginUrl is a method that returns the login URL.\r\n * @returns The login URL.\r\n */\r\n public getLoginUrl() : string | undefined {\r\n return this.loginUrl;\r\n }\r\n\r\n /**\r\n * deleteUser deletes the user\r\n * */\r\n protected async deleteUserData(accessToken : string) : Promise<object> {\r\n const response : AxiosResponse = await axios.post(`${this.gneissEnpoint}/resource/delete_user`, {}, {\r\n headers: {\r\n \"Authorization\": `Bearer ${accessToken}`\r\n } \r\n });\r\n return response.data;\r\n }\r\n}\r\n\r\nexport default AuthGneissCore;\r\n", "import { Response } from \"express\";\r\nimport { JwtPayload, decode } from \"jsonwebtoken\";\r\nimport { Request } from \"express\";\r\n\r\n/**\r\n * Set the access token in the response cookies.\r\n * @param res - The response object.\r\n * @param accessToken - The access token to set.\r\n */\r\nfunction setAccessToken(res: Response, accessToken: string) {\r\n\r\n const decodedToken = decode(accessToken) as JwtPayload;\r\n \r\n // decoded.exp is in seconds since epoch\r\n // Date.now() returns milliseconds since epoch\r\n // maxAge needs milliseconds remaining\r\n if (!decodedToken.exp) {\r\n throw new Error(\"Access token does not contain an expiration time\");\r\n }\r\n \r\n res.cookie('accessToken', accessToken, {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'lax',\r\n maxAge: (decodedToken.exp * 1000) - Date.now()\r\n });\r\n}\r\n\r\n/**\r\n * Set the refresh token in the response cookies.\r\n * @param res - The response object.\r\n * @param refreshToken - The refresh token to set.\r\n */\r\nfunction setRefreshToken(res: Response, refreshToken: string) {\r\n\r\n const decodedToken = decode(refreshToken) as JwtPayload;\r\n\r\n if (!decodedToken.exp) {\r\n throw new Error(\"Refresh token does not contain an expiration time\");\r\n }\r\n\r\n res.cookie('refreshToken', refreshToken, {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'lax',\r\n maxAge: (decodedToken.exp * 1000) - Date.now()\r\n });\r\n}\r\n\r\nfunction parseCookies(req: Request) : { [key: string]: string } {\r\n const cookies = req.headers.cookie;\r\n if (!cookies) {\r\n return {};\r\n }\r\n return cookies.split(';').reduce((acc: { [key: string]: string }, cookie) => {\r\n const [key, value] = cookie.split('=').map(s => s.trim());\r\n acc[key] = value;\r\n return acc;\r\n }, {});\r\n}\r\n\r\nfunction clearCookies(res: Response) {\r\n res.clearCookie(\"accessToken\", {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'strict',\r\n path: '/'\r\n });\r\n res.clearCookie(\"refreshToken\", {\r\n httpOnly: true,\r\n secure: process.env.NODE_ENV === 'production',\r\n sameSite: 'strict',\r\n path: '/'\r\n });\r\n}\r\n\r\nexport { setAccessToken, setRefreshToken, parseCookies, clearCookies };\r\n", "import { AuthGneissCore, AuthGneissCoreConfig } from \"@core\";\r\nimport { Request, Response, NextFunction } from \"express\";\r\nimport { RequestWithTokens, Tokens } from \"@core/types\";\r\nimport { setAccessToken, setRefreshToken, parseCookies } from \"@utils\";\r\nimport { JwtPayload } from \"jsonwebtoken\";\r\nimport { AxiosError } from \"axios\";\r\nimport axios from \"axios\";\r\nimport { clearCookies } from \"@/utils/storage/cookieHandling\";\r\n\r\n/**\r\n * ExpressAuthGneissClient extends AuthGneissCore to provide Express-specific authentication middleware\r\n * and functionality for handling OAuth2 authentication flow with Gneiss authentication service.\r\n * \r\n * @extends AuthGneissCore\r\n * @example\r\n * const authClient = new ExpressAuthGneissClient({\r\n * clientId: 'your-client-id',\r\n * clientSecret: 'your-client-secret',\r\n * redirectUrl: 'your-redirect-url'\r\n * });\r\n */\r\nclass ExpressAuthGneissClient extends AuthGneissCore {\r\n\r\n constructor(\r\n config: AuthGneissCoreConfig\r\n ) {\r\n super(config);\r\n \r\n // Bind the methods in constructor\r\n this.requireAuth = this.requireAuth.bind(this);\r\n this.handleCallBack = this.handleCallBack.bind(this);\r\n this.login = this.login.bind(this);\r\n this.logout = this.logout.bind(this);\r\n this.getUser = this.getUser.bind(this);\r\n this.deleteUser = this.deleteUser.bind(this)\r\n }\r\n\r\n /**\r\n * requireAuth is a middleware function that checks if the access token is valid.\r\n * If the access token is not valid, it attempts to refresh the token using the refresh token.\r\n * If the refresh token is not valid, it redirects the user to the login page.\r\n * @param req - The request object.\r\n * @param res - The response object.\r\n * @param next - The next middleware function.\r\n */\r\n public async requireAuth(req: Request, res: Response, next: NextFunction): Promise<void> {\r\n const cookies = parseCookies(req);\r\n //Check for the existence of the access token\r\n console.log(\"DEBUG: cookies\", cookies);\r\n try {\r\n const isAccessTokenValid : boolean = await this.validateToken(cookies?.accessToken);\r\n if (!isAccessTokenValid) { //if the access token is not valid\r\n //try to refresh the token\r\n const newAccessToken : string | null = await this.refreshToken(cookies?.refreshToken);\r\n if (newAccessToken) { // set access token and then redirect to the original requested url to 'redo' the request with new access token\r\n setAccessToken(res, newAccessToken);\r\n res.redirect(req.originalUrl)\r\n }\r\n else {\r\n // no access token or valid refresh token, redirect to login\r\n const returnToUrl : string | undefined = req.originalUrl as string;\r\n res.redirect(`${this.loginUrl}?redirect_url=${this.config.baseUrl}${this.config.redirectUrl}&return_to_url=${returnToUrl}`);\r\n }\r\n }\r\n else {\r\n // access token is valid, continue to the next middleware or route handler\r\n next();\r\n }\r\n } catch (error) {\r\n // console.error('Error in requireAuth middleware:', error);\r\n if (error instanceof AxiosError) {\r\n res.status((error as AxiosError).response?.status || 500).send((error as AxiosError).response?.data || 'Internal server error');\r\n } else {\r\n res.status(500).send('Internal server error');\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * getUserData is a middleware function that fetches user data using the access token.\r\n * @param req - The request object.\r\n * @param res - The response object.\r\n * @param next - The next middleware function.\r\n */\r\n public async getUser(req: Request, res: Response): Promise<void> {\r\n const cookies = parseCookies(req);\r\n const accessToken = cookies?.accessToken;\r\n if (!accessToken) {\r\n throw new Error(\"No access token found in request cookies\");\r\n }\r\n const userData = await this.getUserData(accessToken);\r\n res.status(200).send(userData);\r\n }\r\n\r\n /**\r\n * handleCallBack is a middleware function that handles the callback from the authentication service.\r\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.\r\n * @param req - The request object.\r\n * @param res - The response object.\r\n * @param next - The next middleware function.\r\n */\r\n public async handleCallBack(\r\n req: Request,\r\n res: Response,\r\n next: NextFunction\r\n ): Promise<void> {\r\n try {\r\n const authCode: string | undefined = req.query.auth_code as string\r\n const returnToUrl : string | undefined = req.query.return_to_url as string;\r\n if (!authCode) {\r\n throw new Error(\"No auth code found in request url parameters\");\r\n }\r\n\r\n const tokens: Tokens = await this.getTokens(authCode);\r\n \r\n // Set the access and refresh tokens in the response cookies\r\n setAccessToken(res, tokens.accessToken);\r\n setRefreshToken(res, tokens.refreshToken);\r\n\r\n if (returnToUrl) {\r\n // Go to the original request url\r\n res.redirect(returnToUrl);\r\n }\r\n else {\r\n // Go to the root url\r\n res.redirect(\"/\")\r\n }\r\n } catch (error) {\r\n // console.error('Error in handleCallBack middleware:', error);\r\n if (error instanceof AxiosError) {\r\n res.status((error as AxiosError).response?.status || 500).send((error as AxiosError).response?.data || 'Internal server error');\r\n console.error(\"DEBUG: error\", error);\r\n } else {\r\n res.status(500).send('Internal server error');\r\n console.error(\"DEBUG: error\", error);\r\n }\r\n }\r\n }\r\n\r\n /**\r\n * login is a function that redirects the user to the Gneiss authentication service for authentication.\r\n * @param req - The request object.\r\n * @param res - The response object.\r\n */\r\n public login(req: Request, res: Response): void {\r\n try {\r\n if (!this.loginUrl) {\r\n throw new Error('Login URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.');\r\n }\r\n res.redirect(this.loginUrl + `?redirect_url=${this.config.baseUrl}${this.config.redirectUrl}`);\r\n } catch (error) {\r\n console.error('Error in login middleware:', error);\r\n res.status(500).send('Internal server error');\r\n }\r\n }\r\n\r\n /**\r\n * logout is a function that redirects the user to the Gneiss logout service.\r\n * @param req - The request object.\r\n * @param res - The response object.\r\n */\r\n public logout(req: Request, res: Response): void {\r\n const cookies = parseCookies(req);\r\n try {\r\n if (!this.logoutUrl) {\r\n throw new Error('Logout URL is not configured. Check if GNEISS_ENDPOINT environment variable is set.');\r\n }\r\n if (cookies?.accessToken) { // Only logout if the access token exists\r\n axios.post(this.logoutUrl, {}, { // Logout\r\n headers: {\r\n \"Authorization\": `Bearer ${cookies?.accessToken}`\r\n }\r\n });\r\n }\r\n clearCookies(res); // clear the access and refresh cookies\r\n res.redirect(\"/\") // Redirect back to home after logout\r\n } catch (error) {\r\n console.error('Error in logout middleware:', error);\r\n res.status(500).send('Internal server error');\r\n }\r\n }\r\n\r\n /**\r\n * Utility route handler for deleting a user\r\n * This ensures that the user is fully logged out before \r\n * deleting the user's data\r\n * \r\n * @param req - The request object.\r\n * @param res - The response object.\r\n */\r\n public deleteUser(req: Request, res: Response) {\r\n const cookies = parseCookies(req);\r\n this.logout(req, res)\r\n this.deleteUserData(cookies?.accessToken)\r\n }\r\n}\r\n\r\nexport default ExpressAuthGneissClient;\r\n"],
5
+ "mappings": "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",
6
6
  "names": ["AxiosError", "axios", "AxiosError", "axios"]
7
7
  }
@@ -12,7 +12,6 @@ declare class AuthGneissCore {
12
12
  protected gneissEnpoint: string | undefined;
13
13
  protected loginUrl: string | undefined;
14
14
  protected logoutUrl: string | undefined;
15
- protected invalidateUrl: string | undefined;
16
15
  constructor(config: AuthGneissCoreConfig);
17
16
  /**
18
17
  * getTokens is a method that exchanges an authentication code for access and refresh tokens.
@@ -20,30 +19,34 @@ declare class AuthGneissCore {
20
19
  * @param authCode - The authentication code received from the Gneiss authentication service.
21
20
  * @returns A promise that resolves to an object containing the access and refresh tokens.
22
21
  */
23
- getTokens(authCode: string): Promise<Tokens>;
22
+ protected getTokens(authCode: string): Promise<Tokens>;
24
23
  /**
25
24
  * refreshToken is a method that refreshes the access token using the refresh token.
26
25
  * @param refreshToken - The refresh token to be used for token refresh.
27
26
  * @returns A promise that resolves to the refreshed access token.
28
27
  */
29
- refreshToken(refreshToken: string): Promise<string | null>;
28
+ protected refreshToken(refreshToken: string): Promise<string | null>;
30
29
  /**
31
30
  * getUserData is a method that fetches user data using the access token.
32
31
  * @param accessToken - The access token to be used for user data fetching.
33
32
  * @returns A promise that resolves to the user data.
34
33
  */
35
- getUserData(accessToken: string): Promise<any>;
34
+ protected getUserData(accessToken: string): Promise<any>;
36
35
  /**
37
36
  * validateToken is a method that validates the access token.
38
37
  * @param token - The access token to be validated.
39
38
  * @returns A promise that resolves to a boolean indicating the validity of the token.
40
39
  */
41
- validateToken(token: string): Promise<boolean>;
40
+ protected validateToken(token: string): Promise<boolean>;
42
41
  /**
43
42
  * getLoginUrl is a method that returns the login URL.
44
43
  * @returns The login URL.
45
44
  */
46
45
  getLoginUrl(): string | undefined;
46
+ /**
47
+ * deleteUser deletes the user
48
+ * */
49
+ protected deleteUserData(accessToken: string): Promise<object>;
47
50
  }
48
51
  export default AuthGneissCore;
49
52
  //# sourceMappingURL=AuthGneissCore.d.ts.map
@@ -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;AAQrC;;;;;;GAMG;AACH,cAAM,cAAc;IAChB,SAAS,CAAC,MAAM,EAAE,oBAAoB,CAAC;IACvC,SAAS,CAAC,aAAa,EAAG,MAAM,GAAG,SAAS,CAAA;IAC5C,SAAS,CAAC,QAAQ,EAAG,MAAM,GAAG,SAAS,CAAA;IACvC,SAAS,CAAC,SAAS,EAAG,MAAM,GAAG,SAAS,CAAA;IACxC,SAAS,CAAC,aAAa,EAAG,MAAM,GAAG,SAAS,CAAA;gBAGxC,MAAM,EAAE,oBAAoB;IAqBhC;;;;;OAKG;IACG,SAAS,CAAC,QAAQ,EAAG,MAAM,GAAI,OAAO,CAAC,MAAM,CAAC;IAsBpD;;;;OAIG;IACG,YAAY,CAAC,YAAY,EAAE,MAAM,GAAG,OAAO,CAAC,MAAM,GAAG,IAAI,CAAC;IAehE;;;;OAIG;IACG,WAAW,CAAC,WAAW,EAAE,MAAM;IAarC;;;;OAIG;IACG,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAwBpD;;;OAGG;IACI,WAAW,IAAK,MAAM,GAAG,SAAS;CAG5C;AAED,eAAe,cAAc,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;AAOrC;;;;;;GAMG;AACH,cAAM,cAAc;IAChB,SAAS,CAAC,MAAM,EAAE,oBAAoB,CAAC;IACvC,SAAS,CAAC,aAAa,EAAG,MAAM,GAAG,SAAS,CAAA;IAC5C,SAAS,CAAC,QAAQ,EAAG,MAAM,GAAG,SAAS,CAAA;IACvC,SAAS,CAAC,SAAS,EAAG,MAAM,GAAG,SAAS,CAAA;gBAGpC,MAAM,EAAE,oBAAoB;IAoBhC;;;;;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;IAe1E;;;;OAIG;cACa,WAAW,CAAC,WAAW,EAAE,MAAM;IAa/C;;;;OAIG;cACa,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,OAAO,CAAC,OAAO,CAAC;IAwB9D;;;OAGG;IACI,WAAW,IAAK,MAAM,GAAG,SAAS;IAIzC;;SAEK;cACW,cAAc,CAAC,WAAW,EAAG,MAAM,GAAI,OAAO,CAAC,MAAM,CAAC;CAQzE;AAED,eAAe,cAAc,CAAC"}
@@ -50,6 +50,15 @@ declare class ExpressAuthGneissClient extends AuthGneissCore {
50
50
  * @param res - The response object.
51
51
  */
52
52
  logout(req: Request, res: Response): void;
53
+ /**
54
+ * Utility route handler for deleting a user
55
+ * This ensures that the user is fully logged out before
56
+ * deleting the user's data
57
+ *
58
+ * @param req - The request object.
59
+ * @param res - The response object.
60
+ */
61
+ deleteUser(req: Request, res: Response): void;
53
62
  }
54
63
  export default ExpressAuthGneissClient;
55
64
  //# sourceMappingURL=ExpressAuthGneissClient.d.ts.map
@@ -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;gBAG5C,MAAM,EAAE,oBAAoB;IAYhC;;;;;;;OAOG;IACU,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAgCxF;;;;;OAKG;IACU,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAUhE;;;;;;OAMG;IACU,cAAc,CACvB,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,YAAY,GACnB,OAAO,CAAC,IAAI,CAAC;IAkChB;;;;OAIG;IACI,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI;IAY/C;;;;OAIG;IACI,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI;CAuBnD;AAED,eAAe,uBAAuB,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;gBAG5C,MAAM,EAAE,oBAAoB;IAahC;;;;;;;OAOG;IACU,WAAW,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,EAAE,IAAI,EAAE,YAAY,GAAG,OAAO,CAAC,IAAI,CAAC;IAiCxF;;;;;OAKG;IACU,OAAO,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,OAAO,CAAC,IAAI,CAAC;IAUhE;;;;;;OAMG;IACU,cAAc,CACvB,GAAG,EAAE,OAAO,EACZ,GAAG,EAAE,QAAQ,EACb,IAAI,EAAE,YAAY,GACnB,OAAO,CAAC,IAAI,CAAC;IAkChB;;;;OAIG;IACI,KAAK,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI;IAY/C;;;;OAIG;IACI,MAAM,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ,GAAG,IAAI;IAqBhD;;;;;;;OAOG;IACI,UAAU,CAAC,GAAG,EAAE,OAAO,EAAE,GAAG,EAAE,QAAQ;CAKhD;AAED,eAAe,uBAAuB,CAAC"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gneiss/client-auth",
3
- "version": "1.0.1",
3
+ "version": "1.0.3",
4
4
  "main": "dist/cjs/index.js",
5
5
  "module": "dist/esm/index.js",
6
6
  "types": "dist/types/src/index.d.ts",
@@ -13,7 +13,8 @@
13
13
  }
14
14
  },
15
15
  "scripts": {
16
- "build": "node build.js && tsc --emitDeclarationOnly --outDir dist/types",
16
+ "build": "node build.js && tsc --emitDeclarationOnly --outDir dist/types && npm run install-to-examples",
17
+ "install-to-examples": "npm uninstall @gneiss/client-auth --prefix ./examples && npm install . --prefix ./examples",
17
18
  "build:watch": "node build.js --watch",
18
19
  "test": "jest",
19
20
  "clean": "rd /s /q dist"