# use the empty string "".
EmailVerifiedClaim: "email_verified"
+ # OpenID claim field contianing the user's preferred
+ # username. If empty, use the mailbox part of the user's email
+ # address.
+ UsernameClaim: ""
+
PAM:
# (Experimental) Use PAM to authenticate users.
Enable: false
# use the empty string "".
EmailVerifiedClaim: "email_verified"
+ # OpenID claim field contianing the user's preferred
+ # username. If empty, use the mailbox part of the user's email
+ # address.
+ UsernameClaim: ""
+
PAM:
# (Experimental) Use PAM to authenticate users.
Enable: false
ClientSecret: cluster.Login.OpenIDConnect.ClientSecret,
EmailClaim: cluster.Login.OpenIDConnect.EmailClaim,
EmailVerifiedClaim: cluster.Login.OpenIDConnect.EmailVerifiedClaim,
+ UsernameClaim: cluster.Login.OpenIDConnect.UsernameClaim,
}
case !wantGoogle && !wantOpenIDConnect && wantSSO && !wantPAM && !wantLDAP:
return &ssoLoginController{railsProxy}
UseGooglePeopleAPI bool // Use Google People API to look up alternate email addresses
EmailClaim string // OpenID claim to use as email address; typically "email"
EmailVerifiedClaim string // If non-empty, ensure claim value is true before accepting EmailClaim; typically "email_verified"
+ UsernameClaim string // If non-empty, use as preferred username
// override Google People API base URL for testing purposes
// (normally empty, set by google pkg to
ret.Email, _ = claims[ctrl.EmailClaim].(string)
}
+ if ctrl.UsernameClaim != "" {
+ ret.Username, _ = claims[ctrl.UsernameClaim].(string)
+ }
+
if !ctrl.UseGooglePeopleAPI {
if ret.Email == "" {
return nil, fmt.Errorf("cannot log in with unverified email address %q", claims[ctrl.EmailClaim])
return nil, errors.New("cannot log in without a verified email address")
}
for ae := range altEmails {
- if ae != ret.Email {
- ret.AlternateEmails = append(ret.AlternateEmails, ae)
- if i := strings.Index(ae, "@"); i > 0 && strings.ToLower(ae[i+1:]) == strings.ToLower(ctrl.Cluster.Users.PreferDomainForUsername) {
+ if ae == ret.Email {
+ continue
+ }
+ ret.AlternateEmails = append(ret.AlternateEmails, ae)
+ if ret.Username == "" {
+ i := strings.Index(ae, "@")
+ if i > 0 && strings.ToLower(ae[i+1:]) == strings.ToLower(ctrl.Cluster.Users.PreferDomainForUsername) {
ret.Username = strings.SplitN(ae[:i], "+", 2)[0]
}
}
"name": s.authName,
"alt_verified": true, // for custom claim tests
"alt_email": "alt_email@example.com", // for custom claim tests
+ "alt_username": "desired-username", // for custom claim tests
})
json.NewEncoder(w).Encode(struct {
AccessToken string `json:"access_token"`
c.Log("=== succeed because email_verified is false but not required")
s.authEmail = "user@oidc.example.com"
s.authEmailVerified = false
+ s.cluster.Login.OpenIDConnect.EmailClaim = "email"
s.cluster.Login.OpenIDConnect.EmailVerifiedClaim = ""
+ s.cluster.Login.OpenIDConnect.UsernameClaim = ""
},
},
{
c.Log("=== fail because email_verified is false and required")
s.authEmail = "user@oidc.example.com"
s.authEmailVerified = false
+ s.cluster.Login.OpenIDConnect.EmailClaim = "email"
s.cluster.Login.OpenIDConnect.EmailVerifiedClaim = "email_verified"
+ s.cluster.Login.OpenIDConnect.UsernameClaim = ""
},
},
{
c.Log("=== succeed because email_verified is false but config uses custom 'verified' claim")
s.authEmail = "user@oidc.example.com"
s.authEmailVerified = false
+ s.cluster.Login.OpenIDConnect.EmailClaim = "email"
s.cluster.Login.OpenIDConnect.EmailVerifiedClaim = "alt_verified"
+ s.cluster.Login.OpenIDConnect.UsernameClaim = ""
},
},
{
s.authEmailVerified = false
s.cluster.Login.OpenIDConnect.EmailClaim = "alt_email"
s.cluster.Login.OpenIDConnect.EmailVerifiedClaim = "alt_verified"
+ s.cluster.Login.OpenIDConnect.UsernameClaim = "alt_username"
},
},
} {
c.Check(token, check.Matches, `v2/zzzzz-gj3su-.{15}/.{32,50}`)
authinfo := getCallbackAuthInfo(c, s.railsSpy)
c.Check(authinfo.Email, check.Equals, trial.expectEmail)
+
+ switch s.cluster.Login.OpenIDConnect.UsernameClaim {
+ case "alt_username":
+ c.Check(authinfo.Username, check.Equals, "desired-username")
+ case "":
+ c.Check(authinfo.Username, check.Equals, "")
+ default:
+ c.Fail() // bad test case
+ }
}
}
ClientSecret string
EmailClaim string
EmailVerifiedClaim string
+ UsernameClaim string
}
PAM struct {
Enable bool