Skip to content
Snippets Groups Projects
Commit 45143c98 authored by Happy2C0de's avatar Happy2C0de
Browse files

Add claimMapping enforcement

parent ba1bd65c
No related branches found
No related tags found
No related merge requests found
......@@ -56,16 +56,23 @@ type Config struct {
// 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 preferred username claims
PreferredUsernameKey string `json:"preferred_username"` // defaults to "preferred_username"
ClaimMapping ClaimMapping `json:"claimMapping"`
}
type ClaimMapping struct {
// Enforce the ClaimMapping.
// i.e. an 'email' claim will always be taken if available,
// irrelevant of the settings in EmailKey. This option will enforce the ClaimMapping options independent of the existing claims.
Enforce bool `json:"enforce"` // defaults to false
// 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 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"`
// Configurable key which contains the groups claims
GroupsKey string `json:"groups"` // defaults to "groups"
}
// Domains that don't support basic auth. golang.org/x/oauth2 has an internal
......@@ -153,9 +160,7 @@ func (c *Config) Open(id string, logger log.Logger) (conn connector.Connector, e
promptType: c.PromptType,
userIDKey: c.UserIDKey,
userNameKey: c.UserNameKey,
preferredUsernameKey: c.ClaimMapping.PreferredUsernameKey,
emailKey: c.ClaimMapping.EmailKey,
groupsKey: c.ClaimMapping.GroupsKey,
claimMapping: c.ClaimMapping,
}, nil
}
......@@ -178,9 +183,7 @@ type oidcConnector struct {
promptType string
userIDKey string
userNameKey string
preferredUsernameKey string
emailKey string
groupsKey string
claimMapping ClaimMapping
}
func (c *oidcConnector) Close() error {
......@@ -288,9 +291,14 @@ 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)
prefUsername := "preferred_username"
preferredUsername, found := claims[prefUsername].(string)
if (!found || c.claimMapping.Enforce) && c.claimMapping.PreferredUsernameKey != "" {
prefUsername = c.claimMapping.PreferredUsernameKey
preferredUsername, found = claims[prefUsername].(string)
if !found {
return identity, fmt.Errorf("missing \"%s\" claim", prefUsername)
}
}
hasEmailScope := false
......@@ -304,9 +312,12 @@ func (c *oidcConnector) createIdentity(ctx context.Context, identity connector.I
var email string
emailKey := "email"
email, found = claims[emailKey].(string)
if !found && c.emailKey != "" {
emailKey = c.emailKey
if (!found || c.claimMapping.Enforce) && c.claimMapping.EmailKey != "" {
emailKey = c.claimMapping.EmailKey
email, found = claims[emailKey].(string)
if !found {
return identity, fmt.Errorf("missing \"%s\" claim", emailKey)
}
}
if !found && hasEmailScope {
......@@ -326,8 +337,8 @@ func (c *oidcConnector) createIdentity(ctx context.Context, identity connector.I
if c.insecureEnableGroups {
groupsKey := "groups"
vs, found := claims[groupsKey].([]interface{})
if !found {
groupsKey = c.groupsKey
if (!found || c.claimMapping.Enforce) && c.claimMapping.GroupsKey != "" {
groupsKey = c.claimMapping.GroupsKey
vs, found = claims[groupsKey].([]interface{})
}
......
......@@ -49,9 +49,7 @@ func TestHandleCallback(t *testing.T) {
name string
userIDKey string
userNameKey string
preferredUsernameKey string
emailKey string
groupsKey string
claimMapping ClaimMapping
insecureSkipEmailVerified bool
scopes []string
expectUserID string
......@@ -78,10 +76,12 @@ func TestHandleCallback(t *testing.T) {
},
},
{
name: "customEmailClaim",
userIDKey: "", // not configured
userNameKey: "", // not configured
emailKey: "mail",
name: "customEmailClaim",
userIDKey: "", // not configured
userNameKey: "", // not configured
claimMapping: ClaimMapping{
EmailKey: "mail",
},
expectUserID: "subvalue",
expectUserName: "namevalue",
expectedEmailField: "emailvalue",
......@@ -92,6 +92,25 @@ func TestHandleCallback(t *testing.T) {
"email_verified": true,
},
},
{
name: "enforceCustomEmailClaim",
userIDKey: "", // not configured
userNameKey: "", // not configured
claimMapping: ClaimMapping{
Enforce: true,
EmailKey: "custommail",
},
expectUserID: "subvalue",
expectUserName: "namevalue",
expectedEmailField: "customemailvalue",
token: map[string]interface{}{
"sub": "subvalue",
"name": "namevalue",
"mail": "emailvalue",
"custommail": "customemailvalue",
"email_verified": true,
},
},
{
name: "email_verified not in claims, configured to be skipped",
insecureSkipEmailVerified: true,
......@@ -131,8 +150,10 @@ func TestHandleCallback(t *testing.T) {
},
},
{
name: "withPreferredUsernameKey",
preferredUsernameKey: "username_key",
name: "withPreferredUsernameKey",
claimMapping: ClaimMapping{
PreferredUsernameKey: "username_key",
},
expectUserID: "subvalue",
expectUserName: "namevalue",
expectPreferredUsername: "username_value",
......@@ -200,8 +221,10 @@ func TestHandleCallback(t *testing.T) {
},
},
{
name: "customGroupsKey",
groupsKey: "cognito:groups",
name: "customGroupsKey",
claimMapping: ClaimMapping{
GroupsKey: "cognito:groups",
},
expectUserID: "subvalue",
expectUserName: "namevalue",
expectedEmailField: "emailvalue",
......@@ -217,8 +240,10 @@ func TestHandleCallback(t *testing.T) {
},
},
{
name: "customGroupsKeyButGroupsProvided",
groupsKey: "cognito:groups",
name: "customGroupsKeyButGroupsProvided",
claimMapping: ClaimMapping{
GroupsKey: "cognito:groups",
},
expectUserID: "subvalue",
expectUserName: "namevalue",
expectedEmailField: "emailvalue",
......@@ -234,6 +259,27 @@ func TestHandleCallback(t *testing.T) {
"cognito:groups": []string{"group3", "group4"},
},
},
{
name: "customGroupsKeyButGroupsProvidedButEnforced",
claimMapping: ClaimMapping{
Enforce: true,
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",
"groups": []string{"group1", "group2"},
"cognito:groups": []string{"group3", "group4"},
},
},
}
for _, tc := range tests {
......@@ -264,9 +310,7 @@ func TestHandleCallback(t *testing.T) {
InsecureEnableGroups: true,
BasicAuthUnsupported: &basicAuth,
}
config.ClaimMapping.PreferredUsernameKey = tc.preferredUsernameKey
config.ClaimMapping.EmailKey = tc.emailKey
config.ClaimMapping.GroupsKey = tc.groupsKey
config.ClaimMapping = tc.claimMapping
conn, err := newConnector(config)
if err != nil {
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment