add tests for groups key mapping Signed-off-by: Rui Yang <ruiya@vmware.com>
This commit is contained in:
@@ -44,28 +44,36 @@ type Config struct {
|
||||
// InsecureEnableGroups enables groups claims. This is disabled by default until https://github.com/dexidp/dex/issues/1065 is resolved
|
||||
InsecureEnableGroups bool `json:"insecureEnableGroups"`
|
||||
|
||||
// GroupsClaimMapping sets the name of the claim which contains the users groups. InsecureEnableGroups must be enabled to use this setting
|
||||
GroupsClaimMapping string `json:"groupsClaimMapping"` // defaults to "groups"
|
||||
|
||||
// GetUserInfo uses the userinfo endpoint to get additional claims for
|
||||
// the token. This is especially useful where upstreams return "thin"
|
||||
// id tokens
|
||||
GetUserInfo bool `json:"getUserInfo"`
|
||||
|
||||
// Configurable key which contains the user id claim
|
||||
// Deprecated: use UserIDKey in claimMapping instead
|
||||
UserIDKey string `json:"userIDKey"`
|
||||
|
||||
// Configurable key which contains the user name claim
|
||||
// Deprecated: use UserNameKey in claimMapping instead
|
||||
UserNameKey string `json:"userNameKey"`
|
||||
|
||||
// Configurable key which contains the preferred username claims
|
||||
PreferredUsernameKey string `json:"preferredUsernameKey"`
|
||||
|
||||
// EmailClaim override email claim key. Defaults to "email"
|
||||
EmailClaim string `json:"emailClaim"`
|
||||
|
||||
// PromptType will be used fot the prompt parameter (when offline_access, by default prompt=consent)
|
||||
PromptType string `json:"promptType"`
|
||||
|
||||
ClaimMapping struct {
|
||||
// Configurable key which contains the user id claim
|
||||
UserIDKey string `json:"user_id"` // defaults to "sub"
|
||||
|
||||
// Configurable key which contains the username claim
|
||||
UserNameKey string `json:"user_name"` // defaults to "name"
|
||||
|
||||
// Configurable key which contains the preferred username claims
|
||||
PreferredUsernameKey string `json:"preferred_username"` // defaults to "preferred_username"
|
||||
|
||||
// Configurable key which contains the email claims
|
||||
EmailKey string `json:"email"` // defaults to "email"
|
||||
|
||||
// Configurable key which contains the groups claims
|
||||
GroupsKey string `json:"groups"` // defaults to "groups"
|
||||
} `json:"claimMapping"`
|
||||
}
|
||||
|
||||
// Domains that don't support basic auth. golang.org/x/oauth2 has an internal
|
||||
@@ -118,11 +126,6 @@ func (c *Config) Open(id string, logger log.Logger) (conn connector.Connector, e
|
||||
endpoint.AuthStyle = oauth2.AuthStyleInParams
|
||||
}
|
||||
|
||||
emailClaim := "email"
|
||||
if len(c.EmailClaim) > 0 {
|
||||
emailClaim = c.EmailClaim
|
||||
}
|
||||
|
||||
scopes := []string{oidc.ScopeOpenID}
|
||||
if len(c.Scopes) > 0 {
|
||||
scopes = append(scopes, c.Scopes...)
|
||||
@@ -135,9 +138,16 @@ func (c *Config) Open(id string, logger log.Logger) (conn connector.Connector, e
|
||||
c.PromptType = "consent"
|
||||
}
|
||||
|
||||
// GroupsClaimMapping should be "groups" by default, if not set
|
||||
if c.GroupsClaimMapping == "" {
|
||||
c.GroupsClaimMapping = "groups"
|
||||
// Backward compatibility
|
||||
userIDKey := c.ClaimMapping.UserIDKey
|
||||
if userIDKey == "" {
|
||||
userIDKey = c.UserIDKey
|
||||
}
|
||||
|
||||
// Backward compatibility
|
||||
userNameKey := c.ClaimMapping.UserNameKey
|
||||
if userNameKey == "" {
|
||||
userNameKey = c.UserNameKey
|
||||
}
|
||||
|
||||
clientID := c.ClientID
|
||||
@@ -159,13 +169,13 @@ func (c *Config) Open(id string, logger log.Logger) (conn connector.Connector, e
|
||||
hostedDomains: c.HostedDomains,
|
||||
insecureSkipEmailVerified: c.InsecureSkipEmailVerified,
|
||||
insecureEnableGroups: c.InsecureEnableGroups,
|
||||
groupsClaimMapping: c.GroupsClaimMapping,
|
||||
getUserInfo: c.GetUserInfo,
|
||||
userIDKey: c.UserIDKey,
|
||||
userNameKey: c.UserNameKey,
|
||||
preferredUsernameKey: c.PreferredUsernameKey,
|
||||
emailClaim: emailClaim,
|
||||
promptType: c.PromptType,
|
||||
userIDKey: userIDKey,
|
||||
userNameKey: userNameKey,
|
||||
preferredUsernameKey: c.ClaimMapping.PreferredUsernameKey,
|
||||
emailKey: c.ClaimMapping.EmailKey,
|
||||
groupsKey: c.ClaimMapping.GroupsKey,
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -184,13 +194,13 @@ type oidcConnector struct {
|
||||
hostedDomains []string
|
||||
insecureSkipEmailVerified bool
|
||||
insecureEnableGroups bool
|
||||
groupsClaimMapping string
|
||||
getUserInfo bool
|
||||
promptType string
|
||||
userIDKey string
|
||||
userNameKey string
|
||||
preferredUsernameKey string
|
||||
emailClaim string
|
||||
promptType string
|
||||
emailKey string
|
||||
groupsKey string
|
||||
}
|
||||
|
||||
func (c *oidcConnector) Close() error {
|
||||
@@ -298,6 +308,11 @@ func (c *oidcConnector) createIdentity(ctx context.Context, identity connector.I
|
||||
return identity, fmt.Errorf("missing \"%s\" claim", userNameKey)
|
||||
}
|
||||
|
||||
preferredUsername, found := claims["preferred_username"].(string)
|
||||
if !found {
|
||||
preferredUsername, _ = claims[c.preferredUsernameKey].(string)
|
||||
}
|
||||
|
||||
hasEmailScope := false
|
||||
for _, s := range c.oauth2Config.Scopes {
|
||||
if s == "email" {
|
||||
@@ -306,9 +321,16 @@ func (c *oidcConnector) createIdentity(ctx context.Context, identity connector.I
|
||||
}
|
||||
}
|
||||
|
||||
email, found := claims[c.emailClaim].(string)
|
||||
var email string
|
||||
emailKey := "email"
|
||||
email, found = claims[emailKey].(string)
|
||||
if !found && c.emailKey != "" {
|
||||
emailKey = c.emailKey
|
||||
email, found = claims[emailKey].(string)
|
||||
}
|
||||
|
||||
if !found && hasEmailScope {
|
||||
return identity, fmt.Errorf("missing \"%s\" claim", c.emailClaim)
|
||||
return identity, fmt.Errorf("missing \"%s\" claim", emailKey)
|
||||
}
|
||||
|
||||
emailVerified, found := claims["email_verified"].(bool)
|
||||
@@ -319,13 +341,28 @@ func (c *oidcConnector) createIdentity(ctx context.Context, identity connector.I
|
||||
return identity, errors.New("missing \"email_verified\" claim")
|
||||
}
|
||||
}
|
||||
hostedDomain, _ := claims["hd"].(string)
|
||||
|
||||
preferredUsername, found := claims["preferred_username"].(string)
|
||||
if !found {
|
||||
preferredUsername, _ = claims[c.preferredUsernameKey].(string)
|
||||
var groups []string
|
||||
if c.insecureEnableGroups {
|
||||
groupsKey := "groups"
|
||||
vs, found := claims[groupsKey].([]interface{})
|
||||
if !found {
|
||||
groupsKey = c.groupsKey
|
||||
vs, found = claims[groupsKey].([]interface{})
|
||||
}
|
||||
|
||||
if found {
|
||||
for _, v := range vs {
|
||||
if s, ok := v.(string); ok {
|
||||
groups = append(groups, s)
|
||||
} else {
|
||||
return identity, fmt.Errorf("malformed \"%v\" claim", groupsKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
hostedDomain, _ := claims["hd"].(string)
|
||||
if len(c.hostedDomains) > 0 {
|
||||
found := false
|
||||
for _, domain := range c.hostedDomains {
|
||||
@@ -355,6 +392,7 @@ func (c *oidcConnector) createIdentity(ctx context.Context, identity connector.I
|
||||
PreferredUsername: preferredUsername,
|
||||
Email: email,
|
||||
EmailVerified: emailVerified,
|
||||
Groups: groups,
|
||||
ConnectorData: connData,
|
||||
}
|
||||
|
||||
@@ -366,19 +404,5 @@ func (c *oidcConnector) createIdentity(ctx context.Context, identity connector.I
|
||||
identity.UserID = userID
|
||||
}
|
||||
|
||||
if c.insecureEnableGroups {
|
||||
|
||||
vs, ok := claims[c.groupsClaimMapping].([]interface{})
|
||||
if ok {
|
||||
for _, v := range vs {
|
||||
if s, ok := v.(string); ok {
|
||||
identity.Groups = append(identity.Groups, s)
|
||||
} else {
|
||||
return identity, fmt.Errorf("malformed \"%v\" claim", c.groupsClaimMapping)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return identity, nil
|
||||
}
|
||||
|
@@ -50,11 +50,13 @@ func TestHandleCallback(t *testing.T) {
|
||||
userIDKey string
|
||||
userNameKey string
|
||||
preferredUsernameKey string
|
||||
emailKey string
|
||||
groupsKey string
|
||||
insecureSkipEmailVerified bool
|
||||
scopes []string
|
||||
emailClaim string
|
||||
expectUserID string
|
||||
expectUserName string
|
||||
expectGroups []string
|
||||
expectPreferredUsername string
|
||||
expectedEmailField string
|
||||
token map[string]interface{}
|
||||
@@ -65,10 +67,12 @@ func TestHandleCallback(t *testing.T) {
|
||||
userNameKey: "", // not configured
|
||||
expectUserID: "subvalue",
|
||||
expectUserName: "namevalue",
|
||||
expectGroups: []string{"group1", "group2"},
|
||||
expectedEmailField: "emailvalue",
|
||||
token: map[string]interface{}{
|
||||
"sub": "subvalue",
|
||||
"name": "namevalue",
|
||||
"groups": []string{"group1", "group2"},
|
||||
"email": "emailvalue",
|
||||
"email_verified": true,
|
||||
},
|
||||
@@ -77,7 +81,7 @@ func TestHandleCallback(t *testing.T) {
|
||||
name: "customEmailClaim",
|
||||
userIDKey: "", // not configured
|
||||
userNameKey: "", // not configured
|
||||
emailClaim: "mail",
|
||||
emailKey: "mail",
|
||||
expectUserID: "subvalue",
|
||||
expectUserName: "namevalue",
|
||||
expectedEmailField: "emailvalue",
|
||||
@@ -195,6 +199,41 @@ func TestHandleCallback(t *testing.T) {
|
||||
"email": "emailvalue",
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "customGroupsKey",
|
||||
groupsKey: "cognito:groups",
|
||||
expectUserID: "subvalue",
|
||||
expectUserName: "namevalue",
|
||||
expectedEmailField: "emailvalue",
|
||||
expectGroups: []string{"group3", "group4"},
|
||||
scopes: []string{"groups"},
|
||||
insecureSkipEmailVerified: true,
|
||||
token: map[string]interface{}{
|
||||
"sub": "subvalue",
|
||||
"name": "namevalue",
|
||||
"user_name": "username",
|
||||
"email": "emailvalue",
|
||||
"cognito:groups": []string{"group3", "group4"},
|
||||
},
|
||||
},
|
||||
{
|
||||
name: "customGroupsKeyButGroupsProvided",
|
||||
groupsKey: "cognito:groups",
|
||||
expectUserID: "subvalue",
|
||||
expectUserName: "namevalue",
|
||||
expectedEmailField: "emailvalue",
|
||||
expectGroups: []string{"group1", "group2"},
|
||||
scopes: []string{"groups"},
|
||||
insecureSkipEmailVerified: true,
|
||||
token: map[string]interface{}{
|
||||
"sub": "subvalue",
|
||||
"name": "namevalue",
|
||||
"user_name": "username",
|
||||
"email": "emailvalue",
|
||||
"groups": []string{"group1", "group2"},
|
||||
"cognito:groups": []string{"group3", "group4"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range tests {
|
||||
@@ -219,13 +258,15 @@ func TestHandleCallback(t *testing.T) {
|
||||
ClientSecret: "clientSecret",
|
||||
Scopes: scopes,
|
||||
RedirectURI: fmt.Sprintf("%s/callback", serverURL),
|
||||
UserIDKey: tc.userIDKey,
|
||||
UserNameKey: tc.userNameKey,
|
||||
PreferredUsernameKey: tc.preferredUsernameKey,
|
||||
EmailClaim: tc.emailClaim,
|
||||
InsecureSkipEmailVerified: tc.insecureSkipEmailVerified,
|
||||
InsecureEnableGroups: true,
|
||||
BasicAuthUnsupported: &basicAuth,
|
||||
}
|
||||
config.ClaimMapping.UserIDKey = tc.userIDKey
|
||||
config.ClaimMapping.UserNameKey = tc.userNameKey
|
||||
config.ClaimMapping.PreferredUsernameKey = tc.preferredUsernameKey
|
||||
config.ClaimMapping.EmailKey = tc.emailKey
|
||||
config.ClaimMapping.GroupsKey = tc.groupsKey
|
||||
|
||||
conn, err := newConnector(config)
|
||||
if err != nil {
|
||||
@@ -247,6 +288,7 @@ func TestHandleCallback(t *testing.T) {
|
||||
expectEquals(t, identity.PreferredUsername, tc.expectPreferredUsername)
|
||||
expectEquals(t, identity.Email, tc.expectedEmailField)
|
||||
expectEquals(t, identity.EmailVerified, true)
|
||||
expectEquals(t, identity.Groups, tc.expectGroups)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user