mirror of
https://github.com/Tria-plc/emaui.git
synced 2026-08-27 07:22:56 +00:00
feat: migrate authentication storage to use js-cookie for improved token management
This commit is contained in:
@@ -1,3 +1,4 @@
|
||||
import Cookies from 'js-cookie';
|
||||
import { useCallback, useEffect, useRef } from 'react';
|
||||
import { createRoot, type Root } from 'react-dom/client';
|
||||
import { useNavigate } from 'react-router-dom';
|
||||
@@ -138,12 +139,8 @@ export default function UserManagementPage() {
|
||||
style.textContent = UM_OVERRIDES;
|
||||
document.head.appendChild(style);
|
||||
|
||||
const readCookie = (name: string) => {
|
||||
const m = document.cookie.match(new RegExp('(?:^|;\\s*)' + name + '=([^;]*)'));
|
||||
return m ? decodeURIComponent(m[1]) : undefined;
|
||||
};
|
||||
const token = readCookie('ema-backoffice-auth-token') ?? '';
|
||||
const refreshToken = readCookie('ema-backoffice-refresh-token');
|
||||
const token = Cookies.get('ema-backoffice-auth-token') ?? '';
|
||||
const refreshToken = Cookies.get('ema-backoffice-refresh-token');
|
||||
|
||||
const session: UserManagementSessionOptions = {
|
||||
initialSession: token
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import Cookies from 'js-cookie';
|
||||
|
||||
export const SESSION_HEADER_KEYS = {
|
||||
tenantId: 'x-tenant-id',
|
||||
organizationUnitId: 'x-organization-unit-id',
|
||||
@@ -11,17 +13,10 @@ const TOKEN_STORAGE_KEYS = [
|
||||
'auth-token',
|
||||
] as const;
|
||||
|
||||
function getCookie(name: string): string | undefined {
|
||||
const match = document.cookie.match(
|
||||
new RegExp('(?:^|;\\s*)' + name + '=([^;]*)'),
|
||||
);
|
||||
return match ? decodeURIComponent(match[1]) : undefined;
|
||||
}
|
||||
|
||||
export function resolveTokenFromStorage(): string | undefined {
|
||||
// cookie first (backoffice stores tokens there), then localStorage (portal / legacy)
|
||||
for (const key of TOKEN_STORAGE_KEYS) {
|
||||
const cookie = getCookie(key);
|
||||
const cookie = Cookies.get(key);
|
||||
if (cookie) return cookie;
|
||||
const stored = localStorage.getItem(key);
|
||||
if (stored) return stored;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import Cookies from 'js-cookie';
|
||||
import { Navigate, Outlet, useLocation } from 'react-router-dom';
|
||||
import type { ReactNode } from 'react';
|
||||
import { authStorage } from '../utils/auth-storage';
|
||||
@@ -7,14 +8,9 @@ interface ProtectedRouteProps {
|
||||
loginPath?: string;
|
||||
}
|
||||
|
||||
function getTokenFromCookie(): string | undefined {
|
||||
const match = document.cookie.match(/(?:^|;\s*)auth-token=([^;]*)/);
|
||||
return match ? decodeURIComponent(match[1]) : undefined;
|
||||
}
|
||||
|
||||
export function ProtectedRoute({ children, loginPath = '/login' }: ProtectedRouteProps) {
|
||||
const location = useLocation();
|
||||
const token = authStorage.getToken() ?? getTokenFromCookie();
|
||||
const token = authStorage.getToken() ?? Cookies.get('auth-token');
|
||||
|
||||
if (!token) {
|
||||
return <Navigate to={loginPath} state={{ from: location }} replace />;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { createSlice, type PayloadAction } from '@reduxjs/toolkit';
|
||||
import type { AuthState, AuthUser, CurrentProfile, LoginPayload } from '../types/auth.types';
|
||||
import { authStorage } from '../utils/auth-storage';
|
||||
import { authStorage, clearAllCookies } from '../utils/auth-storage';
|
||||
|
||||
const initialState: AuthState = {
|
||||
user: null,
|
||||
@@ -37,6 +37,7 @@ const authSlice = createSlice({
|
||||
state.isAuthenticated = false;
|
||||
state.currentProfile = null;
|
||||
authStorage.clear();
|
||||
clearAllCookies()
|
||||
},
|
||||
hydrateAuth(state) {
|
||||
const token = authStorage.getToken();
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
const MAX_AGE = 60 * 60 * 24 * 7; // ponytail: cookie lifetime knob; JWT expiry + refresh govern real auth
|
||||
import Cookies from 'js-cookie';
|
||||
|
||||
const COOKIE_EXPIRES_DAYS = 7; // ponytail: cookie lifetime knob; JWT expiry + refresh govern real auth
|
||||
|
||||
interface Backend {
|
||||
get(k: string): string | null;
|
||||
@@ -13,27 +15,25 @@ const localBackend: Backend = {
|
||||
};
|
||||
|
||||
const cookieBackend: Backend = {
|
||||
get: (k) => {
|
||||
const m = document.cookie.match(new RegExp('(?:^|;\\s*)' + k + '=([^;]*)'));
|
||||
return m ? decodeURIComponent(m[1]) : null;
|
||||
},
|
||||
get: (k) => Cookies.get(k) ?? null,
|
||||
// ponytail: 4KB/cookie cap — auth-user/current-profile JSON must stay under it
|
||||
set: (k, v) => {
|
||||
document.cookie = `${k}=${encodeURIComponent(v)}; path=/; Secure; SameSite=Strict; Max-Age=${MAX_AGE}`;
|
||||
},
|
||||
remove: (k) => {
|
||||
document.cookie = `${k}=; path=/; Secure; SameSite=Strict; Max-Age=0`;
|
||||
},
|
||||
set: (k, v) =>
|
||||
Cookies.set(k, v, { path: '/', secure: true, sameSite: 'strict', expires: COOKIE_EXPIRES_DAYS }),
|
||||
remove: (k) => Cookies.remove(k, { path: '/' }),
|
||||
};
|
||||
|
||||
import Cookies from "js-cookie";
|
||||
const AUTH_KEY_NAMES = ['auth-token', 'refresh-token', 'auth-user', 'profile-id', 'current-profile'];
|
||||
|
||||
let _prefix = "ema-auth";
|
||||
let _prefix = 'ema-auth';
|
||||
let backend: Backend = localBackend;
|
||||
|
||||
export function configureAuthStorage(prefix: string, useCookies = false) {
|
||||
_prefix = prefix;
|
||||
backend = useCookies ? cookieBackend : localBackend;
|
||||
if (useCookies) {
|
||||
// one-time cleanup: drop pre-migration localStorage leftovers so tokens live in cookies only
|
||||
AUTH_KEY_NAMES.forEach((k) => localStorage.removeItem(`${prefix}-${k}`));
|
||||
}
|
||||
}
|
||||
|
||||
function key(k: string) {
|
||||
@@ -68,16 +68,14 @@ export const authStorage = {
|
||||
[key('auth-token'), key('refresh-token'), key('auth-user'), key('profile-id'), key('current-profile')].forEach((k) =>
|
||||
backend.remove(k),
|
||||
);
|
||||
document.cookie =
|
||||
"auth-token=; path=/; expires=Thu, 01 Jan 1970 00:00:00 UTC; SameSite=Lax";
|
||||
Cookies.remove('auth-token', { path: '/' });
|
||||
},
|
||||
};
|
||||
|
||||
export const clearAllCookies = () => {
|
||||
const cookies = Cookies.get();
|
||||
|
||||
Object.keys(cookies).forEach((name) => {
|
||||
Cookies.remove(name);
|
||||
Cookies.remove(name, { path: "/" });
|
||||
Cookies.remove(name, { path: '/' });
|
||||
});
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user