Files
minecraft-account-manager/apps/web/src/lib/auth/admin-auth.ts
T

59 lines
1.9 KiB
TypeScript

import { extractOidcRoles } from "@minecraft-account-manager/auth";
import type { NextAuthOptions } from "next-auth";
import KeycloakProvider from "next-auth/providers/keycloak";
const issuer = process.env.KEYCLOAK_ISSUER_URL?.trim() ?? "";
const clientId = process.env.KEYCLOAK_CLIENT_ID?.trim() ?? "";
const clientSecret = process.env.KEYCLOAK_CLIENT_SECRET?.trim() ?? "";
export const requiredAdminRole =
process.env.KEYCLOAK_REQUIRED_ROLE?.trim() || "minecraft-account-manager-admin";
export const isAdminOidcConfigured = Boolean(issuer && clientId && clientSecret);
export const adminAuthOptions: NextAuthOptions = {
secret: process.env.AUTH_SECRET,
providers: isAdminOidcConfigured
? [
KeycloakProvider({
issuer,
clientId,
clientSecret,
authorization: { params: { scope: "openid email profile" } },
}),
]
: [],
pages: { signIn: "/admin/login" },
session: { strategy: "jwt" },
callbacks: {
async signIn({ profile, account }) {
if (!isAdminOidcConfigured) return false;
return extractOidcRoles({
clientId,
profile,
idToken: account?.id_token,
accessToken: account?.access_token,
}).includes(requiredAdminRole);
},
async jwt({ token, profile, account }) {
if (profile || account?.id_token || account?.access_token) {
token.roles = extractOidcRoles({
clientId,
profile,
idToken: account?.id_token,
accessToken: account?.access_token,
});
}
token.roles ??= [];
return token;
},
async session({ session, token }) {
if (session.user) {
(session.user as typeof session.user & { roles: string[] }).roles = Array.isArray(token.roles)
? token.roles.filter((role): role is string => typeof role === "string")
: [];
}
return session;
},
},
};