@@ -60,9 +60,13 @@ type FakeIDP struct {
60
60
refreshIDTokenClaims * SyncMap [string , jwt.MapClaims ]
61
61
62
62
// hooks
63
- hookUserInfo func (email string ) jwt.MapClaims
64
- fakeCoderd func (req * http.Request ) (* http.Response , error )
65
- hookOnRefresh func (email string ) error
63
+ // hookValidRedirectURL can be used to reject a redirect url from the
64
+ // IDP -> Application. Almost all IDPs have the concept of
65
+ // "Authorized Redirect URLs". This can be used to emulate that.
66
+ hookValidRedirectURL func (redirectURL string ) error
67
+ hookUserInfo func (email string ) jwt.MapClaims
68
+ fakeCoderd func (req * http.Request ) (* http.Response , error )
69
+ hookOnRefresh func (email string ) error
66
70
// Custom authentication for the client. This is useful if you want
67
71
// to test something like PKI auth vs a client_secret.
68
72
hookAuthenticateClient func (t testing.TB , req * http.Request ) (url.Values , error )
@@ -74,6 +78,12 @@ type FakeIDP struct {
74
78
75
79
type FakeIDPOpt func (idp * FakeIDP )
76
80
81
+ func WithAuthorizedRedirectURL (hook func (redirectURL string ) error ) func (* FakeIDP ) {
82
+ return func (f * FakeIDP ) {
83
+ f .hookValidRedirectURL = hook
84
+ }
85
+ }
86
+
77
87
// WithRefreshHook is called when a refresh token is used. The email is
78
88
// the email of the user that is being refreshed assuming the claims are correct.
79
89
func WithRefreshHook (hook func (email string ) error ) func (* FakeIDP ) {
@@ -421,6 +431,8 @@ func (f *FakeIDP) httpHandler(t testing.TB) http.Handler {
421
431
// This endpoint is required to initialize the OIDC provider.
422
432
// It is used to get the OIDC configuration.
423
433
mux .Get ("/.well-known/openid-configuration" , func (rw http.ResponseWriter , r * http.Request ) {
434
+ f .logger .Info (r .Context (), "HTTP OIDC Config" , slog .F ("url" , r .URL .String ()))
435
+
424
436
_ = json .NewEncoder (rw ).Encode (f .provider )
425
437
})
426
438
@@ -429,19 +441,19 @@ func (f *FakeIDP) httpHandler(t testing.TB) http.Handler {
429
441
// w/e and clicking "Allow". They will be redirected back to the redirect
430
442
// when this is done.
431
443
mux .Handle (authorizePath , http .HandlerFunc (func (rw http.ResponseWriter , r * http.Request ) {
432
- f .logger .Info (r .Context (), "HTTP Call Authorize" , slog .F ("url" , string ( r .URL .String () )))
444
+ f .logger .Info (r .Context (), "HTTP Call Authorize" , slog .F ("url" , r .URL .String ()))
433
445
434
446
clientID := r .URL .Query ().Get ("client_id" )
435
- if clientID != f .clientID {
436
- t .Errorf ("unexpected client_id %q" , clientID )
447
+ if ! assert .Equal (t , f .clientID , clientID , "unexpected client_id" ) {
437
448
http .Error (rw , "invalid client_id" , http .StatusBadRequest )
449
+ return
438
450
}
439
451
440
452
redirectURI := r .URL .Query ().Get ("redirect_uri" )
441
453
state := r .URL .Query ().Get ("state" )
442
454
443
455
scope := r .URL .Query ().Get ("scope" )
444
- _ = scope
456
+ assert . NotEmpty ( t , scope , " scope is empty" )
445
457
446
458
responseType := r .URL .Query ().Get ("response_type" )
447
459
switch responseType {
@@ -456,10 +468,17 @@ func (f *FakeIDP) httpHandler(t testing.TB) http.Handler {
456
468
return
457
469
}
458
470
471
+ err := f .hookValidRedirectURL (redirectURI )
472
+ if err != nil {
473
+ t .Errorf ("not authorized redirect_uri by custom hook %q: %s" , redirectURI , err .Error ())
474
+ http .Error (rw , fmt .Sprintf ("invalid redirect_uri: %s" , err .Error ()), http .StatusBadRequest )
475
+ return
476
+ }
477
+
459
478
ru , err := url .Parse (redirectURI )
460
479
if err != nil {
461
- t .Errorf ("invalid redirect_uri %q" , redirectURI )
462
- http .Error (rw , "invalid redirect_uri" , http .StatusBadRequest )
480
+ t .Errorf ("invalid redirect_uri %q: %s " , redirectURI , err . Error () )
481
+ http .Error (rw , fmt . Sprintf ( "invalid redirect_uri: %s" , err . Error ()) , http .StatusBadRequest )
463
482
return
464
483
}
465
484
@@ -573,6 +592,7 @@ func (f *FakeIDP) httpHandler(t testing.TB) http.Handler {
573
592
token , err := f .authenticateBearerTokenRequest (t , r )
574
593
f .logger .Info (r .Context (), "HTTP Call UserInfo" ,
575
594
slog .Error (err ),
595
+ slog .F ("url" , r .URL .String ()),
576
596
)
577
597
if err != nil {
578
598
http .Error (rw , fmt .Sprintf ("invalid user info request: %s" , err .Error ()), http .StatusBadRequest )
0 commit comments