feat(platform): add Discord onboarding and Velocity gate

This commit is contained in:
dmg
2026-08-01 13:45:18 -04:00
parent 9d305e5dc9
commit c5de0a1810
80 changed files with 4840 additions and 1572 deletions
+58
View File
@@ -0,0 +1,58 @@
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;
},
},
};