Files
ArchiTools/src/core/auth/auth-options.ts
T
AI Assistant ca4d7b5d8d feat(auth): force Authentik login on first visit, fix ManicTime sync
Auth:
- Add middleware.ts that redirects unauthenticated users to Authentik SSO
- Extract authOptions to shared auth-options.ts
- Add getAuthSession() helper for API route protection
- Add loading spinner during session validation
- Dev mode bypasses auth (stub user still works)

ManicTime:
- Fix hardcoded companyId="beletage" — now uses group context from Tags.txt
- Fix extended project format label parsing (extracts name after year)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-09 12:26:08 +02:00

48 lines
1.5 KiB
TypeScript

import type { NextAuthOptions } from "next-auth";
import AuthentikProvider from "next-auth/providers/authentik";
export const authOptions: NextAuthOptions = {
providers: [
AuthentikProvider({
clientId: process.env.AUTHENTIK_CLIENT_ID || "",
clientSecret: process.env.AUTHENTIK_CLIENT_SECRET || "",
issuer: process.env.AUTHENTIK_ISSUER || "",
}),
],
callbacks: {
async jwt({ token, user, profile }) {
if (user) {
token.id = user.id;
}
if (profile) {
// Map Authentik groups/roles to our internal roles
const groups = (profile as any).groups || [];
let role = "user";
if (groups.includes("architools-admin")) role = "admin";
else if (groups.includes("architools-manager")) role = "manager";
token.role = role;
// Map company based on groups
let company = "group";
if (groups.includes("company-beletage")) company = "beletage";
else if (groups.includes("company-urban-switch"))
company = "urban-switch";
else if (groups.includes("company-studii-de-teren"))
company = "studii-de-teren";
token.company = company;
}
return token;
},
async session({ session, token }) {
if (session.user) {
(session.user as any).id = token.id;
(session.user as any).role = token.role || "user";
(session.user as any).company = token.company || "group";
}
return session;
},
},
};