@@ -2,6 +2,7 @@ package middleware
2
2
3
3
import (
4
4
"errors"
5
+ "fmt"
5
6
"net/http"
6
7
"net/http/httptest"
7
8
"net/url"
@@ -404,3 +405,194 @@ func TestJWTwithKID(t *testing.T) {
404
405
}
405
406
}
406
407
}
408
+
409
+ func TestJWTConfig_skipper (t * testing.T ) {
410
+ e := echo .New ()
411
+
412
+ e .Use (JWTWithConfig (JWTConfig {
413
+ Skipper : func (context echo.Context ) bool {
414
+ return true // skip everything
415
+ },
416
+ SigningKey : []byte ("secret" ),
417
+ }))
418
+
419
+ isCalled := false
420
+ e .GET ("/" , func (c echo.Context ) error {
421
+ isCalled = true
422
+ return c .String (http .StatusTeapot , "test" )
423
+ })
424
+
425
+ req := httptest .NewRequest (http .MethodGet , "/" , nil )
426
+ res := httptest .NewRecorder ()
427
+ e .ServeHTTP (res , req )
428
+
429
+ assert .Equal (t , http .StatusTeapot , res .Code )
430
+ assert .True (t , isCalled )
431
+ }
432
+
433
+ func TestJWTConfig_BeforeFunc (t * testing.T ) {
434
+ e := echo .New ()
435
+ e .GET ("/" , func (c echo.Context ) error {
436
+ return c .String (http .StatusTeapot , "test" )
437
+ })
438
+
439
+ isCalled := false
440
+ e .Use (JWTWithConfig (JWTConfig {
441
+ BeforeFunc : func (context echo.Context ) {
442
+ isCalled = true
443
+ },
444
+ SigningKey : []byte ("secret" ),
445
+ }))
446
+
447
+ req := httptest .NewRequest (http .MethodGet , "/" , nil )
448
+ req .Header .Set (echo .HeaderAuthorization , DefaultJWTConfig .AuthScheme + " eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ" )
449
+ res := httptest .NewRecorder ()
450
+ e .ServeHTTP (res , req )
451
+
452
+ assert .Equal (t , http .StatusTeapot , res .Code )
453
+ assert .True (t , isCalled )
454
+ }
455
+
456
+ func TestJWTConfig_extractorErrorHandling (t * testing.T ) {
457
+ var testCases = []struct {
458
+ name string
459
+ given JWTConfig
460
+ expectStatusCode int
461
+ }{
462
+ {
463
+ name : "ok, ErrorHandler is executed" ,
464
+ given : JWTConfig {
465
+ SigningKey : []byte ("secret" ),
466
+ ErrorHandler : func (err error ) error {
467
+ return echo .NewHTTPError (http .StatusTeapot , "custom_error" )
468
+ },
469
+ },
470
+ expectStatusCode : http .StatusTeapot ,
471
+ },
472
+ {
473
+ name : "ok, ErrorHandlerWithContext is executed" ,
474
+ given : JWTConfig {
475
+ SigningKey : []byte ("secret" ),
476
+ ErrorHandlerWithContext : func (err error , context echo.Context ) error {
477
+ return echo .NewHTTPError (http .StatusTeapot , "custom_error" )
478
+ },
479
+ },
480
+ expectStatusCode : http .StatusTeapot ,
481
+ },
482
+ }
483
+
484
+ for _ , tc := range testCases {
485
+ t .Run (tc .name , func (t * testing.T ) {
486
+ e := echo .New ()
487
+ e .GET ("/" , func (c echo.Context ) error {
488
+ return c .String (http .StatusNotImplemented , "should not end up here" )
489
+ })
490
+
491
+ e .Use (JWTWithConfig (tc .given ))
492
+
493
+ req := httptest .NewRequest (http .MethodGet , "/" , nil )
494
+ res := httptest .NewRecorder ()
495
+ e .ServeHTTP (res , req )
496
+
497
+ assert .Equal (t , tc .expectStatusCode , res .Code )
498
+ })
499
+ }
500
+ }
501
+
502
+ func TestJWTConfig_parseTokenErrorHandling (t * testing.T ) {
503
+ var testCases = []struct {
504
+ name string
505
+ given JWTConfig
506
+ expectErr string
507
+ }{
508
+ {
509
+ name : "ok, ErrorHandler is executed" ,
510
+ given : JWTConfig {
511
+ SigningKey : []byte ("secret" ),
512
+ ErrorHandler : func (err error ) error {
513
+ return echo .NewHTTPError (http .StatusTeapot , "ErrorHandler: " + err .Error ())
514
+ },
515
+ },
516
+ expectErr : "{\" message\" :\" ErrorHandler: parsing failed\" }\n " ,
517
+ },
518
+ {
519
+ name : "ok, ErrorHandlerWithContext is executed" ,
520
+ given : JWTConfig {
521
+ SigningKey : []byte ("secret" ),
522
+ ErrorHandlerWithContext : func (err error , context echo.Context ) error {
523
+ return echo .NewHTTPError (http .StatusTeapot , "ErrorHandlerWithContext: " + err .Error ())
524
+ },
525
+ },
526
+ expectErr : "{\" message\" :\" ErrorHandlerWithContext: parsing failed\" }\n " ,
527
+ },
528
+ }
529
+
530
+ for _ , tc := range testCases {
531
+ t .Run (tc .name , func (t * testing.T ) {
532
+ e := echo .New ()
533
+ //e.Debug = true
534
+ e .GET ("/" , func (c echo.Context ) error {
535
+ return c .String (http .StatusNotImplemented , "should not end up here" )
536
+ })
537
+
538
+ config := tc .given
539
+ parseTokenCalled := false
540
+ config .ParseTokenFunc = func (auth string , c echo.Context ) (interface {}, error ) {
541
+ parseTokenCalled = true
542
+ return nil , errors .New ("parsing failed" )
543
+ }
544
+ e .Use (JWTWithConfig (config ))
545
+
546
+ req := httptest .NewRequest (http .MethodGet , "/" , nil )
547
+ req .Header .Set (echo .HeaderAuthorization , DefaultJWTConfig .AuthScheme + " eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ" )
548
+ res := httptest .NewRecorder ()
549
+
550
+ e .ServeHTTP (res , req )
551
+
552
+ assert .Equal (t , http .StatusTeapot , res .Code )
553
+ assert .Equal (t , tc .expectErr , res .Body .String ())
554
+ assert .True (t , parseTokenCalled )
555
+ })
556
+ }
557
+ }
558
+
559
+ func TestJWTConfig_custom_ParseTokenFunc_Keyfunc (t * testing.T ) {
560
+ e := echo .New ()
561
+ e .GET ("/" , func (c echo.Context ) error {
562
+ return c .String (http .StatusTeapot , "test" )
563
+ })
564
+
565
+ // example of minimal custom ParseTokenFunc implementation. Allows you to use different versions of `github.com/dgrijalva/jwt-go`
566
+ // with current JWT middleware
567
+ signingKey := []byte ("secret" )
568
+
569
+ config := JWTConfig {
570
+ ParseTokenFunc : func (auth string , c echo.Context ) (interface {}, error ) {
571
+ keyFunc := func (t * jwt.Token ) (interface {}, error ) {
572
+ if t .Method .Alg () != "HS256" {
573
+ return nil , fmt .Errorf ("unexpected jwt signing method=%v" , t .Header ["alg" ])
574
+ }
575
+ return signingKey , nil
576
+ }
577
+
578
+ // claims are of type `jwt.MapClaims` when token is created with `jwt.Parse`
579
+ token , err := jwt .Parse (auth , keyFunc )
580
+ if err != nil {
581
+ return nil , err
582
+ }
583
+ if ! token .Valid {
584
+ return nil , errors .New ("invalid token" )
585
+ }
586
+ return token , nil
587
+ },
588
+ }
589
+
590
+ e .Use (JWTWithConfig (config ))
591
+
592
+ req := httptest .NewRequest (http .MethodGet , "/" , nil )
593
+ req .Header .Set (echo .HeaderAuthorization , DefaultJWTConfig .AuthScheme + " eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9.TJVA95OrM7E2cBab30RMHrHDcEfxjoYZgeFONFh7HgQ" )
594
+ res := httptest .NewRecorder ()
595
+ e .ServeHTTP (res , req )
596
+
597
+ assert .Equal (t , http .StatusTeapot , res .Code )
598
+ }
0 commit comments