@@ -12,7 +12,9 @@ import { createDatabase, createTables } from '../tests/helpers.js'
1212import { tokensUserProvider } from '@adonisjs/auth/access_tokens'
1313
1414test . group ( 'Jwt guard | authenticate' , ( ) => {
15- test ( 'it should return a jwt token when user is authenticated with refresh token' , async ( { assert } ) => {
15+ test ( 'it should return a jwt token when user is authenticated with refresh token' , async ( {
16+ assert,
17+ } ) => {
1618 const ctx = new HttpContextFactory ( ) . create ( )
1719 const userProvider = new JwtFakeUserProvider ( )
1820
@@ -47,7 +49,7 @@ test.group('Jwt guard | authenticate', () => {
4749 static refreshTokens = DbAccessTokensProvider . forModel ( User , {
4850 prefix : 'rt_' ,
4951 table : 'jwt_refresh_tokens' ,
50- type : 'auth_token ' ,
52+ type : 'jwt_refresh_token ' ,
5153 tokenSecretLength : 40 ,
5254 } )
5355 }
@@ -72,6 +74,312 @@ test.group('Jwt guard | authenticate', () => {
7274 assert . exists ( refreshToken . value ?. release ( ) )
7375 } )
7476
77+ test ( 'throw error when refresh token user provider is not defined' , async ( { assert } ) => {
78+ const ctx = new HttpContextFactory ( ) . create ( )
79+ const userProvider = new JwtFakeUserProvider ( )
80+
81+ const guard = new JwtGuard ( ctx , userProvider , {
82+ secret : 'thisisasecret' ,
83+ } )
84+
85+ const [ result ] = await Promise . allSettled ( [ guard . authenticateWithRefreshToken ( ) ] )
86+ assert . equal ( result ! . status , 'rejected' )
87+ if ( result ! . status === 'rejected' ) {
88+ assert . instanceOf ( result ! . reason , errors . E_UNAUTHORIZED_ACCESS )
89+ }
90+ assert . isUndefined ( guard . user )
91+ assert . throws ( ( ) => guard . getUserOrFail ( ) , 'Unauthorized access' )
92+ assert . isFalse ( guard . isAuthenticated )
93+ assert . isTrue ( guard . authenticationAttempted )
94+ } )
95+
96+ test ( 'throw error when refresh token authorization header is missing' , async ( { assert } ) => {
97+ const ctx = new HttpContextFactory ( ) . create ( )
98+ const userProvider = new JwtFakeUserProvider ( )
99+ const db = await createDatabase ( )
100+ await createTables ( db )
101+
102+ const guard = new JwtGuard ( ctx , userProvider , {
103+ secret : 'thisisasecret' ,
104+ refreshTokenUserProvider : tokensUserProvider ( {
105+ tokens : 'refreshTokens' ,
106+ async model ( ) {
107+ return {
108+ default : User ,
109+ }
110+ } ,
111+ } ) ,
112+ } )
113+
114+ class User extends BaseModel {
115+ @column ( { isPrimary : true } )
116+ declare id : number
117+
118+ @column ( )
119+ declare username : string
120+
121+ @column ( )
122+ declare email : string
123+
124+ @column ( )
125+ declare password : string
126+
127+ static refreshTokens = DbAccessTokensProvider . forModel ( User , {
128+ prefix : 'rt_' ,
129+ table : 'jwt_refresh_tokens' ,
130+ type : 'jwt_refresh_token' ,
131+ tokenSecretLength : 40 ,
132+ } )
133+ }
134+
135+ const [ result ] = await Promise . allSettled ( [ guard . authenticateWithRefreshToken ( ) ] )
136+ assert . equal ( result ! . status , 'rejected' )
137+ if ( result ! . status === 'rejected' ) {
138+ assert . instanceOf ( result ! . reason , errors . E_UNAUTHORIZED_ACCESS )
139+ }
140+ assert . isUndefined ( guard . user )
141+ assert . throws ( ( ) => guard . getUserOrFail ( ) , 'Unauthorized access' )
142+ assert . isFalse ( guard . isAuthenticated )
143+ assert . isTrue ( guard . authenticationAttempted )
144+ } )
145+
146+ test ( 'throw error when refresh token authorization header is invalid' , async ( { assert } ) => {
147+ const ctx = new HttpContextFactory ( ) . create ( )
148+ const userProvider = new JwtFakeUserProvider ( )
149+ const db = await createDatabase ( )
150+ await createTables ( db )
151+
152+ const guard = new JwtGuard ( ctx , userProvider , {
153+ secret : 'thisisasecret' ,
154+ refreshTokenUserProvider : tokensUserProvider ( {
155+ tokens : 'refreshTokens' ,
156+ async model ( ) {
157+ return {
158+ default : User ,
159+ }
160+ } ,
161+ } ) ,
162+ } )
163+
164+ class User extends BaseModel {
165+ @column ( { isPrimary : true } )
166+ declare id : number
167+
168+ @column ( )
169+ declare username : string
170+
171+ @column ( )
172+ declare email : string
173+
174+ @column ( )
175+ declare password : string
176+
177+ static refreshTokens = DbAccessTokensProvider . forModel ( User , {
178+ prefix : 'rt_' ,
179+ table : 'jwt_refresh_tokens' ,
180+ type : 'jwt_refresh_token' ,
181+ tokenSecretLength : 40 ,
182+ } )
183+ }
184+
185+ ctx . request . request . headers . authorization = `foo bar`
186+ const [ result ] = await Promise . allSettled ( [ guard . authenticateWithRefreshToken ( ) ] )
187+ assert . equal ( result ! . status , 'rejected' )
188+ if ( result ! . status === 'rejected' ) {
189+ assert . instanceOf ( result ! . reason , errors . E_UNAUTHORIZED_ACCESS )
190+ }
191+ assert . isUndefined ( guard . user )
192+ assert . throws ( ( ) => guard . getUserOrFail ( ) , 'Unauthorized access' )
193+ assert . isFalse ( guard . isAuthenticated )
194+ assert . isTrue ( guard . authenticationAttempted )
195+ } )
196+
197+ test ( 'throw error if the user authentication attempt has been made already' , async ( {
198+ assert,
199+ } ) => {
200+ const ctx = new HttpContextFactory ( ) . create ( )
201+ const userProvider = new JwtFakeUserProvider ( )
202+ const db = await createDatabase ( )
203+ await createTables ( db )
204+
205+ const guard = new JwtGuard ( ctx , userProvider , {
206+ secret : 'thisisasecret' ,
207+ refreshTokenUserProvider : tokensUserProvider ( {
208+ tokens : 'refreshTokens' ,
209+ async model ( ) {
210+ return {
211+ default : User ,
212+ }
213+ } ,
214+ } ) ,
215+ } )
216+
217+ class User extends BaseModel {
218+ @column ( { isPrimary : true } )
219+ declare id : number
220+
221+ @column ( )
222+ declare username : string
223+
224+ @column ( )
225+ declare email : string
226+
227+ @column ( )
228+ declare password : string
229+
230+ static refreshTokens = DbAccessTokensProvider . forModel ( User , {
231+ prefix : 'rt_' ,
232+ table : 'jwt_refresh_tokens' ,
233+ type : 'jwt_refresh_token' ,
234+ tokenSecretLength : 40 ,
235+ } )
236+ }
237+
238+ const user = await User . create ( {
239+ 240+ username : 'maxime' ,
241+ password : 'password' ,
242+ } )
243+
244+ const refreshToken = await User . refreshTokens . create ( user )
245+
246+ await assert . rejects ( ( ) => guard . authenticate ( ) , 'Unauthorized access' )
247+ ctx . request . request . headers . authorization = `Bearer ${ refreshToken . value ?. release ( ) } `
248+ await assert . rejects ( ( ) => guard . authenticate ( ) , 'Unauthorized access' )
249+ assert . isUndefined ( guard . user )
250+ assert . throws ( ( ) => guard . getUserOrFail ( ) , 'Unauthorized access' )
251+ assert . isFalse ( guard . isAuthenticated )
252+ assert . isTrue ( guard . authenticationAttempted )
253+ } )
254+
255+ test ( 'it should return the user when user is already authenticated with refresh token' , async ( {
256+ assert,
257+ } ) => {
258+ const ctx = new HttpContextFactory ( ) . create ( )
259+ const userProvider = new JwtFakeUserProvider ( )
260+
261+ const db = await createDatabase ( )
262+ await createTables ( db )
263+
264+ const guard = new JwtGuard ( ctx , userProvider , {
265+ secret : 'thisisasecret' ,
266+ refreshTokenUserProvider : tokensUserProvider ( {
267+ tokens : 'refreshTokens' ,
268+ async model ( ) {
269+ return {
270+ default : User ,
271+ }
272+ } ,
273+ } ) ,
274+ } )
275+
276+ class User extends BaseModel {
277+ @column ( { isPrimary : true } )
278+ declare id : number
279+
280+ @column ( )
281+ declare username : string
282+
283+ @column ( )
284+ declare email : string
285+
286+ @column ( )
287+ declare password : string
288+
289+ static refreshTokens = DbAccessTokensProvider . forModel ( User , {
290+ prefix : 'rt_' ,
291+ table : 'jwt_refresh_tokens' ,
292+ type : 'jwt_refresh_token' ,
293+ tokenSecretLength : 40 ,
294+ } )
295+ }
296+
297+ const user = await User . create ( {
298+ 299+ username : 'maxime' ,
300+ password : 'password' ,
301+ } )
302+ const refreshToken = await User . refreshTokens . create ( user )
303+ ctx . request . request . headers . authorization = `Bearer ${ refreshToken . value ?. release ( ) } `
304+ await guard . authenticateWithRefreshToken ( )
305+ const authenticatedUser = await guard . authenticateWithRefreshToken ( )
306+ assert . isTrue ( guard . isAuthenticated )
307+ assert . isTrue ( guard . authenticationAttempted )
308+ assert . equal ( guard . user , authenticatedUser )
309+ assert . deepEqual ( guard . getUserOrFail ( ) , authenticatedUser )
310+ assert . exists ( authenticatedUser . currentToken )
311+ assert . exists ( refreshToken . value ?. release ( ) )
312+ } )
313+
314+ test ( 'throw error when the refresh token used belongs to a unknown user' , async ( { assert } ) => {
315+ const ctx = new HttpContextFactory ( ) . create ( )
316+ const userProvider = new JwtFakeUserProvider ( )
317+ const db = await createDatabase ( )
318+ await createTables ( db )
319+ const guard = new JwtGuard ( ctx , userProvider , {
320+ secret : 'thisisasecret' ,
321+ refreshTokenUserProvider : tokensUserProvider ( {
322+ tokens : 'refreshTokens' ,
323+ async model ( ) {
324+ return {
325+ default : User ,
326+ }
327+ } ,
328+ } ) ,
329+ } )
330+
331+ class User extends BaseModel {
332+ @column ( { isPrimary : true } )
333+ declare id : number
334+
335+ @column ( )
336+ declare username : string
337+
338+ @column ( )
339+ declare email : string
340+
341+ @column ( )
342+ declare password : string
343+
344+ static refreshTokens = DbAccessTokensProvider . forModel ( User , {
345+ prefix : 'rt_' ,
346+ table : 'jwt_refresh_tokens' ,
347+ type : 'jwt_refresh_token' ,
348+ tokenSecretLength : 40 ,
349+ } )
350+ }
351+
352+ await User . createMany ( [
353+ {
354+ 355+ username : 'john' ,
356+ password : 'password' ,
357+ } ,
358+ {
359+ 360+ username : 'jane' ,
361+ password : 'password' ,
362+ } ,
363+ ] )
364+
365+ const user = await User . create ( {
366+ 367+ username : 'maxime' ,
368+ password : 'password' ,
369+ } )
370+ const refreshToken = await User . refreshTokens . create ( user )
371+ ctx . request . request . headers . authorization = `Bearer ${ refreshToken . value ?. release ( ) } `
372+ const [ result ] = await Promise . allSettled ( [ guard . authenticateWithRefreshToken ( ) ] )
373+ assert . equal ( result ! . status , 'rejected' )
374+ if ( result ! . status === 'rejected' ) {
375+ assert . instanceOf ( result ! . reason , errors . E_UNAUTHORIZED_ACCESS )
376+ }
377+ assert . isUndefined ( guard . user )
378+ assert . throws ( ( ) => guard . getUserOrFail ( ) , 'Unauthorized access' )
379+ assert . isFalse ( guard . isAuthenticated )
380+ assert . isTrue ( guard . authenticationAttempted )
381+ } )
382+
75383 test ( 'it should return a token when user is authenticated' , async ( { assert } ) => {
76384 const ctx = new HttpContextFactory ( ) . create ( )
77385 const userProvider = new JwtFakeUserProvider ( )
@@ -414,9 +722,7 @@ test.group('Jwt guard | authenticate', () => {
414722 const ctx = new HttpContextFactory ( ) . create ( )
415723 const userProvider = new JwtFakeUserProvider ( )
416724 const user = await userProvider . findById ( 1 )
417- const token = await userProvider . createToken ( user ! . getOriginal ( ) , 'thisisasecret' , {
418- expiresIn : '1h' ,
419- } )
725+ const token = await userProvider . createToken ( user ! . getOriginal ( ) , 'thisisasecret' )
420726
421727 const guard = new JwtGuard ( ctx , userProvider , { secret : 'thisisasecret' } )
422728 await assert . rejects ( ( ) => guard . authenticate ( ) , 'Unauthorized access' )
0 commit comments