mod-portal-v2/server/api/auth/token.post.ts

61 lines
No EOL
1.6 KiB
TypeScript

function parseJwt(token: string) {
try {
const base64Payload = token.split('.')[1]
const payload = Buffer.from(base64Payload, 'base64').toString('utf8')
return JSON.parse(payload)
} catch {
return null
}
}
export default defineEventHandler(async (event) => {
const config = useRuntimeConfig(event)
const body = await readBody(event)
if (!body?.code || !body?.redirectUri) {
throw createError({
statusCode: 400,
statusMessage: 'Missing code or redirectUri'
})
}
const tokenUrl = `${config.public.keycloakUrl}/realms/${config.public.keycloakRealm}/protocol/openid-connect/token`
const params = new URLSearchParams({
grant_type: 'authorization_code',
client_id: config.public.keycloakClientId,
code: body.code,
redirect_uri: body.redirectUri
})
if (config.keycloakClientSecret) {
params.append('client_secret', config.keycloakClientSecret)
}
try {
const response = await $fetch<any>(tokenUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/x-www-form-urlencoded'
},
body: params.toString()
})
const decodedToken = parseJwt(response.access_token)
const realmRoles: string[] = decodedToken?.realm_access?.roles || []
if (!realmRoles.includes('portal-access')) {
throw createError({
statusCode: 403,
statusMessage: 'Access Denied'
})
}
return response
} catch (error: any) {
throw createError({
statusCode: error.statusCode || error.response?.status || 401,
statusMessage: error.data?.message || error.response?._data?.error_description || 'Failed to exchange code'
})
}
})