diff --git a/app/[section]/page.tsx b/app/[section]/page.tsx
index 2dc1195e..d24fe1c2 100644
--- a/app/[section]/page.tsx
+++ b/app/[section]/page.tsx
@@ -1,7 +1,7 @@
import { notFound } from 'next/navigation'
import { getServerSession } from 'next-auth/next';
import { authOptions } from '@/app/api/auth/[...nextauth]/route';
-import { ResponsiveIframe } from '@/app/components/responsive-iframe';
+import ResponsiveIframe from '@/app/components/responsive-iframe';
import { redirect } from 'next/navigation';
// Use environment variables for real service URLs
@@ -62,7 +62,7 @@ export default async function SectionPage(props: { params: { section: string } }
)
diff --git a/app/api/auth/[...nextauth]/route.ts b/app/api/auth/[...nextauth]/route.ts
index 34251d30..80e67910 100644
--- a/app/api/auth/[...nextauth]/route.ts
+++ b/app/api/auth/[...nextauth]/route.ts
@@ -1,6 +1,57 @@
import NextAuth, { NextAuthOptions } from "next-auth";
import KeycloakProvider from "next-auth/providers/keycloak";
+// Define Keycloak profile type
+interface KeycloakProfile {
+ sub: string;
+ email?: string;
+ name?: string;
+ preferred_username?: string;
+ given_name?: string;
+ family_name?: string;
+ realm_access?: {
+ roles: string[];
+ };
+}
+
+// Define custom profile type
+interface CustomProfile {
+ id: string;
+ name?: string | null;
+ email?: string | null;
+ username: string;
+ first_name: string;
+ last_name: string;
+ role: string[];
+}
+
+// Declare module augmentation for NextAuth types
+declare module "next-auth" {
+ interface Session {
+ user: {
+ id: string;
+ name?: string | null;
+ email?: string | null;
+ image?: string | null;
+ username: string;
+ first_name: string;
+ last_name: string;
+ role: string[];
+ };
+ accessToken?: string;
+ }
+
+ interface JWT {
+ sub?: string;
+ accessToken?: string;
+ refreshToken?: string;
+ role?: string[];
+ username?: string;
+ first_name?: string;
+ last_name?: string;
+ }
+}
+
// Simple, minimal implementation - NO REFRESH TOKEN LOGIC
export const authOptions: NextAuthOptions = {
providers: [
@@ -8,37 +59,69 @@ export const authOptions: NextAuthOptions = {
clientId: process.env.KEYCLOAK_CLIENT_ID || "",
clientSecret: process.env.KEYCLOAK_CLIENT_SECRET || "",
issuer: process.env.KEYCLOAK_ISSUER || "",
+ profile(profile: any) {
+ // Extract roles from the profile
+ const roles = profile.realm_access?.roles || [];
+
+ return {
+ id: profile.sub,
+ name: profile.name || profile.preferred_username,
+ email: profile.email,
+ image: null,
+ role: roles.map((role: string) => role.replace(/^ROLE_/, '').toLowerCase()),
+ first_name: profile.given_name || '',
+ last_name: profile.family_name || '',
+ username: profile.preferred_username || profile.email?.split('@')[0] || '',
+ };
+ }
}),
],
session: {
strategy: "jwt",
- maxAge: 8 * 60 * 60, // 8 hours only
+ maxAge: 8 * 60 * 60, // 8 hours
},
callbacks: {
- // Simple JWT callback - no refresh logic
- async jwt({ token, account }) {
- if (account) {
- // Initial sign-in, store tokens
+ async jwt({ token, account, profile }: any) {
+ if (account && profile) {
+ // Just store access token and critical fields
token.accessToken = account.access_token;
- token.sub = account.providerAccountId;
+ // Make sure roles are available
+ if (profile.role) {
+ token.role = profile.role;
+ token.username = profile.username || '';
+ token.first_name = profile.first_name || '';
+ token.last_name = profile.last_name || '';
+ }
}
return token;
},
- // Simple session callback
- async session({ session, token }) {
+ async session({ session, token }: any) {
+ // Pass necessary info to the session
session.accessToken = token.accessToken;
if (session.user) {
session.user.id = token.sub || "";
+
+ // Ensure roles are passed to the session
+ if (token.role) {
+ session.user.role = token.role;
+ session.user.username = token.username || '';
+ session.user.first_name = token.first_name || '';
+ session.user.last_name = token.last_name || '';
+ } else {
+ // Fallback roles
+ session.user.role = ["user"];
+ session.user.username = '';
+ session.user.first_name = '';
+ session.user.last_name = '';
+ }
}
return session;
}
},
- // Redirect to signin page for any errors
pages: {
signIn: '/signin',
error: '/signin',
},
- // Set reasonable cookie options
cookies: {
sessionToken: {
name: 'next-auth.session-token',
diff --git a/app/dossiers/page.tsx b/app/dossiers/page.tsx
index 8610b3ac..0454cd9e 100644
--- a/app/dossiers/page.tsx
+++ b/app/dossiers/page.tsx
@@ -1,7 +1,7 @@
import { getServerSession } from "next-auth/next";
import { authOptions } from "@/app/api/auth/[...nextauth]/route";
import { redirect } from "next/navigation";
-import { ResponsiveIframe } from "@/app/components/responsive-iframe";
+import ResponsiveIframe from "@/app/components/responsive-iframe";
export default async function Page() {
const session = await getServerSession(authOptions);
@@ -15,12 +15,12 @@ export default async function Page() {