Sosthene 59bfa9bd55
All checks were successful
Test - Build & Deploy to Scaleway / build-and-push-image-lecoffre (push) Successful in 1m18s
Test - Build & Deploy to Scaleway / deploy-to-scaleway-lecoffre (push) Successful in 3s
jwt debug
2025-08-03 18:35:09 +02:00

240 lines
7.3 KiB
TypeScript

import jwt_decode from "jwt-decode";
import CookieService from "../CookieService/CookieService";
import UserStore from "@Front/Stores/CustomerStore";
import CustomerStore from "@Front/Stores/CustomerStore";
import { FrontendVariables } from "@Front/Config/VariablesFront";
enum PROVIDER_OPENID {
idNot = "idNot",
}
export interface IUserJwtPayload {
userId: string;
email: string | null;
openId: {
providerName: PROVIDER_OPENID;
userId: string | number;
};
office_Id: string;
role: string;
rules: string[];
exp: number;
}
export interface ICustomerJwtPayload {
customerId: string;
email: string;
exp: number;
}
export default class JwtService {
private static instance: JwtService;
private constructor() {}
public static getInstance() {
return (this.instance ??= new this());
}
public getUserJwtPayload(): IUserJwtPayload | undefined {
const accessToken = CookieService.getInstance().getCookie("leCoffreAccessToken");
if (!accessToken) return;
return jwt_decode(accessToken);
}
public getCustomerJwtPayload(): ICustomerJwtPayload | undefined {
const accessToken = CookieService.getInstance().getCookie("leCoffreAccessToken");
if (!accessToken) return;
return jwt_decode(accessToken);
}
public decodeJwt(): IUserJwtPayload | undefined {
const accessToken = CookieService.getInstance().getCookie("leCoffreAccessToken");
if (!accessToken) return;
return jwt_decode(accessToken);
}
public decodeCustomerJwt(): ICustomerJwtPayload | undefined {
const accessToken = CookieService.getInstance().getCookie("leCoffreAccessToken");
if (!accessToken) return;
return jwt_decode(accessToken);
}
/**
* @description : set a cookie with a name and a value that expire in 7 days
* @throws {Error} If the name or the value is empty
*/
public async refreshToken(refreshToken: string): Promise<boolean> {
const userToken = jwt_decode(refreshToken) as IUserJwtPayload;
const customerToken = jwt_decode(refreshToken) as ICustomerJwtPayload;
if (userToken?.exp && userToken.exp > Math.floor(Date.now() / 1000)) {
const variables = FrontendVariables.getInstance();
if (userToken?.userId) {
try {
const headers = new Headers();
headers.append("Authorization", `Bearer ${refreshToken}`);
const response = await fetch(
`${
variables.BACK_API_PROTOCOL + variables.BACK_API_HOST + variables.BACK_API_ROOT_URL + variables.BACK_API_VERSION
}/idnot/user/auth/refresh-token`,
{ method: "POST", headers: headers },
);
const newAccessToken: { accessToken: string } = await response.json();
if (newAccessToken) {
await UserStore.instance.connect(newAccessToken.accessToken, refreshToken);
return true;
}
} catch (err) {
console.error(err);
return false;
}
} else if (customerToken?.customerId) {
try {
const headers = new Headers();
headers.append("Authorization", `Bearer ${refreshToken}`);
const response = await fetch(
`${
variables.BACK_API_PROTOCOL + variables.BACK_API_HOST + variables.BACK_API_ROOT_URL + variables.BACK_API_VERSION
}/id360/customers/refresh-token`,
{ method: "POST", headers: headers },
);
const newAccessToken: { accessToken: string } = await response.json();
if (newAccessToken) {
await CustomerStore.instance.connect(newAccessToken.accessToken, refreshToken);
return true;
}
} catch (err) {
console.error(err);
return false;
}
}
}
return false;
}
public async forceRefreshToken(refreshToken: string): Promise<boolean> {
const userToken = jwt_decode(refreshToken) as IUserJwtPayload;
const customerToken = jwt_decode(refreshToken) as ICustomerJwtPayload;
const variables = FrontendVariables.getInstance();
if (userToken?.userId) {
try {
const headers = new Headers();
headers.append("Authorization", `Bearer ${refreshToken}`);
const response = await fetch(
`${
variables.BACK_API_PROTOCOL + variables.BACK_API_HOST + variables.BACK_API_ROOT_URL + variables.BACK_API_VERSION
}/idnot/user/auth/refresh-token`,
{ method: "POST", headers: headers },
);
const newAccessToken: { accessToken: string } = await response.json();
if (newAccessToken) {
await UserStore.instance.connect(newAccessToken.accessToken, refreshToken);
return true;
}
} catch (err) {
console.error(err);
return false;
}
} else if (customerToken?.customerId) {
try {
const headers = new Headers();
headers.append("Authorization", `Bearer ${refreshToken}`);
const response = await fetch(
`${
variables.BACK_API_PROTOCOL + variables.BACK_API_HOST + variables.BACK_API_ROOT_URL + variables.BACK_API_VERSION
}/id360/customers/refresh-token`,
{ method: "POST", headers: headers },
);
const newAccessToken: { accessToken: string } = await response.json();
if (newAccessToken) {
await CustomerStore.instance.connect(newAccessToken.accessToken, refreshToken);
return true;
}
} catch (err) {
console.error(err);
return false;
}
}
return false;
}
public hasRule(name: string, action: string) {
const token = this.decodeJwt();
if (!token) return false;
return token?.rules?.some((rule: string) => rule === `${action} ${name}`);
}
/**
* Debug method to log JWT token details including rules
*/
public debugJwtToken() {
const token = this.decodeJwt();
if (!token) {
console.warn("No JWT token found");
return null;
}
console.log("=== JWT Token Debug Info ===");
console.log("User ID:", token.userId);
console.log("Email:", token.email);
console.log("Role:", token.role);
console.log("Office ID:", token.office_Id);
console.log("Rules count:", token.rules?.length || 0);
console.log("Rules:", token.rules);
console.log("Expiration:", new Date(token.exp * 1000).toISOString());
console.log("=============================");
return token;
}
/**
* Check if a specific rule exists in the JWT token
*/
public checkSpecificRule(name: string, action: string) {
const token = this.decodeJwt();
if (!token) {
console.warn("No JWT token found");
return false;
}
const expectedRule = `${action} ${name}`;
const hasRule = token?.rules?.some((rule: string) => rule === expectedRule);
console.log(`=== Rule Check: ${expectedRule} ===`);
console.log("Expected rule:", expectedRule);
console.log("Available rules:", token.rules);
console.log("Rule found:", hasRule);
console.log("=============================");
return hasRule;
}
/**
* Compare JWT rules with expected rules from database
*/
public compareRulesWithDatabase(expectedRules: string[]) {
const token = this.decodeJwt();
if (!token) {
console.warn("No JWT token found");
return { missing: expectedRules, extra: [], matches: [] };
}
const jwtRules = token.rules || [];
const missing = expectedRules.filter(rule => !jwtRules.includes(rule));
const extra = jwtRules.filter(rule => !expectedRules.includes(rule));
const matches = jwtRules.filter(rule => expectedRules.includes(rule));
console.log("=== Rules Comparison ===");
console.log("Expected rules (from DB):", expectedRules);
console.log("JWT rules:", jwtRules);
console.log("Missing rules:", missing);
console.log("Extra rules:", extra);
console.log("Matching rules:", matches);
console.log("=========================");
return { missing, extra, matches };
}
}