fix(FE) : add full session logout
This commit is contained in:
No files matched your search
@@ -64,7 +64,7 @@ const sessionInfo = computed(() => ({
|
|||||||
</v-btn>
|
</v-btn>
|
||||||
</template>
|
</template>
|
||||||
|
|
||||||
<v-sheet rounded="md" width="360" elevation="10">
|
<v-sheet rounded="md" width="400" elevation="10">
|
||||||
<div class="px-8 pt-6">
|
<div class="px-8 pt-6">
|
||||||
<h6 class="text-h5 font-weight-medium">User Profile</h6>
|
<h6 class="text-h5 font-weight-medium">User Profile</h6>
|
||||||
<div class="d-flex align-center mt-4 pb-4">
|
<div class="d-flex align-center mt-4 pb-4">
|
||||||
|
|||||||
@@ -107,6 +107,9 @@ export const useAuth = () => {
|
|||||||
const response = await $fetch<LogoutResponse>('/api/auth/logout', {
|
const response = await $fetch<LogoutResponse>('/api/auth/logout', {
|
||||||
method: 'POST'
|
method: 'POST'
|
||||||
})
|
})
|
||||||
|
// const response = await $fetch<LogoutResponse>('/api/auth/clear-session', {
|
||||||
|
// method: 'POST'
|
||||||
|
// });
|
||||||
|
|
||||||
// Clear user immediately regardless of response
|
// Clear user immediately regardless of response
|
||||||
_user.value = null
|
_user.value = null
|
||||||
|
|||||||
@@ -64,8 +64,8 @@ const filterOptions = [
|
|||||||
modelKey: 'sortOption',
|
modelKey: 'sortOption',
|
||||||
options: [
|
options: [
|
||||||
{ label: 'Default', value: null },
|
{ label: 'Default', value: null },
|
||||||
{ label: 'Tanggal Daftar ⬆', value: 'tanggal_daftar|DESC' },
|
{ label: 'Tanggal Daftar (Terbaru)', value: 'tanggal_daftar|DESC' },
|
||||||
{ label: 'Tanggal Daftar ⬇', value: 'tanggal_daftar|ASC' }
|
{ label: 'Tanggal Daftar (Terlama)', value: 'tanggal_daftar|ASC' }
|
||||||
],
|
],
|
||||||
defaultValue: null
|
defaultValue: null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,8 +61,8 @@ const filterOptions = [
|
|||||||
modelKey: 'sortOption',
|
modelKey: 'sortOption',
|
||||||
options: [
|
options: [
|
||||||
{ label: 'Default', value: null },
|
{ label: 'Default', value: null },
|
||||||
{ label: 'Tanggal Daftar ⬆', value: 'tanggal_daftar|DESC' },
|
{ label: 'Tanggal Daftar (Terbaru)', value: 'tanggal_daftar|DESC' },
|
||||||
{ label: 'Tanggal Daftar ⬇', value: 'tanggal_daftar|ASC' }
|
{ label: 'Tanggal Daftar (Terlama)', value: 'tanggal_daftar|ASC' }
|
||||||
],
|
],
|
||||||
defaultValue: null
|
defaultValue: null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,8 +61,8 @@ const filterOptions = [
|
|||||||
modelKey: 'sortOption',
|
modelKey: 'sortOption',
|
||||||
options: [
|
options: [
|
||||||
{ label: 'Default', value: null },
|
{ label: 'Default', value: null },
|
||||||
{ label: 'Tanggal Daftar ⬆', value: 'tanggal_daftar|DESC' },
|
{ label: 'Tanggal Daftar (Terbaru)', value: 'tanggal_daftar|DESC' },
|
||||||
{ label: 'Tanggal Daftar ⬇', value: 'tanggal_daftar|ASC' }
|
{ label: 'Tanggal Daftar (Terlama)', value: 'tanggal_daftar|ASC' }
|
||||||
],
|
],
|
||||||
defaultValue: null
|
defaultValue: null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -61,8 +61,8 @@ const filterOptions = [
|
|||||||
modelKey: 'sortOption',
|
modelKey: 'sortOption',
|
||||||
options: [
|
options: [
|
||||||
{ label: 'Default', value: null },
|
{ label: 'Default', value: null },
|
||||||
{ label: 'Tanggal Daftar ⬆', value: 'tanggal_daftar|DESC' },
|
{ label: 'Tanggal Daftar (Terbaru)', value: 'tanggal_daftar|DESC' },
|
||||||
{ label: 'Tanggal Daftar ⬇', value: 'tanggal_daftar|ASC' }
|
{ label: 'Tanggal Daftar (Terlama)', value: 'tanggal_daftar|ASC' }
|
||||||
],
|
],
|
||||||
defaultValue: null
|
defaultValue: null
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,77 @@
|
|||||||
|
// server/api/auth/clear-session.post.ts
|
||||||
|
// Endpoint to forcefully clear session cookies and logout from Keycloak
|
||||||
|
export default defineEventHandler(async (event) => {
|
||||||
|
try {
|
||||||
|
const config = useRuntimeConfig();
|
||||||
|
console.log('🧹 Clear session endpoint called');
|
||||||
|
|
||||||
|
// Get the current session to retrieve ID token for Keycloak logout
|
||||||
|
const sessionCookie = getCookie(event, 'user_session');
|
||||||
|
let idToken = null;
|
||||||
|
|
||||||
|
if (sessionCookie) {
|
||||||
|
try {
|
||||||
|
// Try to decode JWT-based session from cookie
|
||||||
|
const sessionJson = Buffer.from(sessionCookie, 'base64').toString('utf-8');
|
||||||
|
const session = JSON.parse(sessionJson);
|
||||||
|
idToken = session.idToken;
|
||||||
|
console.log('🔑 ID token found for Keycloak logout');
|
||||||
|
} catch (error) {
|
||||||
|
console.warn('⚠️ Could not parse session cookie (might be old format)');
|
||||||
|
// Continue anyway to clear cookies
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Clear all auth-related cookies
|
||||||
|
console.log('🧹 Clearing all session cookies...');
|
||||||
|
deleteCookie(event, 'user_session');
|
||||||
|
deleteCookie(event, 'oauth_state');
|
||||||
|
|
||||||
|
// Also clear with different path variations
|
||||||
|
deleteCookie(event, 'user_session', { path: '/' });
|
||||||
|
deleteCookie(event, 'oauth_state', { path: '/' });
|
||||||
|
|
||||||
|
console.log('✅ Local session cleared successfully');
|
||||||
|
|
||||||
|
// Build Keycloak logout URL
|
||||||
|
const logoutPath = config.keycloakLogoutUri || `${config.keycloakIssuer}/protocol/openid-connect/logout`;
|
||||||
|
const logoutUrl = new URL(logoutPath);
|
||||||
|
|
||||||
|
const postLogoutRedirectUri = config.postLogoutRedirectUri || `${config.public.authUrl}/LoginPage?logout=success`;
|
||||||
|
|
||||||
|
logoutUrl.searchParams.set('client_id', config.keycloakClientId);
|
||||||
|
logoutUrl.searchParams.set('post_logout_redirect_uri', postLogoutRedirectUri);
|
||||||
|
|
||||||
|
// Add ID token hint if available for proper Keycloak session termination
|
||||||
|
if (idToken) {
|
||||||
|
logoutUrl.searchParams.set('id_token_hint', idToken);
|
||||||
|
console.log('🔑 Added id_token_hint to Keycloak logout URL');
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log('🔗 Keycloak logout URL:', logoutUrl.toString());
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: true,
|
||||||
|
logoutUrl: logoutUrl.toString(),
|
||||||
|
message: 'Session cleared successfully. Redirecting to Keycloak logout...'
|
||||||
|
};
|
||||||
|
|
||||||
|
} catch (error: any) {
|
||||||
|
console.error('❌ Clear session error:', error);
|
||||||
|
|
||||||
|
// Even on error, provide a basic logout URL
|
||||||
|
const config = useRuntimeConfig();
|
||||||
|
const postLogoutRedirectUri = config.postLogoutRedirectUri || `${config.public.authUrl}/LoginPage?logout=success`;
|
||||||
|
const logoutPath = config.keycloakLogoutUri || `${config.keycloakIssuer}/protocol/openid-connect/logout`;
|
||||||
|
const fallbackLogoutUrl = new URL(logoutPath);
|
||||||
|
fallbackLogoutUrl.searchParams.set('client_id', config.keycloakClientId);
|
||||||
|
fallbackLogoutUrl.searchParams.set('post_logout_redirect_uri', postLogoutRedirectUri);
|
||||||
|
|
||||||
|
return {
|
||||||
|
success: false,
|
||||||
|
logoutUrl: fallbackLogoutUrl.toString(),
|
||||||
|
error: 'Error during session cleanup',
|
||||||
|
message: error.message
|
||||||
|
};
|
||||||
|
}
|
||||||
|
});
|
||||||
Reference in New Issue
Block a user