This commit is contained in:
82
server/api/auth/[...].ts
Normal file
82
server/api/auth/[...].ts
Normal file
@@ -0,0 +1,82 @@
|
||||
import { NuxtAuthHandler } from '#auth'
|
||||
import ZitadelProvider from '@auth/core/providers/zitadel'
|
||||
|
||||
export default NuxtAuthHandler({
|
||||
secret: process.env.AUTH_SECRET,
|
||||
providers: [
|
||||
ZitadelProvider({
|
||||
clientId: process.env.ZITADEL_CLIENT_ID,
|
||||
issuer: process.env.ZITADEL_DOMAIN,
|
||||
authorization: {
|
||||
params: {
|
||||
scope: 'openid email profile offline_access urn:zitadel:iam:org:project:371479849505653263:aud'
|
||||
}
|
||||
}
|
||||
})
|
||||
],
|
||||
session: {
|
||||
strategy: 'jwt',
|
||||
maxAge: 30 * 24 * 60 * 60, // 30 days
|
||||
},
|
||||
callbacks: {
|
||||
async jwt({ token, account, user }) {
|
||||
if (account?.provider === 'zitadel') {
|
||||
token.accessToken = account.access_token
|
||||
token.idToken = account.id_token
|
||||
token.roles = (user as any)?.roles
|
||||
|
||||
/* Extract org roles from ID token claims */
|
||||
const allOrgRoles: Record<string, Record<string, Record<string, string>>> = {}
|
||||
const idTokenClaims = (() => {
|
||||
try {
|
||||
const parts = (account.id_token || '').split('.')
|
||||
if (parts.length === 3) {
|
||||
const payload = Buffer.from(parts[1], 'base64url').toString('utf8')
|
||||
return JSON.parse(payload) as Record<string, any>
|
||||
}
|
||||
} catch { /* ignore */ }
|
||||
return null
|
||||
})()
|
||||
if (idTokenClaims) {
|
||||
for (const key of Object.keys(idTokenClaims)) {
|
||||
if (key.startsWith('urn:zitadel:iam:org:project:') && key.endsWith(':roles')) {
|
||||
allOrgRoles[key] = idTokenClaims[key]
|
||||
}
|
||||
}
|
||||
}
|
||||
/* Also check userinfo response for org role claims */
|
||||
for (const key of Object.keys((user as any) || {})) {
|
||||
if (key.startsWith('urn:zitadel:iam:org:project:') && key.endsWith(':roles')) {
|
||||
allOrgRoles[key] = (user as any)[key]
|
||||
}
|
||||
}
|
||||
token.allOrgRoles = Object.keys(allOrgRoles).length > 0 ? allOrgRoles : undefined
|
||||
}
|
||||
if (user?.id) {
|
||||
token.sub = user.id
|
||||
if (user.name || (user as any).profile?.given_name) {
|
||||
token.name = user.name || ((user as any).profile?.given_name || '')
|
||||
}
|
||||
token.email = user.email || ''
|
||||
token.image = user.image || undefined
|
||||
}
|
||||
return token
|
||||
},
|
||||
async session({ session, token }) {
|
||||
const user = session.user as any
|
||||
if (user) {
|
||||
user.name = token.name || undefined
|
||||
user.email = token.email || undefined
|
||||
user.image = token.image || undefined
|
||||
user.roles = token.roles as string[] | undefined
|
||||
user.accessToken = token.accessToken as string | undefined
|
||||
user.allOrgRoles = token.allOrgRoles as Record<string, Record<string, Record<string, string>>> | undefined
|
||||
}
|
||||
return session
|
||||
},
|
||||
async redirect({ url, baseUrl }) {
|
||||
if (url === '/login') return '/login'
|
||||
return url.startsWith(baseUrl) ? url : baseUrl
|
||||
}
|
||||
}
|
||||
})
|
||||
Reference in New Issue
Block a user