auth flow
This commit is contained in:
parent
3be309c0fe
commit
d488979109
@ -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);
|
||||
|
||||
@ -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 (
|
||||
|
||||
@ -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);
|
||||
}
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user