Merge pull request #13791 from reasonerjt/oidc-redirect-extra-parm

Add extra parms when forming redirect URI for OIDC
This commit is contained in:
stonezdj(Daojun Zhang) 2020-12-22 21:45:53 +08:00 committed by GitHub
commit bc0b6b43ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 75 additions and 25 deletions

View File

@ -144,6 +144,7 @@ var (
{Name: common.OIDCUserClaim, Scope: UserScope, Group: OIDCGroup, ItemType: &StringType{}},
{Name: common.OIDCVerifyCert, Scope: UserScope, Group: OIDCGroup, DefaultValue: "true", ItemType: &BoolType{}},
{Name: common.OIDCAutoOnboard, Scope: UserScope, Group: OIDCGroup, DefaultValue: "false", ItemType: &BoolType{}},
{Name: common.OIDCExtraRedirectParms, Scope: UserScope, Group: OIDCGroup, DefaultValue: "{}", ItemType: &StringToStringMapType{}},
{Name: common.WithChartMuseum, Scope: SystemScope, Group: BasicGroup, EnvKey: "WITH_CHARTMUSEUM", DefaultValue: "false", ItemType: &BoolType{}, Editable: true},
{Name: common.WithTrivy, Scope: SystemScope, Group: BasicGroup, EnvKey: "WITH_TRIVY", DefaultValue: "false", ItemType: &BoolType{}, Editable: true},

View File

@ -189,6 +189,22 @@ func (t *MapType) get(str string) (interface{}, error) {
return result, err
}
// StringToStringMapType ...
type StringToStringMapType struct {
}
func (t *StringToStringMapType) validate(str string) error {
result := map[string]string{}
err := json.Unmarshal([]byte(str), &result)
return err
}
func (t *StringToStringMapType) get(str string) (interface{}, error) {
result := map[string]string{}
err := json.Unmarshal([]byte(str), &result)
return result, err
}
// QuotaType ...
type QuotaType struct {
Int64Type

View File

@ -98,6 +98,18 @@ func TestMapType_get(t *testing.T) {
assert.Equal(t, map[string]interface{}{"sample": "abc", "another": "welcome"}, result)
}
func TestStringToStringMapType_validate(t *testing.T) {
test := &StringToStringMapType{}
assert.Nil(t, test.validate(`{"sample":"abc", "another":"welcome"}`))
assert.NotNil(t, test.validate(`{"sample":"abc", "another":123}`))
}
func TestStringToStringMapType_get(t *testing.T) {
test := &StringToStringMapType{}
result, _ := test.get(`{"sample":"abc", "another":"welcome"}`)
assert.Equal(t, map[string]string{"sample": "abc", "another": "welcome"}, result)
}
func Test_parseInt64(t *testing.T) {
type args struct {
str string

View File

@ -108,6 +108,7 @@ const (
OIDCAdminGroup = "oidc_admin_group"
OIDCGroupsClaim = "oidc_groups_claim"
OIDCAutoOnboard = "oidc_auto_onboard"
OIDCExtraRedirectParms = "oidc_extra_redirect_parms"
OIDCScope = "oidc_scope"
OIDCUserClaim = "oidc_user_claim"

View File

@ -79,17 +79,18 @@ type HTTPAuthProxy struct {
// OIDCSetting wraps the settings for OIDC auth endpoint
type OIDCSetting struct {
Name string `json:"name"`
Endpoint string `json:"endpoint"`
VerifyCert bool `json:"verify_cert"`
AutoOnboard bool `json:"auto_onboard"`
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
GroupsClaim string `json:"groups_claim"`
AdminGroup string `json:"admin_group"`
RedirectURL string `json:"redirect_url"`
Scope []string `json:"scope"`
UserClaim string `json:"user_claim"`
Name string `json:"name"`
Endpoint string `json:"endpoint"`
VerifyCert bool `json:"verify_cert"`
AutoOnboard bool `json:"auto_onboard"`
ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
GroupsClaim string `json:"groups_claim"`
AdminGroup string `json:"admin_group"`
RedirectURL string `json:"redirect_url"`
Scope []string `json:"scope"`
UserClaim string `json:"user_claim"`
ExtraRedirectParms map[string]string `json:"extra_redirect_parms"`
}
// QuotaSetting wraps the settings for Quota

View File

@ -161,10 +161,16 @@ func AuthCodeURL(state string) (string, error) {
log.Errorf("Failed to get OAuth configuration, error: %v", err)
return "", err
}
if strings.HasPrefix(conf.Endpoint.AuthURL, googleEndpoint) { // make sure the refresh token will be returned
return conf.AuthCodeURL(state, oauth2.AccessTypeOffline, oauth2.SetAuthURLParam("prompt", "consent")), nil
var options []oauth2.AuthCodeOption
setting := provider.setting.Load().(models.OIDCSetting)
for k, v := range setting.ExtraRedirectParms {
options = append(options, oauth2.SetAuthURLParam(k, v))
}
return conf.AuthCodeURL(state), nil
if strings.HasPrefix(conf.Endpoint.AuthURL, googleEndpoint) { // make sure the refresh token will be returned
options = append(options, oauth2.AccessTypeOffline)
options = append(options, oauth2.SetAuthURLParam("prompt", "consent"))
}
return conf.AuthCodeURL(state, options...), nil
}
// ExchangeToken get the token from token provider via the code

View File

@ -90,12 +90,24 @@ func TestHelperGet(t *testing.T) {
}
func TestAuthCodeURL(t *testing.T) {
conf := map[string]interface{}{
common.OIDCName: "test",
common.OIDCEndpoint: "https://accounts.google.com",
common.OIDCVerifyCert: "true",
common.OIDCScope: "openid, profile, offline_access",
common.OIDCCLientID: "client",
common.OIDCClientSecret: "secret",
common.ExtEndpoint: "https://harbor.test",
common.OIDCExtraRedirectParms: `{"test_key":"test_value"}`,
}
config.GetCfgManager().UpdateConfig(conf)
res, err := AuthCodeURL("random")
assert.Nil(t, err)
u, err := url.ParseRequestURI(res)
assert.Nil(t, err)
q, err := url.ParseQuery(u.RawQuery)
assert.Nil(t, err)
assert.Equal(t, "test_value", q.Get("test_key"))
assert.Equal(t, "offline", q.Get("access_type"))
assert.False(t, strings.Contains(q.Get("scope"), "offline_access"))
}

View File

@ -408,17 +408,18 @@ func OIDCSetting() (*models.OIDCSetting, error) {
extEndpoint := strings.TrimSuffix(cfgMgr.Get(common.ExtEndpoint).GetString(), "/")
scope := splitAndTrim(scopeStr, ",")
return &models.OIDCSetting{
Name: cfgMgr.Get(common.OIDCName).GetString(),
Endpoint: cfgMgr.Get(common.OIDCEndpoint).GetString(),
VerifyCert: cfgMgr.Get(common.OIDCVerifyCert).GetBool(),
AutoOnboard: cfgMgr.Get(common.OIDCAutoOnboard).GetBool(),
ClientID: cfgMgr.Get(common.OIDCCLientID).GetString(),
ClientSecret: cfgMgr.Get(common.OIDCClientSecret).GetString(),
GroupsClaim: cfgMgr.Get(common.OIDCGroupsClaim).GetString(),
AdminGroup: cfgMgr.Get(common.OIDCAdminGroup).GetString(),
RedirectURL: extEndpoint + common.OIDCCallbackPath,
Scope: scope,
UserClaim: cfgMgr.Get(common.OIDCUserClaim).GetString(),
Name: cfgMgr.Get(common.OIDCName).GetString(),
Endpoint: cfgMgr.Get(common.OIDCEndpoint).GetString(),
VerifyCert: cfgMgr.Get(common.OIDCVerifyCert).GetBool(),
AutoOnboard: cfgMgr.Get(common.OIDCAutoOnboard).GetBool(),
ClientID: cfgMgr.Get(common.OIDCCLientID).GetString(),
ClientSecret: cfgMgr.Get(common.OIDCClientSecret).GetString(),
GroupsClaim: cfgMgr.Get(common.OIDCGroupsClaim).GetString(),
AdminGroup: cfgMgr.Get(common.OIDCAdminGroup).GetString(),
RedirectURL: extEndpoint + common.OIDCCallbackPath,
Scope: scope,
UserClaim: cfgMgr.Get(common.OIDCUserClaim).GetString(),
ExtraRedirectParms: cfgMgr.Get(common.OIDCExtraRedirectParms).GetStringToStringMap(),
}, nil
}