Skip to content

Commit ff67ef5

Browse files
committed
Address review feedback: fix empty scope= and OIDC fallback path
- Replace SetAuthURLParam("scope", "") with temporarily nil-ing oauth2Config.Scopes before AuthCodeURL, then restoring via defer. This omits the scope parameter entirely instead of producing an invalid empty scope= (RFC 6749 §3.3). - Propagate ScopeParamName on the OIDC discovery fallback path in createOAuthConfig, so --remote-auth-scope-param-name works with --remote-auth-issuer as well. - Strengthen test assertion to verify scope parameter is truly absent, not just empty-valued. Signed-off-by: Gustavo Gomez <gmogmz@indeed.com>
1 parent 849326a commit ff67ef5

File tree

3 files changed

+17
-7
lines changed

3 files changed

+17
-7
lines changed

pkg/auth/discovery/discovery.go

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -652,7 +652,7 @@ func createOAuthConfig(ctx context.Context, issuer string, config *OAuthFlowConf
652652

653653
// Fall back to OIDC discovery
654654
slog.Debug("Using OIDC discovery")
655-
return oauth.CreateOAuthConfigFromOIDC(
655+
cfg, err := oauth.CreateOAuthConfigFromOIDC(
656656
ctx,
657657
issuer,
658658
config.ClientID,
@@ -662,6 +662,11 @@ func createOAuthConfig(ctx context.Context, issuer string, config *OAuthFlowConf
662662
config.CallbackPort,
663663
config.Resource,
664664
)
665+
if err != nil {
666+
return nil, err
667+
}
668+
cfg.ScopeParamName = config.ScopeParamName
669+
return cfg, nil
665670
}
666671

667672
func newOAuthFlow(ctx context.Context, oauthConfig *oauth.Config, config *OAuthFlowConfig) (*OAuthFlowResult, error) {

pkg/auth/oauth/flow.go

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -278,12 +278,16 @@ func (f *Flow) buildAuthURL() string {
278278
// When a custom scope parameter name is configured, move scopes from the
279279
// standard "scope" parameter to the custom one. This supports OAuth providers
280280
// that use non-standard parameter names (e.g., Slack's "user_scope").
281-
// The standard "scope" is cleared by setting it to empty; oauth2Config.Scopes
282-
// is preserved so token refresh requests still include scopes correctly.
281+
// We temporarily nil out oauth2Config.Scopes so the library omits the standard
282+
// "scope" parameter entirely (an empty scope= would violate RFC 6749 §3.3).
283+
// Scopes are restored via defer so token refresh requests still work correctly.
283284
if f.config.ScopeParamName != "" && len(f.oauth2Config.Scopes) > 0 {
285+
scopeValue := strings.Join(f.oauth2Config.Scopes, " ")
286+
savedScopes := f.oauth2Config.Scopes
287+
f.oauth2Config.Scopes = nil
288+
defer func() { f.oauth2Config.Scopes = savedScopes }()
284289
opts = append(opts,
285-
oauth2.SetAuthURLParam("scope", ""),
286-
oauth2.SetAuthURLParam(f.config.ScopeParamName, strings.Join(f.oauth2Config.Scopes, " ")),
290+
oauth2.SetAuthURLParam(f.config.ScopeParamName, scopeValue),
287291
)
288292
}
289293

pkg/auth/oauth/flow_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -270,8 +270,9 @@ func TestBuildAuthURL(t *testing.T) {
270270
require.NoError(t, err)
271271

272272
query := parsedURL.Query()
273-
// Standard "scope" should be cleared
274-
assert.Empty(t, query.Get("scope"))
273+
// Standard "scope" parameter should be absent, not empty
274+
_, hasScope := query["scope"]
275+
assert.False(t, hasScope, "scope parameter should be absent, not empty")
275276
// Scopes should appear under the custom parameter name
276277
assert.Contains(t, query.Get("user_scope"), "search:read")
277278
assert.Contains(t, query.Get("user_scope"), "chat:write")

0 commit comments

Comments
 (0)