- Updated nuxt.config.js to include Authentik configuration and public keys for client-side access. - Introduced a new composable, useAuth.js, for handling authentication logic with Authentik, including user validation, login, and logout functionalities. - Enhanced documentation to reflect the simplified RBAC structure and the integration of Authentik, emphasizing user-centric design and streamlined permission management. - Refactored middleware for authentication checks and improved error handling during user validation. - Created new pages for login and dashboard, ensuring proper routing and user experience. - Removed obsolete Metabase integration and unnecessary complexity from the project structure.
76 lines
2.1 KiB
JavaScript
76 lines
2.1 KiB
JavaScript
// OAuth2 callback endpoint
|
|
export default defineEventHandler(async (event) => {
|
|
const config = useRuntimeConfig();
|
|
const query = getQuery(event);
|
|
|
|
if (query.error) {
|
|
throw createError({
|
|
statusCode: 400,
|
|
message: query.error_description || 'Authentication failed'
|
|
});
|
|
}
|
|
|
|
if (!query.code) {
|
|
throw createError({
|
|
statusCode: 400,
|
|
message: 'No authorization code received'
|
|
});
|
|
}
|
|
|
|
try {
|
|
// Exchange code for tokens
|
|
const tokens = await $fetch(`${config.public.authentikUrl}/application/o/token/`, {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/x-www-form-urlencoded'
|
|
},
|
|
body: new URLSearchParams({
|
|
grant_type: 'authorization_code',
|
|
code: query.code,
|
|
redirect_uri: `${config.public.appUrl}/api/auth/callback`,
|
|
client_id: config.authentik.clientId,
|
|
client_secret: config.authentik.clientSecret
|
|
})
|
|
});
|
|
|
|
// Get user info using access token
|
|
const userInfo = await $fetch(`${config.public.authentikUrl}/application/o/userinfo/`, {
|
|
headers: {
|
|
'Authorization': `Bearer ${tokens.access_token}`
|
|
}
|
|
});
|
|
|
|
// Set cookies
|
|
setCookie(event, 'auth_token', tokens.access_token, {
|
|
httpOnly: true,
|
|
secure: process.env.NODE_ENV === 'production',
|
|
sameSite: 'lax',
|
|
maxAge: 60 * 60 * 24 // 24 hours
|
|
});
|
|
|
|
setCookie(event, 'refresh_token', tokens.refresh_token, {
|
|
httpOnly: true,
|
|
secure: process.env.NODE_ENV === 'production',
|
|
sameSite: 'lax',
|
|
maxAge: 60 * 60 * 24 * 30 // 30 days
|
|
});
|
|
|
|
// Store user info
|
|
setCookie(event, 'user_info', JSON.stringify(userInfo), {
|
|
httpOnly: true,
|
|
secure: process.env.NODE_ENV === 'production',
|
|
sameSite: 'lax',
|
|
maxAge: 60 * 60 * 24 // 24 hours
|
|
});
|
|
|
|
// Redirect to dashboard
|
|
return sendRedirect(event, '/dashboard');
|
|
|
|
} catch (error) {
|
|
console.error('OAuth token exchange error:', error);
|
|
throw createError({
|
|
statusCode: error.response?.status || 500,
|
|
message: 'Failed to authenticate with Authentik'
|
|
});
|
|
}
|
|
});
|