Browse Source

Merge ca42371edc into 13f012fb81

pull/3811/merge
Darius 4 days ago committed by GitHub
parent
commit
13fd95e5b3
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
  1. 93
      connector/oauth/oauth.go
  2. 59
      connector/oauth/oauth_test.go

93
connector/oauth/oauth.go

@ -19,21 +19,22 @@ import (
var _ connector.CallbackConnector = (*oauthConnector)(nil) var _ connector.CallbackConnector = (*oauthConnector)(nil)
type oauthConnector struct { type oauthConnector struct {
clientID string clientID string
clientSecret string clientSecret string
redirectURI string redirectURI string
tokenURL string tokenURL string
authorizationURL string authorizationURL string
userInfoURL string userInfoURL string
scopes []string scopes []string
userIDKey string userIDKey string
userNameKey string userNameKey string
preferredUsernameKey string preferredUsernameKey string
emailKey string emailKey string
emailVerifiedKey string emailVerifiedKey string
groupsKey string groupsKey string
httpClient *http.Client insecureSkipEmailVerified bool
logger *slog.Logger httpClient *http.Client
logger *slog.Logger
} }
type connectorData struct { type connectorData struct {
@ -41,17 +42,19 @@ type connectorData struct {
} }
type Config struct { type Config struct {
ClientID string `json:"clientID"` ClientID string `json:"clientID"`
ClientSecret string `json:"clientSecret"` ClientSecret string `json:"clientSecret"`
RedirectURI string `json:"redirectURI"` RedirectURI string `json:"redirectURI"`
TokenURL string `json:"tokenURL"` TokenURL string `json:"tokenURL"`
AuthorizationURL string `json:"authorizationURL"` AuthorizationURL string `json:"authorizationURL"`
UserInfoURL string `json:"userInfoURL"` UserInfoURL string `json:"userInfoURL"`
Scopes []string `json:"scopes"` Scopes []string `json:"scopes"`
RootCAs []string `json:"rootCAs"` RootCAs []string `json:"rootCAs"`
InsecureSkipVerify bool `json:"insecureSkipVerify"` // Override the value of email_verified to true in the returned claims
UserIDKey string `json:"userIDKey"` // defaults to "id" InsecureSkipEmailVerified bool `json:"insecureSkipEmailVerified"`
ClaimMapping struct { InsecureSkipVerify bool `json:"insecureSkipVerify"`
UserIDKey string `json:"userIDKey"` // defaults to "id"
ClaimMapping struct {
UserNameKey string `json:"userNameKey"` // defaults to "user_name" UserNameKey string `json:"userNameKey"` // defaults to "user_name"
PreferredUsernameKey string `json:"preferredUsernameKey"` // defaults to "preferred_username" PreferredUsernameKey string `json:"preferredUsernameKey"` // defaults to "preferred_username"
GroupsKey string `json:"groupsKey"` // defaults to "groups" GroupsKey string `json:"groupsKey"` // defaults to "groups"
@ -94,20 +97,21 @@ func (c *Config) Open(id string, logger *slog.Logger) (connector.Connector, erro
} }
oauthConn := &oauthConnector{ oauthConn := &oauthConnector{
clientID: c.ClientID, clientID: c.ClientID,
clientSecret: c.ClientSecret, clientSecret: c.ClientSecret,
tokenURL: c.TokenURL, tokenURL: c.TokenURL,
authorizationURL: c.AuthorizationURL, authorizationURL: c.AuthorizationURL,
userInfoURL: c.UserInfoURL, userInfoURL: c.UserInfoURL,
scopes: c.Scopes, scopes: c.Scopes,
redirectURI: c.RedirectURI, redirectURI: c.RedirectURI,
logger: logger.With(slog.Group("connector", "type", "oauth", "id", id)), logger: logger.With(slog.Group("connector", "type", "oauth", "id", id)),
userIDKey: userIDKey, userIDKey: userIDKey,
userNameKey: userNameKey, userNameKey: userNameKey,
preferredUsernameKey: preferredUsernameKey, preferredUsernameKey: preferredUsernameKey,
groupsKey: groupsKey, groupsKey: groupsKey,
emailKey: emailKey, emailKey: emailKey,
emailVerifiedKey: emailVerifiedKey, emailVerifiedKey: emailVerifiedKey,
insecureSkipEmailVerified: c.InsecureSkipEmailVerified,
} }
oauthConn.httpClient, err = httpclient.NewHTTPClient(c.RootCAs, c.InsecureSkipVerify) oauthConn.httpClient, err = httpclient.NewHTTPClient(c.RootCAs, c.InsecureSkipVerify)
@ -188,7 +192,14 @@ func (c *oauthConnector) HandleCallback(s connector.Scopes, _ []byte, r *http.Re
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[c.emailKey].(string) identity.Email, _ = userInfoResult[c.emailKey].(string)
identity.EmailVerified, _ = userInfoResult[c.emailVerifiedKey].(bool)
identity.EmailVerified, found = userInfoResult[c.emailVerifiedKey].(bool)
if !found {
if c.insecureSkipEmailVerified {
identity.EmailVerified = true
}
}
if s.Groups { if s.Groups {
groups := map[string]struct{}{} groups := map[string]struct{}{}

59
connector/oauth/oauth_test.go

@ -196,6 +196,65 @@ func TestHandleCallbackForNumericUserID(t *testing.T) {
assert.Equal(t, identity.EmailVerified, false) assert.Equal(t, identity.EmailVerified, false)
} }
func TestHandleCallbackWithInsecureSkipEmailVerifiedWhenKeyFound(t *testing.T) {
tokenClaims := map[string]interface{}{}
userInfoClaims := map[string]interface{}{
"name": "test-name",
"user_id_key": 1000,
"user_name_key": "test-username",
"preferred_username": "test-preferred-username",
"mail": "mod_mail",
"has_verified_email": false,
}
testServer := testSetup(t, tokenClaims, userInfoClaims)
defer testServer.Close()
conn := newConnector(t, testServer.URL)
conn.insecureSkipEmailVerified = true
req := newRequestWithAuthCode(t, testServer.URL, "TestHandleCallbackWithInsecureSkipEmailVerifiedWhenKeyFound")
identity, err := conn.HandleCallback(connector.Scopes{Groups: true}, req)
assert.Equal(t, err, nil)
assert.Equal(t, identity.UserID, "1000")
assert.Equal(t, identity.Username, "test-username")
assert.Equal(t, identity.PreferredUsername, "test-preferred-username")
assert.Equal(t, identity.Email, "mod_mail")
assert.Equal(t, identity.EmailVerified, false)
}
func TestHandleCallbackWithInsecureSkipEmailVerifiedWhenKeyNotFound(t *testing.T) {
tokenClaims := map[string]interface{}{}
userInfoClaims := map[string]interface{}{
"name": "test-name",
"user_id_key": 1000,
"user_name_key": "test-username",
"preferred_username": "test-preferred-username",
"mail": "mod_mail",
}
testServer := testSetup(t, tokenClaims, userInfoClaims)
defer testServer.Close()
conn := newConnector(t, testServer.URL)
conn.insecureSkipEmailVerified = true
req := newRequestWithAuthCode(t, testServer.URL, "TestHandleCallbackWithInsecureSkipEmailVerifiedWhenKeyNotFound")
identity, err := conn.HandleCallback(connector.Scopes{Groups: true}, req)
assert.Equal(t, err, nil)
assert.Equal(t, identity.UserID, "1000")
assert.Equal(t, identity.Username, "test-username")
assert.Equal(t, identity.PreferredUsername, "test-preferred-username")
assert.Equal(t, identity.Email, "mod_mail")
assert.Equal(t, identity.EmailVerified, true)
}
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 {
key, err := rsa.GenerateKey(rand.Reader, 1024) key, err := rsa.GenerateKey(rand.Reader, 1024)
if err != nil { if err != nil {

Loading…
Cancel
Save