@@ -2,22 +2,30 @@ import { NextAuthOptions } from "next-auth";
22import ProConnectProvider , { ProConnectProfile } from "./ProConnectProvider" ;
33import * as Sentry from "@sentry/nextjs" ;
44
5- // Debug logging
6- console . log ( "🔧 NextAuth Configuration:" ) ;
7- console . log ( " PROCONNECT_ENV:" , process . env . PROCONNECT_ENV ) ;
8- console . log (
9- " PROCONNECT_CLIENT_ID:" ,
10- process . env . PROCONNECT_CLIENT_ID ? "✓ Set" : "✗ Missing"
11- ) ;
12- console . log (
13- " PROCONNECT_CLIENT_SECRET:" ,
14- process . env . PROCONNECT_CLIENT_SECRET ? "✓ Set" : "✗ Missing"
15- ) ;
16- console . log ( " NEXTAUTH_URL:" , process . env . NEXTAUTH_URL ) ;
17- console . log (
18- " NEXTAUTH_SECRET:" ,
19- process . env . NEXTAUTH_SECRET ? "✓ Set" : "✗ Missing"
20- ) ;
5+ // Allowed email domains for access control
6+ const ALLOWED_EMAIL_DOMAINS = [
7+ "pyrenees-atlantiques.gouv.fr" ,
8+ "seine-maritime.gouv.fr" ,
9+ "correze.gouv.fr" ,
10+ "dreets.gouv.fr" ,
11+ "travail.gouv.fr" ,
12+ "fabrique.social.gouv.fr" ,
13+ "sg.social.gouv.fr" ,
14+ // Add beta.gouv.fr for local development
15+ ...( process . env . NODE_ENV === "development" ? [ "beta.gouv.fr" ] : [ ] ) ,
16+ ] ;
17+
18+ // Helper function to check if email domain is allowed
19+ function isEmailDomainAllowed ( email : string | null | undefined ) : boolean {
20+ if ( ! email ) return false ;
21+
22+ const emailDomain = email . split ( "@" ) [ 1 ] ?. toLowerCase ( ) ;
23+ if ( ! emailDomain ) return false ;
24+
25+ return ALLOWED_EMAIL_DOMAINS . some (
26+ ( domain ) => emailDomain === domain . toLowerCase ( )
27+ ) ;
28+ }
2129
2230export const authOptions : NextAuthOptions = {
2331 providers : [
@@ -27,62 +35,57 @@ export const authOptions: NextAuthOptions = {
2735 } ) ,
2836 ] ,
2937 callbacks : {
30- async jwt ( { token, account, profile } ) {
31- console . log ( "📝 JWT Callback:" , {
32- hasAccount : ! ! account ,
33- hasProfile : ! ! profile ,
34- } ) ;
35- // Persist the OAuth access_token and profile to the token right after signin
38+ async signIn ( ) {
39+ // Always return true to allow session creation with id_token
40+ // This is needed for proper ProConnect logout (requires id_token_hint)
41+ //
42+ // Security: Authorization is enforced in multiple layers:
43+ // 1. JWT callback marks unauthorized users (token.unauthorized = true)
44+ // 2. useAuth() returns isAuthenticated = false for unauthorized users
45+ // 3. AuthorizationCheck redirects unauthorized users to /access-denied
46+ //
47+ // This approach prevents the "user jail" problem while maintaining security
48+ return true ;
49+ } ,
50+ async jwt ( { token, account, profile, user } ) {
51+ // Persist the OAuth tokens and profile after signin
3652 if ( account ) {
37- console . log ( " Account type:" , account . provider ) ;
3853 token . accessToken = account . access_token ;
3954 token . idToken = account . id_token ;
4055 }
4156 if ( profile ) {
42- console . log ( " Profile email:" , profile . email ) ;
4357 token . profile = profile as ProConnectProfile ;
58+
59+ // Check if the user's email domain is allowed
60+ const email = profile . email || user ?. email ;
61+ if ( ! isEmailDomainAllowed ( email ) ) {
62+ token . unauthorized = true ;
63+ }
4464 }
4565 return token ;
4666 } ,
4767 async session ( { session, token } ) {
48- console . log ( "🔐 Session Callback:" , {
49- hasToken : ! ! token ,
50- hasUser : ! ! session . user ,
51- } ) ;
52- // Send properties to the client
68+ // Pass tokens and profile to the client session
5369 session . accessToken = token . accessToken as string ;
5470 session . idToken = token . idToken as string ;
5571 session . profile = token . profile as ProConnectProfile | undefined ;
72+ session . unauthorized = token . unauthorized as boolean | undefined ;
5673 return session ;
5774 } ,
5875 } ,
5976 pages : {
6077 signIn : "/" ,
61- error : "/" ,
78+ error : "/access-denied " ,
6279 } ,
6380 events : {
6481 async signIn ( { user } ) {
65- console . log ( "✅ Sign in event:" , user . email ) ;
6682 Sentry . setUser ( {
6783 id : user . id ,
6884 email : user . email || undefined ,
6985 } ) ;
7086 } ,
7187 async signOut ( ) {
72- console . log ( "👋 Sign out event" ) ;
7388 Sentry . setUser ( null ) ;
7489 } ,
7590 } ,
76- logger : {
77- error ( code , metadata ) {
78- console . error ( "❌ NextAuth Error:" , code , metadata ) ;
79- } ,
80- warn ( code ) {
81- console . warn ( "⚠️ NextAuth Warning:" , code ) ;
82- } ,
83- debug ( code , metadata ) {
84- console . log ( "🐛 NextAuth Debug:" , code , metadata ) ;
85- } ,
86- } ,
87- debug : true ,
8891} ;
0 commit comments