11
22
33import { verifySession , verifyToken } from "./user" ;
4+ import { type ValidRole , VALID_ROLES } from "./configuration" ;
45
56import { type Payload } from 'payload'
67
@@ -20,6 +21,16 @@ function createAuthError(message: string, statusCode: number): AuthError {
2021
2122export type { AuthError } ;
2223
24+ function getValidRole ( permissions ?: string [ ] ) : ValidRole {
25+ if ( ! permissions || permissions . length === 0 ) return 'user' ;
26+ for ( const permission of permissions ) {
27+ if ( VALID_ROLES [ permission ] ) {
28+ return VALID_ROLES [ permission ] ;
29+ }
30+ }
31+ return 'user' ;
32+ }
33+
2334interface User {
2435 id : string ;
2536 email : string ;
@@ -69,118 +80,110 @@ export async function authenticateRequest({ req, payload }: AuthenticateRequestO
6980 role : user . role ,
7081 method : 'cookie' ,
7182 }
72- } else {
73- const session = await verifySession ( req )
74-
75- if ( ! session || ! session . sub || ! session . extra ) throw createAuthError ( "No valid session found" , 401 ) ;
76- const OAUTH_CLIENT_ID = process . env . OAUTH_CLIENT_ID ! ;
77- const permissions = ( ( session . resource_access as Record < string , { roles ?: string [ ] } > ) ?. [ OAUTH_CLIENT_ID ] ?. roles as string [ ] | undefined ) ;
78- if ( ! permissions ) throw createAuthError ( "User does not have permission to access this application." , 403 ) ;
79-
80- if ( ! payload ) throw createAuthError ( "Payload instance is required for Keycloak user normalisation" , 500 ) ;
81- const payloadUser = ( await payload . find ( { collection : 'users' , depth : 1 , limit : 1 , draft : false , overrideAccess : true , where : { email : { equals : session . extra . email } } } ) ) . docs [ 0 ]
82-
83- if ( ! payloadUser && session . extra ) {
84-
85-
86- // create the user in Payload
87- const newUser = await payload . create ( {
88- collection : 'users' ,
89- data : {
90- email : session . extra . email ,
91- name : session . extra . name ,
92- role : permissions [ 0 ] || 'user' ,
93- enabled : true ,
94- accounts : [
95- {
96- provider : 'keycloak' , providerAccountId : session . sub , type : 'oidc' ,
97- }
98- ] ,
99- } ,
100- draft : false ,
101- overrideAccess : true ,
102- } )
103- console . log ( "Created new Payload user for Keycloak user:" , newUser . id , newUser . email )
104- return {
105-
106- method : 'bearer' , ...newUser
107- }
108- } else if ( payloadUser ) {
109- // update user role if changed
110- if ( payloadUser . role !== permissions [ 0 ] ) {
111- await payload . update ( {
112- collection : 'users' ,
113- id : payloadUser . id ,
114- data : {
115- role : permissions [ 0 ] || 'user' ,
116- } ,
117- draft : false ,
118- overrideAccess : true ,
119- } )
120- console . log ( `Updated Payload user role for ${ payloadUser . email } to ${ permissions } ` ) ;
121- }
122-
123- return { method : 'bearer' , ...payloadUser }
124- } else {
125- return null ;
126- }
12783 }
84+
85+ const session = await verifySession ( req ) ;
86+ if ( ! session ?. sub || ! session . extra ) throw createAuthError ( "No valid session found" , 401 ) ;
87+
88+ const OAUTH_CLIENT_ID = process . env . OAUTH_CLIENT_ID ! ;
89+ const permissions = ( ( session . resource_access as Record < string , { roles ?: string [ ] } > ) ?. [ OAUTH_CLIENT_ID ] ?. roles as string [ ] | undefined ) ;
90+ if ( ! permissions ) throw createAuthError ( "User does not have permission to access this application." , 403 ) ;
91+
92+ if ( ! payload ) throw createAuthError ( "Payload instance is required for Keycloak user normalisation" , 500 ) ;
93+
94+ const payloadUser = ( await payload . find ( {
95+ collection : 'users' ,
96+ depth : 1 ,
97+ limit : 1 ,
98+ draft : false ,
99+ overrideAccess : true ,
100+ where : { email : { equals : session . extra . email } }
101+ } ) ) . docs [ 0 ] ;
102+
103+ const role = getValidRole ( permissions ) ;
104+
105+ if ( ! payloadUser ) {
106+ const newUser = await payload . create ( {
107+ collection : 'users' ,
108+ data : {
109+ email : session . extra . email ,
110+ name : session . extra . name ,
111+ role,
112+ enabled : true ,
113+ accounts : [ { provider : 'keycloak' , providerAccountId : session . sub , type : 'oidc' } ] ,
114+ } ,
115+ draft : false ,
116+ overrideAccess : true ,
117+ } ) ;
118+ console . log ( "Created new Payload user for Keycloak user:" , newUser . id , newUser . email ) ;
119+ return { method : 'bearer' , ...newUser } ;
120+ }
121+
122+ if ( payloadUser . role !== role ) {
123+ await payload . update ( {
124+ collection : 'users' ,
125+ id : payloadUser . id ,
126+ data : { role } ,
127+ draft : false ,
128+ overrideAccess : true ,
129+ } ) ;
130+ console . log ( `Updated Payload user role for ${ payloadUser . email } to ${ role } ` ) ;
131+ }
132+
133+ return { method : 'bearer' , ...payloadUser } ;
128134}
129135
130136export async function authenticateRequestHeaders ( { headers, payload } : { headers : Headers , payload : Payload } ) {
131- if ( ! headers . get ( 'authorization' ) ) {
132- return null
133- }
137+ const authHeader = headers . get ( 'authorization' ) ;
138+ if ( ! authHeader ) return null ;
134139
135- const session = await verifyToken ( headers . get ( 'authorization' ) ! . replace ( 'Bearer ' , '' ) ) ;
140+ const session = await verifyToken ( authHeader . replace ( 'Bearer ' , '' ) ) ;
141+ if ( ! session ?. sub || ! session . extra ) throw createAuthError ( "No valid session found" , 401 ) ;
136142
137- if ( ! session || ! session . sub || ! session . extra ) throw createAuthError ( "No valid session found" , 401 ) ;
138143 const OAUTH_CLIENT_ID = process . env . OAUTH_CLIENT_ID ! ;
139144 const permissions = ( ( session . resource_access as Record < string , { roles ?: string [ ] } > ) ?. [ OAUTH_CLIENT_ID ] ?. roles as string [ ] | undefined ) ;
140145 if ( ! permissions ) throw createAuthError ( "User does not have permission to access this application." , 403 ) ;
141146
142147 if ( ! payload ) throw createAuthError ( "Payload instance is required for Keycloak user normalisation" , 500 ) ;
143- const payloadUser = ( await payload . find ( { collection : 'users' , depth : 1 , limit : 1 , draft : false , overrideAccess : true , where : { email : { equals : session . extra . email } } } ) ) . docs [ 0 ]
144-
145- if ( ! payloadUser && session . extra ) {
146- // create the user in Payload
147- const newUser = await payload . create ( {
148- collection : 'users' ,
149- data : {
150- email : session . extra . email ,
151- name : session . extra . name ,
152- role : permissions [ 0 ] || 'user' ,
153- enabled : true ,
154- accounts : [
155- {
156- provider : 'keycloak' , providerAccountId : session . sub , type : 'oidc' ,
157- }
158- ] ,
159- } ,
160- draft : false ,
161- overrideAccess : true ,
162- } )
163- console . log ( "Created new Payload user for Keycloak user:" , newUser . id , newUser . email )
164- return { user : { ...newUser , collection : 'users' as const } }
165-
166- } else if ( payloadUser ) {
167- // update user role if changed
168- if ( payloadUser . role !== permissions [ 0 ] ) {
169- await payload . update ( {
170- collection : 'users' ,
171- id : payloadUser . id ,
172- data : {
173- role : permissions [ 0 ] || 'user' ,
174- } ,
175- draft : false ,
176- overrideAccess : true ,
177- } )
178- console . log ( `Updated Payload user role for ${ payloadUser . email } to ${ permissions } ` ) ;
179- }
180148
181- return { user : { ...payloadUser , collection : 'users' as const } }
149+ const payloadUser = ( await payload . find ( {
150+ collection : 'users' ,
151+ depth : 1 ,
152+ limit : 1 ,
153+ draft : false ,
154+ overrideAccess : true ,
155+ where : { email : { equals : session . extra . email } }
156+ } ) ) . docs [ 0 ] ;
157+
158+ const role = getValidRole ( permissions ) ;
159+
160+ if ( ! payloadUser ) {
161+ const newUser = await payload . create ( {
162+ collection : 'users' ,
163+ data : {
164+ email : session . extra . email ,
165+ name : session . extra . name ,
166+ role,
167+ enabled : true ,
168+ accounts : [ { provider : 'keycloak' , providerAccountId : session . sub , type : 'oidc' } ] ,
169+ } ,
170+ draft : false ,
171+ overrideAccess : true ,
172+ } ) ;
173+ console . log ( "Created new Payload user for Keycloak user:" , newUser . id , newUser . email ) ;
174+ return { user : { ...newUser , collection : 'users' as const } } ;
175+ }
182176
183- } else {
184- return null ;
177+ if ( payloadUser . role !== role ) {
178+ await payload . update ( {
179+ collection : 'users' ,
180+ id : payloadUser . id ,
181+ data : { role } ,
182+ draft : false ,
183+ overrideAccess : true ,
184+ } ) ;
185+ console . log ( `Updated Payload user role for ${ payloadUser . email } to ${ role } ` ) ;
185186 }
187+
188+ return { user : { ...payloadUser , collection : 'users' as const } } ;
186189}
0 commit comments