use claim mappings when retrieving user identity
Signed-off-by: Rui Yang <ruiya@vmware.com>
This commit is contained in:
parent
60b8875780
commit
02860da8b6
3 changed files with 90 additions and 50 deletions
|
@ -28,10 +28,12 @@ type oauthConnector struct {
|
||||||
authorizationURL string
|
authorizationURL string
|
||||||
userInfoURL string
|
userInfoURL string
|
||||||
scopes []string
|
scopes []string
|
||||||
groupsKey string
|
|
||||||
userIDKey string
|
userIDKey string
|
||||||
userNameKey string
|
userNameKey string
|
||||||
preferredUsernameKey string
|
preferredUsernameKey string
|
||||||
|
emailKey string
|
||||||
|
emailVerifiedKey string
|
||||||
|
groupsKey string
|
||||||
httpClient *http.Client
|
httpClient *http.Client
|
||||||
logger log.Logger
|
logger log.Logger
|
||||||
}
|
}
|
||||||
|
@ -48,12 +50,16 @@ type Config struct {
|
||||||
AuthorizationURL string `json:"authorizationURL"`
|
AuthorizationURL string `json:"authorizationURL"`
|
||||||
UserInfoURL string `json:"userInfoURL"`
|
UserInfoURL string `json:"userInfoURL"`
|
||||||
Scopes []string `json:"scopes"`
|
Scopes []string `json:"scopes"`
|
||||||
GroupsKey string `json:"groupsKey"`
|
|
||||||
UserIDKey string `json:"userIDKey"`
|
|
||||||
UserNameKey string `json:"userNameKey"`
|
|
||||||
PreferredUsernameKey string `json:"preferredUsernameKey"`
|
|
||||||
RootCAs []string `json:"rootCAs"`
|
RootCAs []string `json:"rootCAs"`
|
||||||
InsecureSkipVerify bool `json:"insecureSkipVerify"`
|
InsecureSkipVerify bool `json:"insecureSkipVerify"`
|
||||||
|
UserIDKey string `json:"userIDKey"` // defaults to "id"
|
||||||
|
ClaimMapping struct {
|
||||||
|
UserNameKey string `json:"userNameKey"` // defaults to "user_name"
|
||||||
|
PreferredUsernameKey string `json:"preferredUsernameKey"` // defaults to "preferred_username"
|
||||||
|
GroupsKey string `json:"groupsKey"` // defaults to "groups"
|
||||||
|
EmailKey string `json:"emailKey"` // defaults to "email"
|
||||||
|
EmailVerifiedKey string `json:"emailVerifiedKey"` // defaults to "email_verified"
|
||||||
|
} `json:"claimMapping"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error) {
|
func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error) {
|
||||||
|
@ -66,11 +72,14 @@ func (c *Config) Open(id string, logger log.Logger) (connector.Connector, error)
|
||||||
authorizationURL: c.AuthorizationURL,
|
authorizationURL: c.AuthorizationURL,
|
||||||
userInfoURL: c.UserInfoURL,
|
userInfoURL: c.UserInfoURL,
|
||||||
scopes: c.Scopes,
|
scopes: c.Scopes,
|
||||||
groupsKey: c.GroupsKey,
|
|
||||||
userIDKey: c.UserIDKey,
|
|
||||||
userNameKey: c.UserNameKey,
|
|
||||||
redirectURI: c.RedirectURI,
|
redirectURI: c.RedirectURI,
|
||||||
logger: logger,
|
logger: logger,
|
||||||
|
userIDKey: c.UserIDKey,
|
||||||
|
userNameKey: c.ClaimMapping.UserNameKey,
|
||||||
|
preferredUsernameKey: c.ClaimMapping.PreferredUsernameKey,
|
||||||
|
groupsKey: c.ClaimMapping.GroupsKey,
|
||||||
|
emailKey: c.ClaimMapping.EmailKey,
|
||||||
|
emailVerifiedKey: c.ClaimMapping.EmailVerifiedKey,
|
||||||
}
|
}
|
||||||
|
|
||||||
oauthConn.httpClient, err = newHTTPClient(c.RootCAs, c.InsecureSkipVerify)
|
oauthConn.httpClient, err = newHTTPClient(c.RootCAs, c.InsecureSkipVerify)
|
||||||
|
@ -173,26 +182,39 @@ func (c *oauthConnector) HandleCallback(s connector.Scopes, r *http.Request) (id
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.userIDKey == "" {
|
if c.userIDKey == "" {
|
||||||
c.userIDKey = "user_id"
|
c.userIDKey = "id"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
userID, found := userInfoResult[c.userIDKey].(string)
|
||||||
|
if !found {
|
||||||
|
return identity, fmt.Errorf("OAuth Connector: not found %v claim", c.userIDKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
identity.UserID = userID
|
||||||
if c.userNameKey == "" {
|
if c.userNameKey == "" {
|
||||||
c.userNameKey = "user_name"
|
c.userNameKey = "user_name"
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.groupsKey == "" {
|
|
||||||
c.groupsKey = "groups"
|
|
||||||
}
|
|
||||||
|
|
||||||
if c.preferredUsernameKey == "" {
|
if c.preferredUsernameKey == "" {
|
||||||
c.preferredUsernameKey = "preferred_username"
|
c.preferredUsernameKey = "preferred_username"
|
||||||
}
|
}
|
||||||
|
|
||||||
identity.UserID, _ = userInfoResult[c.userIDKey].(string)
|
if c.groupsKey == "" {
|
||||||
|
c.groupsKey = "groups"
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.emailKey == "" {
|
||||||
|
c.emailKey = "email"
|
||||||
|
}
|
||||||
|
|
||||||
|
if c.emailVerifiedKey == "" {
|
||||||
|
c.emailVerifiedKey = "email_verified"
|
||||||
|
}
|
||||||
|
|
||||||
identity.Username, _ = userInfoResult[c.userNameKey].(string)
|
identity.Username, _ = userInfoResult[c.userNameKey].(string)
|
||||||
identity.PreferredUsername, _ = userInfoResult[c.preferredUsernameKey].(string)
|
identity.PreferredUsername, _ = userInfoResult[c.preferredUsernameKey].(string)
|
||||||
identity.Email, _ = userInfoResult["email"].(string)
|
identity.Email, _ = userInfoResult[c.emailKey].(string)
|
||||||
identity.EmailVerified, _ = userInfoResult["email_verified"].(bool)
|
identity.EmailVerified, _ = userInfoResult[c.emailVerifiedKey].(bool)
|
||||||
|
|
||||||
if s.Groups {
|
if s.Groups {
|
||||||
groups := map[string]bool{}
|
groups := map[string]bool{}
|
||||||
|
|
|
@ -75,8 +75,8 @@ func TestHandleCallBackForGroupsInUserInfo(t *testing.T) {
|
||||||
"user_id_key": "test-user-id",
|
"user_id_key": "test-user-id",
|
||||||
"user_name_key": "test-username",
|
"user_name_key": "test-username",
|
||||||
"preferred_username": "test-preferred-username",
|
"preferred_username": "test-preferred-username",
|
||||||
"email": "test-email",
|
"mail": "mod_mail",
|
||||||
"email_verified": true,
|
"has_verified_email": false,
|
||||||
"groups_key": []string{"admin-group", "user-group"},
|
"groups_key": []string{"admin-group", "user-group"},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -96,8 +96,8 @@ func TestHandleCallBackForGroupsInUserInfo(t *testing.T) {
|
||||||
assert.Equal(t, identity.UserID, "test-user-id")
|
assert.Equal(t, identity.UserID, "test-user-id")
|
||||||
assert.Equal(t, identity.Username, "test-username")
|
assert.Equal(t, identity.Username, "test-username")
|
||||||
assert.Equal(t, identity.PreferredUsername, "test-preferred-username")
|
assert.Equal(t, identity.PreferredUsername, "test-preferred-username")
|
||||||
assert.Equal(t, identity.Email, "test-email")
|
assert.Equal(t, identity.Email, "mod_mail")
|
||||||
assert.Equal(t, identity.EmailVerified, true)
|
assert.Equal(t, identity.EmailVerified, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHandleCallBackForGroupsInToken(t *testing.T) {
|
func TestHandleCallBackForGroupsInToken(t *testing.T) {
|
||||||
|
@ -128,8 +128,8 @@ func TestHandleCallBackForGroupsInToken(t *testing.T) {
|
||||||
assert.Equal(t, identity.PreferredUsername, "test-preferred-username")
|
assert.Equal(t, identity.PreferredUsername, "test-preferred-username")
|
||||||
assert.Equal(t, identity.UserID, "test-user-id")
|
assert.Equal(t, identity.UserID, "test-user-id")
|
||||||
assert.Equal(t, identity.Username, "test-username")
|
assert.Equal(t, identity.Username, "test-username")
|
||||||
assert.Equal(t, identity.Email, "test-email")
|
assert.Equal(t, identity.Email, "")
|
||||||
assert.Equal(t, identity.EmailVerified, true)
|
assert.Equal(t, identity.EmailVerified, false)
|
||||||
}
|
}
|
||||||
|
|
||||||
func testSetup(t *testing.T, tokenClaims map[string]interface{}, userInfoClaims map[string]interface{}) *httptest.Server {
|
func testSetup(t *testing.T, tokenClaims map[string]interface{}, userInfoClaims map[string]interface{}) *httptest.Server {
|
||||||
|
@ -198,11 +198,14 @@ func newConnector(t *testing.T, serverURL string) *oauthConnector {
|
||||||
AuthorizationURL: serverURL + "/authorize",
|
AuthorizationURL: serverURL + "/authorize",
|
||||||
UserInfoURL: serverURL + "/userinfo",
|
UserInfoURL: serverURL + "/userinfo",
|
||||||
Scopes: []string{"openid", "groups"},
|
Scopes: []string{"openid", "groups"},
|
||||||
GroupsKey: "groups_key",
|
|
||||||
UserIDKey: "user_id_key",
|
UserIDKey: "user_id_key",
|
||||||
UserNameKey: "user_name_key",
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
testConfig.ClaimMapping.UserNameKey = "user_name_key"
|
||||||
|
testConfig.ClaimMapping.GroupsKey = "groups_key"
|
||||||
|
testConfig.ClaimMapping.EmailKey = "mail"
|
||||||
|
testConfig.ClaimMapping.EmailVerifiedKey = "has_verified_email"
|
||||||
|
|
||||||
log := logrus.New()
|
log := logrus.New()
|
||||||
|
|
||||||
conn, err := testConfig.Open("id", log)
|
conn, err := testConfig.Open("id", log)
|
||||||
|
|
|
@ -35,15 +35,30 @@ connectors:
|
||||||
# scopes:
|
# scopes:
|
||||||
# - identity
|
# - identity
|
||||||
|
|
||||||
# Optional: Configurable keys for groups claim look up
|
# Optional: Configurable keys for user ID look up
|
||||||
|
# Default: id
|
||||||
|
# userIDKey:
|
||||||
|
|
||||||
|
# Auth roviders return non-standard user identity profile
|
||||||
|
# Use claimMapping to map those user infomations to standard claims:
|
||||||
|
claimMapping:
|
||||||
|
# Optional: Configurable keys for user name look up
|
||||||
|
# Default: user_name
|
||||||
|
# userNameKey:
|
||||||
|
|
||||||
|
# Optional: Configurable keys for preferred username look up
|
||||||
|
# Default: preferred_username
|
||||||
|
# preferredUsernameKey:
|
||||||
|
|
||||||
|
# Optional: Configurable keys for user groups look up
|
||||||
# Default: groups
|
# Default: groups
|
||||||
# groupsKey:
|
# groupsKey:
|
||||||
|
|
||||||
# Optional: Configurable keys for user ID claim look up
|
# Optional: Configurable keys for email look up
|
||||||
# Default: user_id
|
# Default: email
|
||||||
# userIDKey:
|
# emailKey:
|
||||||
|
|
||||||
# Optional: Configurable keys for preferred username claim look up
|
# Optional: Configurable keys for email verified look up
|
||||||
# Default: preferred_username
|
# Default: email_verified
|
||||||
# preferredUsernameKey:
|
# emailVerifiedKey:
|
||||||
```
|
```
|
||||||
|
|
Reference in a new issue