auth flow

This commit is contained in:
alma 2025-05-02 16:38:58 +02:00
parent 3be309c0fe
commit d488979109
3 changed files with 117 additions and 17 deletions

View File

@ -83,16 +83,27 @@ export const authOptions: NextAuthOptions = {
callbacks: {
async jwt({ token, account, profile }: any) {
if (account && profile) {
// Just store access token and critical fields
// Store access token
token.accessToken = account.access_token;
// Make sure roles are available
if (profile.role) {
token.refreshToken = account.refresh_token;
// Extract roles correctly from the raw Keycloak profile
if (profile.realm_access && profile.realm_access.roles) {
// Directly extract roles from the Keycloak profile structure
token.role = profile.realm_access.roles.map(
(role: string) => role.replace(/^ROLE_/, '').toLowerCase()
);
} else if (profile.role) {
// Fallback to using the role property if already processed
token.role = profile.role;
token.username = profile.username || '';
token.first_name = profile.first_name || '';
token.last_name = profile.last_name || '';
}
// Store user information
token.username = profile.preferred_username || profile.username || '';
token.first_name = profile.given_name || profile.first_name || '';
token.last_name = profile.family_name || profile.last_name || '';
}
return token;
},
async session({ session, token }: any) {
@ -102,7 +113,7 @@ export const authOptions: NextAuthOptions = {
session.user.id = token.sub || "";
// Ensure roles are passed to the session
if (token.role) {
if (token.role && Array.isArray(token.role)) {
session.user.role = token.role;
session.user.username = token.username || '';
session.user.first_name = token.first_name || '';
@ -114,6 +125,9 @@ export const authOptions: NextAuthOptions = {
session.user.first_name = '';
session.user.last_name = '';
}
// Add debug log to see what roles are being passed
console.log('Session user roles:', session.user.role);
}
return session;
}
@ -133,7 +147,7 @@ export const authOptions: NextAuthOptions = {
},
},
},
debug: false,
debug: true, // Enable debug logs temporarily to see role information
};
const handler = NextAuth(authOptions);

View File

@ -11,12 +11,13 @@ export default function SignIn() {
const [message, setMessage] = useState("");
useEffect(() => {
// Clear cookies on errors or manual signout
// Always clear cookies on signin page load to ensure fresh authentication
clearAuthCookies();
// Set error message if present
if (error) {
console.log("Clearing auth cookies due to error:", error);
clearAuthCookies();
// Set error message
if (error === "RefreshTokenError" || error === "invalid_grant") {
setMessage("Your session has expired. Please sign in again.");
} else {
@ -25,9 +26,24 @@ export default function SignIn() {
}
}, [error]);
// Simple login function
// Login function with callbackUrl to maintain original destination
const handleSignIn = () => {
signIn("keycloak", { callbackUrl: "/" });
// Get the callback URL from the query parameters or use the home page
const callbackUrl = searchParams.get("callbackUrl") || "/";
// Add a timestamp parameter to avoid caching issues
const timestamp = new Date().getTime();
const authParams = {
callbackUrl,
redirect: true,
// Adding a timestamp to force Keycloak to skip any cached session
authParams: {
prompt: "login",
t: timestamp.toString()
}
};
signIn("keycloak", authParams);
};
return (

View File

@ -114,17 +114,87 @@ export function clearAuthCookies() {
// Get all cookies to check for chunked auth cookies
const cookies = document.cookie.split(';');
// Clear main auth cookies
// Try multiple path and domain combinations for thorough cleanup
const paths = ['/', '/auth', '/realms', '/admin'];
const domain = window.location.hostname;
const domains = [
domain,
`.${domain}`,
domain.split('.').slice(-2).join('.'),
`.${domain.split('.').slice(-2).join('.')}`
];
// Clear main auth cookies with all path/domain combinations
authCookies.forEach(cookieName => {
// Basic deletion
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; SameSite=None; Secure`;
// Try more aggressive deletion with different paths and domains
paths.forEach(path => {
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=${path}; SameSite=None; Secure`;
domains.forEach(domainValue => {
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=${path}; domain=${domainValue}; SameSite=None; Secure`;
});
});
});
// Check for and clear any chunked cookies
// Check for and clear any chunked cookies and cookies with dynamic names
cookies.forEach(cookie => {
const cookieName = cookie.split('=')[0].trim();
// Check for chunked cookies (they end with a number)
if (cookieName.startsWith('next-auth.') && /\.\d+$/.test(cookieName)) {
// Clear chunked cookies (end with a number) and any auth-related cookies
if (cookieName.startsWith('next-auth.') ||
cookieName.includes('keycloak') ||
cookieName.includes('auth') ||
cookieName.includes('session') ||
/\.\d+$/.test(cookieName)) {
// Basic deletion
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=/; SameSite=None; Secure`;
// Try more aggressive deletion with different paths and domains
paths.forEach(path => {
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=${path}; SameSite=None; Secure`;
domains.forEach(domainValue => {
document.cookie = `${cookieName}=; expires=Thu, 01 Jan 1970 00:00:00 UTC; path=${path}; domain=${domainValue}; SameSite=None; Secure`;
});
});
}
});
// Clear localStorage items related to authentication
try {
const authItems = [
'Meteor.loginToken',
'Meteor.userId',
'token',
'refreshToken',
'userId',
'userName',
'userEmail'
];
authItems.forEach(item => {
localStorage.removeItem(item);
});
// Also look for any items with auth-related names
for (let i = 0; i < localStorage.length; i++) {
const key = localStorage.key(i);
if (key && (key.includes('token') || key.includes('auth') || key.includes('session'))) {
localStorage.removeItem(key);
}
}
} catch (e) {
console.error('Failed to clear localStorage:', e);
}
// Clear all sessionStorage
try {
sessionStorage.clear();
} catch (e) {
console.error('Failed to clear sessionStorage:', e);
}
}