Make sure auto-onboard username claim has higher priority

This commit adjust the priority when consolidating data from userinfo
endpoint and id token, making sure the auto-onboard username claim from
ID token has highest priority.

fixes #15504

Signed-off-by: Daniel Jiang <jiangd@vmware.com>
This commit is contained in:
Daniel Jiang 2021-09-21 18:59:11 +08:00
parent 04cd65d179
commit 91131098c3
2 changed files with 129 additions and 81 deletions

View File

@ -126,13 +126,14 @@ type Token struct {
// UserInfo wraps the information that is extracted via token. It will be transformed to data object that is persisted // UserInfo wraps the information that is extracted via token. It will be transformed to data object that is persisted
// in the DB // in the DB
type UserInfo struct { type UserInfo struct {
Issuer string `json:"iss"` Issuer string `json:"iss"`
Subject string `json:"sub"` Subject string `json:"sub"`
Username string `json:"name"` Username string `json:"name"`
Email string `json:"email"` Email string `json:"email"`
Groups []string `json:"groups"` Groups []string `json:"groups"`
AdminGroupMember bool `json:"admin_group_member"` AdminGroupMember bool `json:"admin_group_member"`
hasGroupClaim bool autoOnboardUsername string
hasGroupClaim bool
} }
func getOauthConf() (*oauth2.Config, error) { func getOauthConf() (*oauth2.Config, error) {
@ -291,7 +292,13 @@ func mergeUserInfo(remote, local *UserInfo) *UserInfo {
// Used data from userinfo // Used data from userinfo
Email: remote.Email, Email: remote.Email,
} }
if remote.Username != "" { // priority for username (high to low):
// 1. Username based on the auto onboard claim from ID token
// 2. Username from response of userinfo endpoint
// 3. Username from the default "name" claim from ID token
if local.autoOnboardUsername != "" {
res.Username = local.autoOnboardUsername
} else if remote.Username != "" {
res.Username = remote.Username res.Username = remote.Username
} else { } else {
res.Username = local.Username res.Username = local.Username
@ -348,7 +355,7 @@ func userInfoFromClaims(c claimsProvider, setting cfgModels.OIDCSetting) (*UserI
} }
if username, ok := allClaims[setting.UserClaim].(string); ok { if username, ok := allClaims[setting.UserClaim].(string); ok {
res.Username = username res.autoOnboardUsername = username
} else { } else {
log.Warningf("OIDC. Failed to recover Username from claim. Claim '%s' is invalid or not a string", setting.UserClaim) log.Warningf("OIDC. Failed to recover Username from claim. Claim '%s' is invalid or not a string", setting.UserClaim)
} }

View File

@ -211,12 +211,13 @@ func TestUserInfoFromClaims(t *testing.T) {
AdminGroup: "g1", AdminGroup: "g1",
}, },
expect: &UserInfo{ expect: &UserInfo{
Issuer: "", Issuer: "",
Subject: "", Subject: "",
Username: "Daniel", autoOnboardUsername: "",
Email: "daniel@gmail.com", Username: "Daniel",
Groups: []string{}, Email: "daniel@gmail.com",
hasGroupClaim: false, Groups: []string{},
hasGroupClaim: false,
}, },
}, },
{ {
@ -232,13 +233,14 @@ func TestUserInfoFromClaims(t *testing.T) {
AdminGroup: "g1", AdminGroup: "g1",
}, },
expect: &UserInfo{ expect: &UserInfo{
Issuer: "", Issuer: "",
Subject: "", Subject: "",
Username: "Daniel", autoOnboardUsername: "",
Email: "daniel@gmail.com", Username: "Daniel",
Groups: []string{"g1", "g2"}, Email: "daniel@gmail.com",
AdminGroupMember: true, Groups: []string{"g1", "g2"},
hasGroupClaim: true, AdminGroupMember: true,
hasGroupClaim: true,
}, },
}, },
{ {
@ -256,13 +258,14 @@ func TestUserInfoFromClaims(t *testing.T) {
AdminGroup: "g1", AdminGroup: "g1",
}, },
expect: &UserInfo{ expect: &UserInfo{
Issuer: "issuer", Issuer: "issuer",
Subject: "subject000", Subject: "subject000",
Username: "jack", autoOnboardUsername: "",
Email: "jack@gmail.com", Username: "jack",
Groups: []string{}, Email: "jack@gmail.com",
hasGroupClaim: true, Groups: []string{},
AdminGroupMember: false, hasGroupClaim: true,
AdminGroupMember: false,
}, },
}, },
{ {
@ -278,13 +281,14 @@ func TestUserInfoFromClaims(t *testing.T) {
AdminGroup: "g1", AdminGroup: "g1",
}, },
expect: &UserInfo{ expect: &UserInfo{
Issuer: "", Issuer: "",
Subject: "", Subject: "",
Username: "airadier@gmail.com", autoOnboardUsername: "airadier@gmail.com",
Email: "airadier@gmail.com", Username: "Alvaro",
Groups: []string{}, Email: "airadier@gmail.com",
hasGroupClaim: false, Groups: []string{},
AdminGroupMember: false, hasGroupClaim: false,
AdminGroupMember: false,
}, },
}, },
} }
@ -303,20 +307,22 @@ func TestMergeUserInfo(t *testing.T) {
}{ }{
{ {
fromInfo: &UserInfo{ fromInfo: &UserInfo{
Issuer: "", Issuer: "",
Subject: "", Subject: "",
Username: "daniel", autoOnboardUsername: "",
Email: "daniel@gmail.com", Username: "daniel",
Groups: []string{}, Email: "daniel@gmail.com",
hasGroupClaim: false, Groups: []string{},
hasGroupClaim: false,
}, },
fromIDToken: &UserInfo{ fromIDToken: &UserInfo{
Issuer: "issuer-google", Issuer: "issuer-google",
Subject: "subject-daniel", Subject: "subject-daniel",
Username: "daniel", autoOnboardUsername: "",
Email: "daniel@yahoo.com", Username: "daniel",
Groups: []string{"developers", "everyone"}, Email: "daniel@yahoo.com",
hasGroupClaim: true, Groups: []string{"developers", "everyone"},
hasGroupClaim: true,
}, },
expected: &UserInfo{ expected: &UserInfo{
Issuer: "issuer-google", Issuer: "issuer-google",
@ -329,20 +335,22 @@ func TestMergeUserInfo(t *testing.T) {
}, },
{ {
fromInfo: &UserInfo{ fromInfo: &UserInfo{
Issuer: "", Issuer: "",
Subject: "", Subject: "",
Username: "tom", autoOnboardUsername: "",
Email: "tom@gmail.com", Username: "tom",
Groups: nil, Email: "tom@gmail.com",
hasGroupClaim: false, Groups: nil,
hasGroupClaim: false,
}, },
fromIDToken: &UserInfo{ fromIDToken: &UserInfo{
Issuer: "issuer-okta", Issuer: "issuer-okta",
Subject: "subject-jiangtan", Subject: "subject-jiangtan",
Username: "tom", autoOnboardUsername: "",
Email: "tom@okta.com", Username: "tom",
Groups: []string{"nouse"}, Email: "tom@okta.com",
hasGroupClaim: false, Groups: []string{"nouse"},
hasGroupClaim: false,
}, },
expected: &UserInfo{ expected: &UserInfo{
Issuer: "issuer-okta", Issuer: "issuer-okta",
@ -355,20 +363,22 @@ func TestMergeUserInfo(t *testing.T) {
}, },
{ {
fromInfo: &UserInfo{ fromInfo: &UserInfo{
Issuer: "", Issuer: "",
Subject: "", Subject: "",
Username: "jim", autoOnboardUsername: "",
Email: "jim@gmail.com", Username: "jim",
Groups: []string{}, Email: "jim@gmail.com",
hasGroupClaim: true, Groups: []string{},
hasGroupClaim: true,
}, },
fromIDToken: &UserInfo{ fromIDToken: &UserInfo{
Issuer: "issuer-yahoo", Issuer: "issuer-yahoo",
Subject: "subject-jim", Subject: "subject-jim",
Username: "jim", autoOnboardUsername: "",
Email: "jim@yaoo.com", Username: "jim",
Groups: []string{"g1", "g2"}, Email: "jim@yaoo.com",
hasGroupClaim: true, Groups: []string{"g1", "g2"},
hasGroupClaim: true,
}, },
expected: &UserInfo{ expected: &UserInfo{
Issuer: "issuer-yahoo", Issuer: "issuer-yahoo",
@ -381,14 +391,24 @@ func TestMergeUserInfo(t *testing.T) {
}, },
{ {
fromInfo: &UserInfo{ fromInfo: &UserInfo{
Issuer: "", Issuer: "",
Subject: "", Subject: "",
Username: "", autoOnboardUsername: "",
Email: "kevin@whatever.com", Username: "",
Groups: []string{}, Email: "kevin@whatever.com",
hasGroupClaim: false, Groups: []string{},
hasGroupClaim: false,
}, },
fromIDToken: &UserInfo{ fromIDToken: &UserInfo{
Issuer: "issuer-whatever",
Subject: "subject-kevin",
autoOnboardUsername: "",
Username: "kevin",
Email: "kevin@whatever.com",
Groups: []string{"g1", "g2"},
hasGroupClaim: true,
},
expected: &UserInfo{
Issuer: "issuer-whatever", Issuer: "issuer-whatever",
Subject: "subject-kevin", Subject: "subject-kevin",
Username: "kevin", Username: "kevin",
@ -396,11 +416,32 @@ func TestMergeUserInfo(t *testing.T) {
Groups: []string{"g1", "g2"}, Groups: []string{"g1", "g2"},
hasGroupClaim: true, hasGroupClaim: true,
}, },
},
{
fromInfo: &UserInfo{
Issuer: "",
Subject: "",
// only the auto onboard username from token will be used
autoOnboardUsername: "info-jt",
Username: "",
Email: "jt@whatever.com",
Groups: []string{},
hasGroupClaim: false,
},
fromIDToken: &UserInfo{
Issuer: "issuer-whatever",
Subject: "subject-jt",
autoOnboardUsername: "token-jt",
Username: "jt",
Email: "jt@whatever.com",
Groups: []string{"g1", "g2"},
hasGroupClaim: true,
},
expected: &UserInfo{ expected: &UserInfo{
Issuer: "issuer-whatever", Issuer: "issuer-whatever",
Subject: "subject-kevin", Subject: "subject-jt",
Username: "kevin", Username: "token-jt",
Email: "kevin@whatever.com", Email: "jt@whatever.com",
Groups: []string{"g1", "g2"}, Groups: []string{"g1", "g2"},
hasGroupClaim: true, hasGroupClaim: true,
}, },