fix(sso): deduplicate one-time grant exchange

This commit is contained in:
Inamul-hasan-tec
2026-09-01 11:22:02 +05:30
parent cc9807b70d
commit 4401683197
2 changed files with 23 additions and 3 deletions
+2 -1
View File
@@ -31,7 +31,8 @@ axiosInstance.interceptors.response.use(
(response) => response,
(error: { config?: { url?: string }; response?: { status?: number } }) => {
const isLoginEndpoint = error.config?.url?.includes('/auth/login');
if (error.response?.status === 401 && !isLoginEndpoint) {
const isSsoExchangeEndpoint = error.config?.url?.includes('/auth/sso/exchange');
if (error.response?.status === 401 && !isLoginEndpoint && !isSsoExchangeEndpoint) {
localStorage.removeItem('accessToken');
if (window.location.pathname !== '/login') {
window.location.href = '/login';
+21 -2
View File
@@ -6,6 +6,25 @@ import { authService } from '../services/authService';
import { setCredentials } from '../../store/slices/authSlice';
import { AuthLayout } from '../components/AuthLayout';
type SSOExchangeResponse = {
data?: { user: unknown; accessToken: string; refreshToken?: string; permissions?: Record<string, unknown> };
user?: unknown;
accessToken?: string;
refreshToken?: string;
permissions?: Record<string, unknown>;
};
let activeGrant: string | null = null;
let activeExchange: Promise<unknown> | null = null;
function exchangeGrantOnce(grant: string) {
if (activeGrant !== grant || !activeExchange) {
activeGrant = grant;
activeExchange = authService.exchangeSaaSToken(grant);
}
return activeExchange;
}
export const SSOCallback = () => {
const [searchParams] = useSearchParams();
const initialError = searchParams.get('error');
@@ -24,9 +43,9 @@ export const SSOCallback = () => {
window.history.replaceState({}, document.title, callbackPath);
if (searchParams.get('error') || !grant || !/^[a-f0-9]{32}$/i.test(grant)) return;
let cancelled = false;
authService.exchangeSaaSToken(grant).then((response) => {
exchangeGrantOnce(grant).then((response) => {
if (cancelled) return;
const result = response as unknown as { data?: { user: unknown; accessToken: string; refreshToken?: string; permissions?: Record<string, unknown> }; user?: unknown; accessToken?: string; refreshToken?: string; permissions?: Record<string, unknown> };
const result = response as SSOExchangeResponse;
const session = result.data ?? result;
const { user, accessToken, refreshToken, permissions } = session;
if (!accessToken) throw new Error('PIM session token was not returned');