correction
This commit is contained in:
parent
517a5e897b
commit
1238deb36b
File diff suppressed because one or more lines are too long
@ -194,6 +194,7 @@ export const authOptions: NextAuthOptions = {
|
|||||||
},
|
},
|
||||||
callbacks: {
|
callbacks: {
|
||||||
async jwt({ token, account, profile }) {
|
async jwt({ token, account, profile }) {
|
||||||
|
// Initial sign-in: account and profile are present
|
||||||
if (account && profile) {
|
if (account && profile) {
|
||||||
const keycloakProfile = profile as KeycloakProfile;
|
const keycloakProfile = profile as KeycloakProfile;
|
||||||
const roles = keycloakProfile.realm_access?.roles || [];
|
const roles = keycloakProfile.realm_access?.roles || [];
|
||||||
@ -204,13 +205,20 @@ export const authOptions: NextAuthOptions = {
|
|||||||
token.accessToken = account.access_token ?? '';
|
token.accessToken = account.access_token ?? '';
|
||||||
token.refreshToken = account.refresh_token ?? '';
|
token.refreshToken = account.refresh_token ?? '';
|
||||||
token.idToken = account.id_token ?? '';
|
token.idToken = account.id_token ?? '';
|
||||||
token.accessTokenExpires = account.expires_at ?? 0;
|
// expires_at from Keycloak is in seconds since epoch, convert to milliseconds
|
||||||
|
token.accessTokenExpires = account.expires_at ? account.expires_at * 1000 : Date.now() + 3600 * 1000;
|
||||||
token.sub = keycloakProfile.sub;
|
token.sub = keycloakProfile.sub;
|
||||||
token.role = cleanRoles;
|
token.role = cleanRoles;
|
||||||
token.username = keycloakProfile.preferred_username ?? '';
|
token.username = keycloakProfile.preferred_username ?? '';
|
||||||
token.first_name = keycloakProfile.given_name ?? '';
|
token.first_name = keycloakProfile.given_name ?? '';
|
||||||
token.last_name = keycloakProfile.family_name ?? '';
|
token.last_name = keycloakProfile.family_name ?? '';
|
||||||
} else if (token.accessToken) {
|
|
||||||
|
// Return immediately on initial sign-in - don't try to refresh tokens we just received
|
||||||
|
return token;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Subsequent requests: check existing token
|
||||||
|
if (token.accessToken) {
|
||||||
try {
|
try {
|
||||||
const decoded = jwtDecode<DecodedToken>(token.accessToken as string);
|
const decoded = jwtDecode<DecodedToken>(token.accessToken as string);
|
||||||
if (decoded.realm_access?.roles) {
|
if (decoded.realm_access?.roles) {
|
||||||
@ -226,7 +234,7 @@ export const authOptions: NextAuthOptions = {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Check if token is expired and needs refresh
|
// Check if token is expired and needs refresh
|
||||||
// accessTokenExpires is in milliseconds (Date.now() + expires_in * 1000)
|
// accessTokenExpires is in milliseconds
|
||||||
const expiresAt = token.accessTokenExpires as number;
|
const expiresAt = token.accessTokenExpires as number;
|
||||||
if (expiresAt && Date.now() < expiresAt) {
|
if (expiresAt && Date.now() < expiresAt) {
|
||||||
// Token is still valid, return as-is
|
// Token is still valid, return as-is
|
||||||
@ -273,7 +281,7 @@ export const authOptions: NextAuthOptions = {
|
|||||||
return refreshedToken;
|
return refreshedToken;
|
||||||
},
|
},
|
||||||
async session({ session, token }) {
|
async session({ session, token }) {
|
||||||
// If session was invalidated or tokens are missing, return null to sign out
|
// If session was invalidated or tokens are missing, throw error to trigger sign out
|
||||||
if (token.error === "SessionNotActive" ||
|
if (token.error === "SessionNotActive" ||
|
||||||
token.error === "NoRefreshToken" ||
|
token.error === "NoRefreshToken" ||
|
||||||
!token.accessToken ||
|
!token.accessToken ||
|
||||||
@ -284,11 +292,9 @@ export const authOptions: NextAuthOptions = {
|
|||||||
hasRefreshToken: !!token.refreshToken
|
hasRefreshToken: !!token.refreshToken
|
||||||
});
|
});
|
||||||
|
|
||||||
// Return null to make NextAuth treat user as unauthenticated
|
// Throw error to make NextAuth treat user as unauthenticated
|
||||||
// This will trigger automatic redirect to sign-in page
|
// This will trigger automatic redirect to sign-in page
|
||||||
// The client-side code will detect session invalidation by checking for
|
throw new Error(token.error || "SessionInvalidated");
|
||||||
// session cookie existence when status is unauthenticated
|
|
||||||
return null as any;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// For other errors, throw to trigger error handling
|
// For other errors, throw to trigger error handling
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user