@@ -50,11 +50,14 @@ type FakeIDP struct {
50
50
// clientID to be used by coderd
51
51
clientID string
52
52
clientSecret string
53
- logger slog.Logger
53
+ // externalProviderID is optional to match the provider in coderd for
54
+ // redirectURLs.
55
+ externalProviderID string
56
+ logger slog.Logger
54
57
// externalAuthValidate will be called when the user tries to validate their
55
58
// external auth. The fake IDP will reject any invalid tokens, so this just
56
59
// controls the response payload after a successfully authed token.
57
- externalAuthValidate map [ string ] func (email string , rw http.ResponseWriter , r * http.Request )
60
+ externalAuthValidate func (email string , rw http.ResponseWriter , r * http.Request )
58
61
59
62
// These maps are used to control the state of the IDP.
60
63
// That is the various access tokens, refresh tokens, states, etc.
@@ -197,7 +200,6 @@ func NewFakeIDP(t testing.TB, opts ...FakeIDPOpt) *FakeIDP {
197
200
hookOnRefresh : func (_ string ) error { return nil },
198
201
hookUserInfo : func (email string ) (jwt.MapClaims , error ) { return jwt.MapClaims {}, nil },
199
202
hookValidRedirectURL : func (redirectURL string ) error { return nil },
200
- externalAuthValidate : make (map [string ]func (email string , rw http.ResponseWriter , r * http.Request )),
201
203
}
202
204
203
205
for _ , opt := range opts {
@@ -356,8 +358,8 @@ func (f *FakeIDP) LoginWithClient(t testing.TB, client *codersdk.Client, idToken
356
358
357
359
// ExternalLogin does the oauth2 flow for external auth providers. This requires
358
360
// an authenticated coder client.
359
- func (f * FakeIDP ) ExternalLogin (t testing.TB , client * codersdk.Client , providerID string , opts ... func (r * http.Request )) * http.Response {
360
- coderOauthURL , err := client .URL .Parse (fmt .Sprintf ("/external-auth/%s/callback" , providerID ))
361
+ func (f * FakeIDP ) ExternalLogin (t testing.TB , client * codersdk.Client , opts ... func (r * http.Request )) * http.Response {
362
+ coderOauthURL , err := client .URL .Parse (fmt .Sprintf ("/external-auth/%s/callback" , f . externalProviderID ))
361
363
require .NoError (t , err )
362
364
f .SetRedirect (t , coderOauthURL .String ())
363
365
@@ -713,7 +715,7 @@ func (f *FakeIDP) httpHandler(t testing.TB) http.Handler {
713
715
_ = json .NewEncoder (rw ).Encode (claims )
714
716
}))
715
717
716
- mux .Mount ("/external-auth-validate/{provider-id} " , http .HandlerFunc (func (rw http.ResponseWriter , r * http.Request ) {
718
+ mux .Mount ("/external-auth-validate/" , http .HandlerFunc (func (rw http.ResponseWriter , r * http.Request ) {
717
719
token , err := f .authenticateBearerTokenRequest (t , r )
718
720
f .logger .Info (r .Context (), "http call idp external auth validate" ,
719
721
slog .Error (err ),
@@ -731,14 +733,13 @@ func (f *FakeIDP) httpHandler(t testing.TB) http.Handler {
731
733
return
732
734
}
733
735
734
- id := chi .URLParam (r , "provider-id" )
735
- handle , ok := f .externalAuthValidate [id ]
736
- if ! ok {
737
- t .Errorf ("missing external auth validate handler for %s" , id )
738
- http .Error (rw , fmt .Sprintf ("missing external auth validate handler for %s" , id ), http .StatusBadRequest )
736
+ if f .externalAuthValidate == nil {
737
+ t .Errorf ("missing external auth validate handler" )
738
+ http .Error (rw , "missing external auth validate handler" , http .StatusBadRequest )
739
739
return
740
740
}
741
- handle (email , rw , r )
741
+
742
+ f .externalAuthValidate (email , rw , r )
742
743
}))
743
744
744
745
mux .Handle (keysPath , http .HandlerFunc (func (rw http.ResponseWriter , r * http.Request ) {
@@ -850,7 +851,7 @@ type ExternalAuthConfigOptions struct {
850
851
ValidatePayload func (email string ) interface {}
851
852
852
853
// routes is more advanced usage. This allows the caller to
853
- // completely customize the response. It captures all routes under the /external-auth-validate/{provider-id}/ *
854
+ // completely customize the response. It captures all routes under the /external-auth-validate/*
854
855
// so the caller can do whatever they want and even add routes.
855
856
routes map [string ]func (email string , rw http.ResponseWriter , r * http.Request )
856
857
}
@@ -875,8 +876,8 @@ func (f *FakeIDP) ExternalAuthConfig(t testing.TB, id string, custom *ExternalAu
875
876
if custom == nil {
876
877
custom = & ExternalAuthConfigOptions {}
877
878
}
878
-
879
- f .externalAuthValidate [ id ] = func (email string , rw http.ResponseWriter , r * http.Request ) {
879
+ f . externalProviderID = id
880
+ f .externalAuthValidate = func (email string , rw http.ResponseWriter , r * http.Request ) {
880
881
newPath := strings .TrimPrefix (r .URL .Path , fmt .Sprintf ("/external-auth-validate/%s" , id ))
881
882
switch newPath {
882
883
// /user is ALWAYS supported under the `/` path too.
0 commit comments