77 lines
2.0 KiB
TypeScript
77 lines
2.0 KiB
TypeScript
import { jwtDecode } from 'jwt-decode'
|
|
import type { KeycloakTokenPayload, Organization } from '~~/types/keycloak'
|
|
import { createLogger } from '~~/shared/utils/logger'
|
|
|
|
export default defineOAuthKeycloakEventHandler({
|
|
async onSuccess(event, { user, tokens }) {
|
|
const config = useRuntimeConfig()
|
|
const logger = createLogger({
|
|
level: config.public.logLevel,
|
|
tag: 'auth',
|
|
fancy: import.meta.env.MODE !== 'production'
|
|
})
|
|
|
|
const rawAccessToken = tokens?.access_token
|
|
let decodedJwt: KeycloakTokenPayload | null = null
|
|
|
|
try {
|
|
decodedJwt = jwtDecode<KeycloakTokenPayload>(rawAccessToken!)
|
|
} catch (err) {
|
|
logger.warn('Failed to decode access token:', err)
|
|
}
|
|
|
|
const organizations = decodedJwt ? extractOrganizations(decodedJwt) : []
|
|
const roles = decodedJwt ? extractRoles(decodedJwt) : []
|
|
|
|
await setUserSession(event, {
|
|
user: {
|
|
keycloakId: user.sub,
|
|
name: user.preferred_username,
|
|
organizations,
|
|
roles
|
|
},
|
|
jwt: {
|
|
accessToken: tokens.access_token,
|
|
refreshToken: tokens.refresh_token,
|
|
expiresIn: tokens.expires_in
|
|
},
|
|
loggedInAt: Date.now()
|
|
})
|
|
|
|
return sendRedirect(event, '/callback')
|
|
},
|
|
|
|
onError(event) {
|
|
const config = useRuntimeConfig()
|
|
const logger = createLogger({
|
|
level: config.public.logLevel,
|
|
tag: 'auth'
|
|
})
|
|
|
|
logger.error('Error during keycloak authentication')
|
|
return sendRedirect(event, '/login')
|
|
}
|
|
})
|
|
|
|
function extractOrganizations(decoded: KeycloakTokenPayload): Organization[] {
|
|
const organizations: Organization[] = []
|
|
const orgClaim = decoded?.organization ?? null
|
|
|
|
if (orgClaim && typeof orgClaim === 'object') {
|
|
Object.entries(orgClaim).forEach(([name, meta]) => {
|
|
if (!name || !meta?.id) return
|
|
|
|
organizations.push({
|
|
name: name,
|
|
id: meta.id
|
|
})
|
|
})
|
|
}
|
|
|
|
return organizations
|
|
}
|
|
|
|
function extractRoles(decoded: KeycloakTokenPayload): string[] {
|
|
return decoded?.resource_access?.legalconsenthub?.roles ?? []
|
|
}
|