11import NextAuth from "next-auth" ;
22import Credentials from "next-auth/providers/credentials" ;
33
4+ interface LoginApiUser {
5+ id : number | string ;
6+ username : string ;
7+ email : string ;
8+ firstName ?: string ;
9+ lastName ?: string ;
10+ roles ?: string [ ] ;
11+ permissions ?: string [ ] ;
12+ profilePicture ?: string | null ;
13+ verified ?: boolean ;
14+ }
15+
16+ interface LoginApiResponse {
17+ success ?: boolean ;
18+ message ?: string ;
19+ user ?: LoginApiUser ;
20+ token ?: string ;
21+ }
22+
423export const { handlers, signIn, signOut, auth } = NextAuth ( {
524 secret : process . env . AUTH_SECRET || process . env . NEXTAUTH_SECRET ,
625 trustHost : true ,
@@ -35,10 +54,10 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
3554
3655 // Check if response is JSON before parsing
3756 const contentType = res . headers . get ( "content-type" ) ;
38- let data : { success ?: boolean ; message ?: string ; user ?: unknown } ;
39-
57+ let data : LoginApiResponse ;
58+
4059 if ( contentType && contentType . includes ( "application/json" ) ) {
41- data = await res . json ( ) ;
60+ data = ( await res . json ( ) ) as LoginApiResponse ;
4261 } else {
4362 // Handle non-JSON responses (e.g. 401 from gateway, rate limit plain text)
4463 const text = await res . text ( ) ;
@@ -50,31 +69,39 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
5069
5170 if ( ! data . success || ! res . ok ) {
5271 const errorMessage = data . message || "Authentication failed" ;
53-
54- if ( errorMessage . toLowerCase ( ) . includes ( "verify" ) ||
72+
73+ if ( errorMessage . toLowerCase ( ) . includes ( "verify" ) ||
5574 errorMessage . toLowerCase ( ) . includes ( "verification" ) ||
5675 errorMessage . toLowerCase ( ) . includes ( "email" ) ) {
5776 throw new Error ( "EMAIL_VERIFICATION_REQUIRED" ) ;
5877 }
59-
78+
6079 if ( errorMessage . toLowerCase ( ) . includes ( "invalid credentials" ) ||
6180 errorMessage . toLowerCase ( ) . includes ( "user not found" ) ) {
6281 throw new Error ( "INVALID_CREDENTIALS" ) ;
6382 }
64-
83+
6584 throw new Error ( errorMessage ) ;
6685 }
6786
87+ const user = data . user ;
88+ if ( ! user ) {
89+ throw new Error ( "Authentication failed: no user data" ) ;
90+ }
91+ if ( ! data . token ) {
92+ throw new Error ( "Authentication failed: no token" ) ;
93+ }
94+
6895 return {
69- id : data . user . id . toString ( ) ,
70- username : data . user . username ,
71- email : data . user . email ,
72- firstName : data . user . firstName ,
73- lastName : data . user . lastName ,
74- roles : data . user . roles || [ "user" ] ,
75- permissions : data . user . permissions || [ ] ,
76- profilePicture : data . user . profilePicture ,
77- verified : data . user . verified || false ,
96+ id : user . id . toString ( ) ,
97+ username : user . username ,
98+ email : user . email ,
99+ firstName : user . firstName ,
100+ lastName : user . lastName ,
101+ roles : user . roles ?? [ "user" ] ,
102+ permissions : user . permissions ?? [ ] ,
103+ profilePicture : user . profilePicture ?? undefined ,
104+ verified : user . verified ?? false ,
78105 token : data . token ,
79106 } ;
80107 } catch ( error ) {
0 commit comments