keycloak improve flow 2
This commit is contained in:
parent
9462fc6799
commit
88f0e946fd
@ -237,6 +237,17 @@ export const authOptions: NextAuthOptions = {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If refresh failed with invalid_grant (token not active), also clear tokens
|
||||||
|
if (refreshedToken.error === "RefreshAccessTokenError" && !refreshedToken.accessToken) {
|
||||||
|
console.log("Refresh token invalid, clearing session to force re-authentication");
|
||||||
|
return {
|
||||||
|
...refreshedToken,
|
||||||
|
accessToken: undefined,
|
||||||
|
refreshToken: undefined,
|
||||||
|
idToken: undefined,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
return refreshedToken;
|
return refreshedToken;
|
||||||
},
|
},
|
||||||
async session({ session, token }) {
|
async session({ session, token }) {
|
||||||
|
|||||||
@ -48,6 +48,21 @@ export async function GET(request: NextRequest) {
|
|||||||
if (!response.ok) {
|
if (!response.ok) {
|
||||||
const error = await response.json().catch(() => ({}));
|
const error = await response.json().catch(() => ({}));
|
||||||
console.error('Failed to refresh Keycloak session:', error);
|
console.error('Failed to refresh Keycloak session:', error);
|
||||||
|
|
||||||
|
// If token is invalid (user logged out from Keycloak), return specific error
|
||||||
|
if (error.error === 'invalid_grant' ||
|
||||||
|
error.error_description?.includes('Token is not active') ||
|
||||||
|
error.error_description?.includes('Session not active')) {
|
||||||
|
return NextResponse.json(
|
||||||
|
{
|
||||||
|
error: 'SessionInvalidated',
|
||||||
|
message: 'Keycloak session was invalidated. Please sign in again.',
|
||||||
|
details: error
|
||||||
|
},
|
||||||
|
{ status: 401 }
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return NextResponse.json(
|
return NextResponse.json(
|
||||||
{ error: 'Failed to refresh Keycloak session', details: error },
|
{ error: 'Failed to refresh Keycloak session', details: error },
|
||||||
{ status: response.status }
|
{ status: response.status }
|
||||||
|
|||||||
@ -15,11 +15,13 @@ export function ResponsiveIframe({ src, className = '', allow, style }: Responsi
|
|||||||
const { data: session } = useSession();
|
const { data: session } = useSession();
|
||||||
const [isRefreshing, setIsRefreshing] = useState(false);
|
const [isRefreshing, setIsRefreshing] = useState(false);
|
||||||
const [iframeSrc, setIframeSrc] = useState<string>('');
|
const [iframeSrc, setIframeSrc] = useState<string>('');
|
||||||
|
const [hasTriedRefresh, setHasTriedRefresh] = useState(false);
|
||||||
|
|
||||||
// Refresh NextAuth session (which will also refresh Keycloak tokens) before loading iframe
|
// Refresh NextAuth session (which will also refresh Keycloak tokens) before loading iframe
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
if (!session || !src || isRefreshing) {
|
// If no session or no src, or already tried refresh, just set src
|
||||||
if (src && !isRefreshing) {
|
if (!session || !src || hasTriedRefresh) {
|
||||||
|
if (src) {
|
||||||
setIframeSrc(src);
|
setIframeSrc(src);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
@ -27,6 +29,7 @@ export function ResponsiveIframe({ src, className = '', allow, style }: Responsi
|
|||||||
|
|
||||||
const refreshSession = async () => {
|
const refreshSession = async () => {
|
||||||
setIsRefreshing(true);
|
setIsRefreshing(true);
|
||||||
|
setHasTriedRefresh(true);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Call our API to refresh the Keycloak session
|
// Call our API to refresh the Keycloak session
|
||||||
@ -39,19 +42,29 @@ export function ResponsiveIframe({ src, className = '', allow, style }: Responsi
|
|||||||
if (response.ok) {
|
if (response.ok) {
|
||||||
console.log('Session refreshed before loading iframe');
|
console.log('Session refreshed before loading iframe');
|
||||||
} else {
|
} else {
|
||||||
|
const errorData = await response.json().catch(() => ({}));
|
||||||
|
|
||||||
|
// If session was invalidated, redirect to sign-in
|
||||||
|
if (response.status === 401 && errorData.error === 'SessionInvalidated') {
|
||||||
|
console.warn('Keycloak session invalidated, redirecting to sign-in');
|
||||||
|
// Sign out from NextAuth and redirect
|
||||||
|
window.location.href = '/signin';
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
console.warn('Failed to refresh session, iframe may require login');
|
console.warn('Failed to refresh session, iframe may require login');
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error refreshing session:', error);
|
console.error('Error refreshing session:', error);
|
||||||
} finally {
|
} finally {
|
||||||
// Set iframe src after attempting refresh
|
// Always set iframe src after attempting refresh (or on error)
|
||||||
setIframeSrc(src);
|
setIframeSrc(src);
|
||||||
setIsRefreshing(false);
|
setIsRefreshing(false);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
refreshSession();
|
refreshSession();
|
||||||
}, [session, src, isRefreshing]);
|
}, [session, src, hasTriedRefresh]);
|
||||||
|
|
||||||
useEffect(() => {
|
useEffect(() => {
|
||||||
const iframe = iframeRef.current;
|
const iframe = iframeRef.current;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user