Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Documentation/connectors/oidc.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,11 @@ connectors:
# - email
# - groups

# Some providers return no standard email claim key (ex: 'mail')
# Override email claim key
# Default is "email"
# emailClaim: email

# Some providers return claims without "email_verified", when they had no usage of emails verification in enrollment process
# or if they are acting as a proxy for another IDP etc AWS Cognito with an upstream SAML IDP
# This can be overridden with the below option
Expand Down
14 changes: 12 additions & 2 deletions connector/oidc/oidc.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ type Config struct {
// Configurable key which contains the user name claim
UserNameKey string `json:"userNameKey"`

// 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"`
}
Expand Down Expand Up @@ -109,6 +112,11 @@ 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...)
Expand Down Expand Up @@ -143,6 +151,7 @@ func (c *Config) Open(id string, logger log.Logger) (conn connector.Connector, e
getUserInfo: c.GetUserInfo,
userIDKey: c.UserIDKey,
userNameKey: c.UserNameKey,
emailClaim: emailClaim,
promptType: c.PromptType,
}, nil
}
Expand All @@ -165,6 +174,7 @@ type oidcConnector struct {
getUserInfo bool
userIDKey string
userNameKey string
emailClaim string
promptType string
}

Expand Down Expand Up @@ -281,9 +291,9 @@ func (c *oidcConnector) createIdentity(ctx context.Context, identity connector.I
}
}

email, found := claims["email"].(string)
email, found := claims[c.emailClaim].(string)
if !found && hasEmailScope {
return identity, errors.New("missing \"email\" claim")
return identity, fmt.Errorf("missing \"%s\" claim", c.emailClaim)
}

emailVerified, found := claims["email_verified"].(bool)
Expand Down
17 changes: 17 additions & 0 deletions connector/oidc/oidc_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ func TestHandleCallback(t *testing.T) {
userNameKey string
insecureSkipEmailVerified bool
scopes []string
emailClaim string
expectUserID string
expectUserName string
expectedEmailField string
Expand All @@ -70,6 +71,21 @@ func TestHandleCallback(t *testing.T) {
"email_verified": true,
},
},
{
name: "customEmailClaim",
userIDKey: "", // not configured
userNameKey: "", // not configured
emailClaim: "mail",
expectUserID: "subvalue",
expectUserName: "namevalue",
expectedEmailField: "emailvalue",
token: map[string]interface{}{
"sub": "subvalue",
"name": "namevalue",
"mail": "emailvalue",
"email_verified": true,
},
},
{
name: "email_verified not in claims, configured to be skipped",
insecureSkipEmailVerified: true,
Expand Down Expand Up @@ -161,6 +177,7 @@ func TestHandleCallback(t *testing.T) {
RedirectURI: fmt.Sprintf("%s/callback", serverURL),
UserIDKey: tc.userIDKey,
UserNameKey: tc.userNameKey,
EmailClaim: tc.emailClaim,
InsecureSkipEmailVerified: tc.insecureSkipEmailVerified,
BasicAuthUnsupported: &basicAuth,
}
Expand Down