@@ -60,88 +60,92 @@ export const getProviders = () => {
6060 const providers : IdentityProvider [ ] = eeIdentityProviders ;
6161
6262 if ( env . SMTP_CONNECTION_URL && env . EMAIL_FROM_ADDRESS && env . AUTH_EMAIL_CODE_LOGIN_ENABLED === 'true' ) {
63- providers . push ( { provider : EmailProvider ( {
64- server : env . SMTP_CONNECTION_URL ,
65- from : env . EMAIL_FROM_ADDRESS ,
66- maxAge : 60 * 10 ,
67- generateVerificationToken : async ( ) => {
68- const token = String ( Math . floor ( 100000 + Math . random ( ) * 900000 ) ) ;
69- return token ;
70- } ,
71- sendVerificationRequest : async ( { identifier, provider, token } ) => {
72- const transport = createTransport ( provider . server ) ;
73- const html = await render ( MagicLinkEmail ( { token : token } ) ) ;
74- const result = await transport . sendMail ( {
75- to : identifier ,
76- from : provider . from ,
77- subject : 'Log in to Sourcebot' ,
78- html,
79- text : `Log in to Sourcebot using this code: ${ token } `
80- } ) ;
63+ providers . push ( {
64+ provider : EmailProvider ( {
65+ server : env . SMTP_CONNECTION_URL ,
66+ from : env . EMAIL_FROM_ADDRESS ,
67+ maxAge : 60 * 10 ,
68+ generateVerificationToken : async ( ) => {
69+ const token = String ( Math . floor ( 100000 + Math . random ( ) * 900000 ) ) ;
70+ return token ;
71+ } ,
72+ sendVerificationRequest : async ( { identifier, provider, token } ) => {
73+ const transport = createTransport ( provider . server ) ;
74+ const html = await render ( MagicLinkEmail ( { token : token } ) ) ;
75+ const result = await transport . sendMail ( {
76+ to : identifier ,
77+ from : provider . from ,
78+ subject : 'Log in to Sourcebot' ,
79+ html,
80+ text : `Log in to Sourcebot using this code: ${ token } `
81+ } ) ;
8182
82- const failed = result . rejected . concat ( result . pending ) . filter ( Boolean ) ;
83- if ( failed . length ) {
84- throw new Error ( `Email(s) (${ failed . join ( ", " ) } ) could not be sent` ) ;
83+ const failed = result . rejected . concat ( result . pending ) . filter ( Boolean ) ;
84+ if ( failed . length ) {
85+ throw new Error ( `Email(s) (${ failed . join ( ", " ) } ) could not be sent` ) ;
86+ }
8587 }
86- }
87- } ) , purpose : "sso" } ) ;
88+ } ) , purpose : "sso"
89+ } ) ;
8890 }
8991
9092 if ( env . AUTH_CREDENTIALS_LOGIN_ENABLED === 'true' ) {
91- providers . push ( { provider : Credentials ( {
92- credentials : {
93- email : { } ,
94- password : { }
95- } ,
96- type : "credentials" ,
97- authorize : async ( credentials ) => {
98- const body = verifyCredentialsRequestSchema . safeParse ( credentials ) ;
99- if ( ! body . success ) {
100- return null ;
101- }
102- const { email, password } = body . data ;
93+ providers . push ( {
94+ provider : Credentials ( {
95+ credentials : {
96+ email : { } ,
97+ password : { }
98+ } ,
99+ type : "credentials" ,
100+ authorize : async ( credentials ) => {
101+ const body = verifyCredentialsRequestSchema . safeParse ( credentials ) ;
102+ if ( ! body . success ) {
103+ return null ;
104+ }
105+ const { email, password } = body . data ;
103106
104- const user = await prisma . user . findUnique ( {
105- where : { email }
106- } ) ;
107+ const user = await prisma . user . findUnique ( {
108+ where : { email }
109+ } ) ;
110+
111+ // The user doesn't exist, so create a new one.
112+ if ( ! user ) {
113+ const hashedPassword = bcrypt . hashSync ( password , 10 ) ;
114+ const newUser = await prisma . user . create ( {
115+ data : {
116+ email,
117+ hashedPassword,
118+ }
119+ } ) ;
107120
108- // The user doesn't exist, so create a new one.
109- if ( ! user ) {
110- const hashedPassword = bcrypt . hashSync ( password , 10 ) ;
111- const newUser = await prisma . user . create ( {
112- data : {
113- email,
114- hashedPassword,
121+ const authJsUser : AuthJsUser = {
122+ id : newUser . id ,
123+ email : newUser . email ,
115124 }
116- } ) ;
117125
118- const authJsUser : AuthJsUser = {
119- id : newUser . id ,
120- email : newUser . email ,
121- }
126+ onCreateUser ( { user : authJsUser } ) ;
127+ return authJsUser ;
122128
123- onCreateUser ( { user : authJsUser } ) ;
124- return authJsUser ;
129+ // Otherwise, the user exists, so verify the password.
130+ } else {
131+ if ( ! user . hashedPassword ) {
132+ return null ;
133+ }
125134
126- // Otherwise, the user exists, so verify the password.
127- } else {
128- if ( ! user . hashedPassword ) {
129- return null ;
130- }
135+ if ( ! bcrypt . compareSync ( password , user . hashedPassword ) ) {
136+ return null ;
137+ }
131138
132- if ( ! bcrypt . compareSync ( password , user . hashedPassword ) ) {
133- return null ;
139+ return {
140+ id : user . id ,
141+ email : user . email ,
142+ name : user . name ?? undefined ,
143+ image : user . image ?? undefined ,
144+ } ;
134145 }
135-
136- return {
137- id : user . id ,
138- email : user . email ,
139- name : user . name ?? undefined ,
140- image : user . image ?? undefined ,
141- } ;
142146 }
143- }
144- } ) , purpose : "sso" } ) ;
147+ } ) , purpose : "sso"
148+ } ) ;
145149 }
146150
147151 return providers ;
@@ -156,7 +160,29 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
156160 trustHost : true ,
157161 events : {
158162 createUser : onCreateUser ,
159- signIn : async ( { user } ) => {
163+ signIn : async ( { user, account } ) => {
164+ // Explicitly update the Account record with the OAuth token details.
165+ // This is necessary to update the access token when the user
166+ // re-authenticates.
167+ if ( account && account . provider && account . providerAccountId ) {
168+ await prisma . account . update ( {
169+ where : {
170+ provider_providerAccountId : {
171+ provider : account . provider ,
172+ providerAccountId : account . providerAccountId ,
173+ } ,
174+ } ,
175+ data : {
176+ refresh_token : account . refresh_token ,
177+ access_token : account . access_token ,
178+ expires_at : account . expires_at ,
179+ token_type : account . token_type ,
180+ scope : account . scope ,
181+ id_token : account . id_token ,
182+ }
183+ } )
184+ }
185+
160186 if ( user . id ) {
161187 await auditService . createAudit ( {
162188 action : "user.signed_in" ,
@@ -225,7 +251,7 @@ export const { handlers, signIn, signOut, auth } = NextAuth({
225251 // Propagate the userId to the session.
226252 id : token . userId ,
227253 }
228-
254+
229255 // Pass only linked account provider errors to the session (not sensitive tokens)
230256 if ( token . linkedAccountTokens ) {
231257 const errors : Record < string , string > = { } ;
0 commit comments