Merge pull request #61508 from rithujohn191/email_verified

Automatic merge from submit-queue (batch tested with PRs 61806, 61508, 62075, 62079, 62052). If you want to cherry-pick this change to another branch, please follow the instructions <a href="https://github.com/kubernetes/community/blob/master/contributors/devel/cherry-picks.md">here</a>.

oidc authentication: email_verified claim is not required for JWT validation

**What this PR does / why we need it**:
Currently the "email_verified" claim is required by the API server to verify an OIDC token. Many OIDC providers do not support the "email_verified" claim. We want to be able to allow their OIDC tokens as valid.

**Which issue(s) this PR fixes** *(optional, in `fixes #<issue number>(, fixes #<issue_number>, ...)` format, will close the issue(s) when PR gets merged)*:
Fixes #59496

**Release note**:

```release-note
OIDC authentication now allows tokens without an "email_verified" claim when using the "email" claim. If an "email_verified" claim is present when using the "email" claim, it must be `true`.
```
/sig auth
/kind feature
/assign @ericchiang 

CC: @sreetummidi
This commit is contained in:
Kubernetes Submit Queue 2018-04-03 17:24:24 -07:00 committed by GitHub
commit 8201b3eb7f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 43 additions and 8 deletions

View File

@ -284,14 +284,18 @@ func (a *Authenticator) AuthenticateToken(token string) (user.Info, bool, error)
}
if a.usernameClaim == "email" {
// Check the email_verified claim to ensure the email is valid.
// If the email_verified claim is present, ensure the email is valid.
// https://openid.net/specs/openid-connect-core-1_0.html#StandardClaims
var emailVerified bool
if err := c.unmarshalClaim("email_verified", &emailVerified); err != nil {
return nil, false, fmt.Errorf("oidc: parse 'email_verified' claim: %v", err)
}
if !emailVerified {
return nil, false, fmt.Errorf("oidc: email not verified")
if hasEmailVerified := c.hasClaim("email_verified"); hasEmailVerified {
var emailVerified bool
if err := c.unmarshalClaim("email_verified", &emailVerified); err != nil {
return nil, false, fmt.Errorf("oidc: parse 'email_verified' claim: %v", err)
}
// If the email_verified claim is present we have to verify it is set to `true`.
if !emailVerified {
return nil, false, fmt.Errorf("oidc: email not verified")
}
}
}
@ -347,3 +351,10 @@ func (c claims) unmarshalClaim(name string, v interface{}) error {
}
return json.Unmarshal([]byte(val), v)
}
func (c claims) hasClaim(name string) bool {
if _, ok := c[name]; !ok {
return false
}
return true
}

View File

@ -287,7 +287,7 @@ func TestToken(t *testing.T) {
wantErr: true,
},
{
// If "email_verified" isn't present, assume false
// If "email_verified" isn't present, assume true
name: "no-email-verified-claim",
options: Options{
IssuerURL: "https://auth.example.com",
@ -305,6 +305,30 @@ func TestToken(t *testing.T) {
"email": "jane@example.com",
"exp": %d
}`, valid.Unix()),
want: &user.DefaultInfo{
Name: "jane@example.com",
},
},
{
name: "invalid-email-verified-claim",
options: Options{
IssuerURL: "https://auth.example.com",
ClientID: "my-client",
UsernameClaim: "email",
now: func() time.Time { return now },
},
signingKey: loadRSAPrivKey(t, "testdata/rsa_1.pem", jose.RS256),
pubKeys: []*jose.JSONWebKey{
loadRSAKey(t, "testdata/rsa_1.pem", jose.RS256),
},
// string value for "email_verified"
claims: fmt.Sprintf(`{
"iss": "https://auth.example.com",
"aud": "my-client",
"email": "jane@example.com",
"email_verified": "false",
"exp": %d
}`, valid.Unix()),
wantErr: true,
},
{