fix(sso): deduplicate one-time grant exchange
This commit is contained in:
@@ -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';
|
||||
|
||||
@@ -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');
|
||||
|
||||
Reference in New Issue
Block a user