Skip to content

Commit b95ce94

Browse files
authored
connector/oidc: allow overriding userinfo and device auth URLs (#4897)
The OIDC connector can already override the token, auth and JWKS URLs discovered from .well-known/openid-configuration, but not the userinfo or device authorization endpoints. This is a problem when a provider advertises those endpoints incorrectly (e.g. https where only http is reachable) and the discovery document can't be changed. Add userInfoURL and deviceAuthURL to providerDiscoveryOverrides and apply them in getProvider, mirroring the existing overrides. Closes #4110 Signed-off-by: Kunalbehbud <b.kunal2002@gmail.com>
1 parent 5e0dc1e commit b95ce94

2 files changed

Lines changed: 49 additions & 1 deletion

File tree

connector/oidc/oidc.go

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -136,13 +136,19 @@ type ProviderDiscoveryOverrides struct {
136136
// JWKSURL provides a way to user overwrite the JWKS URL
137137
// from the .well-known/openid-configuration jwks_uri
138138
JWKSURL string `json:"jwksURL"`
139+
// UserInfoURL provides a way to override the UserInfo URL
140+
// from the .well-known/openid-configuration userinfo_endpoint
141+
UserInfoURL string `json:"userInfoURL"`
142+
// DeviceAuthURL provides a way to override the Device Authorization URL
143+
// from the .well-known/openid-configuration device_authorization_endpoint
144+
DeviceAuthURL string `json:"deviceAuthURL"`
139145
// EndSessionURL provides a way to override the end_session_endpoint
140146
// from the .well-known/openid-configuration
141147
EndSessionURL string `json:"endSessionURL"`
142148
}
143149

144150
func (o *ProviderDiscoveryOverrides) Empty() bool {
145-
return o.TokenURL == "" && o.AuthURL == "" && o.JWKSURL == "" && o.EndSessionURL == ""
151+
return o.TokenURL == "" && o.AuthURL == "" && o.JWKSURL == "" && o.UserInfoURL == "" && o.DeviceAuthURL == "" && o.EndSessionURL == ""
146152
}
147153

148154
func getProvider(ctx context.Context, issuer string, overrides ProviderDiscoveryOverrides) (*oidc.Provider, error) {
@@ -186,6 +192,12 @@ func getProvider(ctx context.Context, issuer string, overrides ProviderDiscovery
186192
if overrides.JWKSURL != "" {
187193
config.JWKSURL = overrides.JWKSURL
188194
}
195+
if overrides.UserInfoURL != "" {
196+
config.UserInfoURL = overrides.UserInfoURL
197+
}
198+
if overrides.DeviceAuthURL != "" {
199+
config.DeviceAuthURL = overrides.DeviceAuthURL
200+
}
189201
return config.NewProvider(context.Background()), nil
190202
}
191203

connector/oidc/oidc_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -833,6 +833,42 @@ func TestProviderOverride(t *testing.T) {
833833
t.Fatalf("unexpected token URL: %s, expected: %s\n", conn.provider.Endpoint().TokenURL, expToken)
834834
}
835835
})
836+
837+
t.Run("Override userinfo and device auth URLs", func(t *testing.T) {
838+
// A second server whose userinfo endpoint returns a distinct subject,
839+
// so we can prove the overridden endpoint (not the discovery default)
840+
// is the one actually used.
841+
overrideServer, err := setupServer(map[string]any{"sub": "override-sub"}, true)
842+
if err != nil {
843+
t.Fatal("failed to setup override server", err)
844+
}
845+
defer overrideServer.Close()
846+
847+
conn, err := newConnector(Config{
848+
Issuer: testServer.URL,
849+
Scopes: []string{"openid", "groups"},
850+
ProviderDiscoveryOverrides: ProviderDiscoveryOverrides{
851+
DeviceAuthURL: "/test-device",
852+
UserInfoURL: fmt.Sprintf("%s/userinfo", overrideServer.URL),
853+
},
854+
})
855+
if err != nil {
856+
t.Fatal("failed to create new connector", err)
857+
}
858+
859+
expDevice := "/test-device"
860+
if conn.provider.Endpoint().DeviceAuthURL != expDevice {
861+
t.Fatalf("unexpected device auth URL: %s, expected: %s\n", conn.provider.Endpoint().DeviceAuthURL, expDevice)
862+
}
863+
864+
userInfo, err := conn.provider.UserInfo(context.Background(), oauth2.StaticTokenSource(&oauth2.Token{AccessToken: "sometoken"}))
865+
if err != nil {
866+
t.Fatal("failed to call UserInfo", err)
867+
}
868+
if userInfo.Subject != "override-sub" {
869+
t.Fatalf("UserInfo did not use the overridden endpoint: got subject %q, expected %q", userInfo.Subject, "override-sub")
870+
}
871+
})
836872
}
837873

838874
func setupServer(tok map[string]interface{}, idTokenDesired bool) (*httptest.Server, error) {

0 commit comments

Comments
 (0)