Adding oidc email scope check
This helps to avoid "no email claim" error if email scope was not specified. Signed-off-by: m.nabokikh <maksim.nabokikh@flant.com>
This commit is contained in:
		| @@ -262,15 +262,25 @@ func (c *oidcConnector) createIdentity(ctx context.Context, identity connector.I | |||||||
| 	if !found { | 	if !found { | ||||||
| 		return identity, fmt.Errorf("missing \"%s\" claim", userNameKey) | 		return identity, fmt.Errorf("missing \"%s\" claim", userNameKey) | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
|  | 	hasEmailScope := false | ||||||
|  | 	for _, s := range c.oauth2Config.Scopes { | ||||||
|  | 		if s == "email" { | ||||||
|  | 			hasEmailScope = true | ||||||
|  | 			break | ||||||
|  | 		} | ||||||
|  | 	} | ||||||
|  |  | ||||||
| 	email, found := claims["email"].(string) | 	email, found := claims["email"].(string) | ||||||
| 	if !found { | 	if !found && hasEmailScope { | ||||||
| 		return identity, errors.New("missing \"email\" claim") | 		return identity, errors.New("missing \"email\" claim") | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	emailVerified, found := claims["email_verified"].(bool) | 	emailVerified, found := claims["email_verified"].(bool) | ||||||
| 	if !found { | 	if !found { | ||||||
| 		if c.insecureSkipEmailVerified { | 		if c.insecureSkipEmailVerified { | ||||||
| 			emailVerified = true | 			emailVerified = true | ||||||
| 		} else { | 		} else if hasEmailScope { | ||||||
| 			return identity, errors.New("missing \"email_verified\" claim") | 			return identity, errors.New("missing \"email_verified\" claim") | ||||||
| 		} | 		} | ||||||
| 	} | 	} | ||||||
|   | |||||||
| @@ -50,16 +50,19 @@ func TestHandleCallback(t *testing.T) { | |||||||
| 		userIDKey                 string | 		userIDKey                 string | ||||||
| 		userNameKey               string | 		userNameKey               string | ||||||
| 		insecureSkipEmailVerified bool | 		insecureSkipEmailVerified bool | ||||||
|  | 		scopes                    []string | ||||||
| 		expectUserID              string | 		expectUserID              string | ||||||
| 		expectUserName            string | 		expectUserName            string | ||||||
|  | 		expectedEmailField        string | ||||||
| 		token                     map[string]interface{} | 		token                     map[string]interface{} | ||||||
| 	}{ | 	}{ | ||||||
| 		{ | 		{ | ||||||
| 			name:           "simpleCase", | 			name:               "simpleCase", | ||||||
| 			userIDKey:      "", // not configured | 			userIDKey:          "", // not configured | ||||||
| 			userNameKey:    "", // not configured | 			userNameKey:        "", // not configured | ||||||
| 			expectUserID:   "subvalue", | 			expectUserID:       "subvalue", | ||||||
| 			expectUserName: "namevalue", | 			expectUserName:     "namevalue", | ||||||
|  | 			expectedEmailField: "emailvalue", | ||||||
| 			token: map[string]interface{}{ | 			token: map[string]interface{}{ | ||||||
| 				"sub":            "subvalue", | 				"sub":            "subvalue", | ||||||
| 				"name":           "namevalue", | 				"name":           "namevalue", | ||||||
| @@ -72,6 +75,7 @@ func TestHandleCallback(t *testing.T) { | |||||||
| 			insecureSkipEmailVerified: true, | 			insecureSkipEmailVerified: true, | ||||||
| 			expectUserID:              "subvalue", | 			expectUserID:              "subvalue", | ||||||
| 			expectUserName:            "namevalue", | 			expectUserName:            "namevalue", | ||||||
|  | 			expectedEmailField:        "emailvalue", | ||||||
| 			token: map[string]interface{}{ | 			token: map[string]interface{}{ | ||||||
| 				"sub":   "subvalue", | 				"sub":   "subvalue", | ||||||
| 				"name":  "namevalue", | 				"name":  "namevalue", | ||||||
| @@ -79,10 +83,11 @@ func TestHandleCallback(t *testing.T) { | |||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			name:           "withUserIDKey", | 			name:               "withUserIDKey", | ||||||
| 			userIDKey:      "name", | 			userIDKey:          "name", | ||||||
| 			expectUserID:   "namevalue", | 			expectUserID:       "namevalue", | ||||||
| 			expectUserName: "namevalue", | 			expectUserName:     "namevalue", | ||||||
|  | 			expectedEmailField: "emailvalue", | ||||||
| 			token: map[string]interface{}{ | 			token: map[string]interface{}{ | ||||||
| 				"sub":            "subvalue", | 				"sub":            "subvalue", | ||||||
| 				"name":           "namevalue", | 				"name":           "namevalue", | ||||||
| @@ -91,10 +96,11 @@ func TestHandleCallback(t *testing.T) { | |||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
| 		{ | 		{ | ||||||
| 			name:           "withUserNameKey", | 			name:               "withUserNameKey", | ||||||
| 			userNameKey:    "user_name", | 			userNameKey:        "user_name", | ||||||
| 			expectUserID:   "subvalue", | 			expectUserID:       "subvalue", | ||||||
| 			expectUserName: "username", | 			expectUserName:     "username", | ||||||
|  | 			expectedEmailField: "emailvalue", | ||||||
| 			token: map[string]interface{}{ | 			token: map[string]interface{}{ | ||||||
| 				"sub":            "subvalue", | 				"sub":            "subvalue", | ||||||
| 				"user_name":      "username", | 				"user_name":      "username", | ||||||
| @@ -102,6 +108,33 @@ func TestHandleCallback(t *testing.T) { | |||||||
| 				"email_verified": true, | 				"email_verified": true, | ||||||
| 			}, | 			}, | ||||||
| 		}, | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name:                      "emptyEmailScope", | ||||||
|  | 			expectUserID:              "subvalue", | ||||||
|  | 			expectUserName:            "namevalue", | ||||||
|  | 			expectedEmailField:        "", | ||||||
|  | 			scopes:                    []string{"groups"}, | ||||||
|  | 			insecureSkipEmailVerified: true, | ||||||
|  | 			token: map[string]interface{}{ | ||||||
|  | 				"sub":       "subvalue", | ||||||
|  | 				"name":      "namevalue", | ||||||
|  | 				"user_name": "username", | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
|  | 		{ | ||||||
|  | 			name:                      "emptyEmailScopeButEmailProvided", | ||||||
|  | 			expectUserID:              "subvalue", | ||||||
|  | 			expectUserName:            "namevalue", | ||||||
|  | 			expectedEmailField:        "emailvalue", | ||||||
|  | 			scopes:                    []string{"groups"}, | ||||||
|  | 			insecureSkipEmailVerified: true, | ||||||
|  | 			token: map[string]interface{}{ | ||||||
|  | 				"sub":       "subvalue", | ||||||
|  | 				"name":      "namevalue", | ||||||
|  | 				"user_name": "username", | ||||||
|  | 				"email":     "emailvalue", | ||||||
|  | 			}, | ||||||
|  | 		}, | ||||||
| 	} | 	} | ||||||
|  |  | ||||||
| 	for _, tc := range tests { | 	for _, tc := range tests { | ||||||
| @@ -111,13 +144,20 @@ func TestHandleCallback(t *testing.T) { | |||||||
| 				t.Fatal("failed to setup test server", err) | 				t.Fatal("failed to setup test server", err) | ||||||
| 			} | 			} | ||||||
| 			defer testServer.Close() | 			defer testServer.Close() | ||||||
|  |  | ||||||
|  | 			var scopes []string | ||||||
|  | 			if len(tc.scopes) > 0 { | ||||||
|  | 				scopes = tc.scopes | ||||||
|  | 			} else { | ||||||
|  | 				scopes = []string{"email", "groups"} | ||||||
|  | 			} | ||||||
| 			serverURL := testServer.URL | 			serverURL := testServer.URL | ||||||
| 			basicAuth := true | 			basicAuth := true | ||||||
| 			config := Config{ | 			config := Config{ | ||||||
| 				Issuer:                    serverURL, | 				Issuer:                    serverURL, | ||||||
| 				ClientID:                  "clientID", | 				ClientID:                  "clientID", | ||||||
| 				ClientSecret:              "clientSecret", | 				ClientSecret:              "clientSecret", | ||||||
| 				Scopes:                    []string{"groups"}, | 				Scopes:                    scopes, | ||||||
| 				RedirectURI:               fmt.Sprintf("%s/callback", serverURL), | 				RedirectURI:               fmt.Sprintf("%s/callback", serverURL), | ||||||
| 				UserIDKey:                 tc.userIDKey, | 				UserIDKey:                 tc.userIDKey, | ||||||
| 				UserNameKey:               tc.userNameKey, | 				UserNameKey:               tc.userNameKey, | ||||||
| @@ -142,7 +182,7 @@ func TestHandleCallback(t *testing.T) { | |||||||
|  |  | ||||||
| 			expectEquals(t, identity.UserID, tc.expectUserID) | 			expectEquals(t, identity.UserID, tc.expectUserID) | ||||||
| 			expectEquals(t, identity.Username, tc.expectUserName) | 			expectEquals(t, identity.Username, tc.expectUserName) | ||||||
| 			expectEquals(t, identity.Email, "emailvalue") | 			expectEquals(t, identity.Email, tc.expectedEmailField) | ||||||
| 			expectEquals(t, identity.EmailVerified, true) | 			expectEquals(t, identity.EmailVerified, true) | ||||||
| 		}) | 		}) | ||||||
| 	} | 	} | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user