diff --git a/management/server/idp/auth0.go b/management/server/idp/auth0.go index bdd33a476..fe56dea99 100644 --- a/management/server/idp/auth0.go +++ b/management/server/idp/auth0.go @@ -23,9 +23,18 @@ type Auth0Manager struct { // Auth0ClientConfig auth0 manager client configurations type Auth0ClientConfig struct { - Audience string `json:"audiance"` + Audience string + AuthIssuer string + ClientID string + ClientSecret string + GrantType string +} + +// auth0JWTRequest payload struct to request a JWT Token +type auth0JWTRequest struct { + Audience string `json:"audience"` AuthIssuer string `json:"auth_issuer"` - ClientId string `json:"client_id"` + ClientID string `json:"client_id"` ClientSecret string `json:"client_secret"` GrantType string `json:"grant_type"` } @@ -40,11 +49,10 @@ type Auth0Credentials struct { } // NewAuth0Manager creates a new instance of the Auth0Manager -func NewAuth0Manager(config Auth0ClientConfig) *Auth0Manager { +func NewAuth0Manager(config Auth0ClientConfig) (*Auth0Manager, error) { httpTransport := http.DefaultTransport.(*http.Transport).Clone() httpTransport.MaxIdleConns = 5 - httpTransport.IdleConnTimeout = 30 httpClient := &http.Client{ Timeout: 10 * time.Second, @@ -53,6 +61,18 @@ func NewAuth0Manager(config Auth0ClientConfig) *Auth0Manager { helper := JsonParser{} + if config.ClientID == "" || config.ClientSecret == "" || config.GrantType == "" || config.Audience == "" || config.AuthIssuer == "" { + return nil, fmt.Errorf("auth0 idp configuration is not complete") + } + + if config.GrantType != "client_credentials" { + return nil, fmt.Errorf("auth0 idp configuration failed. Grant Type should be client_credentials") + } + + if !strings.HasPrefix(strings.ToLower(config.AuthIssuer), "https://") { + return nil, fmt.Errorf("auth0 idp configuration failed. AuthIssuer should contain https://") + } + credentials := &Auth0Credentials{ clientConfig: config, httpClient: httpClient, @@ -63,7 +83,7 @@ func NewAuth0Manager(config Auth0ClientConfig) *Auth0Manager { credentials: credentials, httpClient: httpClient, helper: helper, - } + }, nil } // jwtStillValid returns true if the token still valid and have enough time to be used and get a response from Auth0 @@ -76,7 +96,7 @@ func (c *Auth0Credentials) requestJWTToken() (*http.Response, error) { var res *http.Response url := c.clientConfig.AuthIssuer + "/oauth/token" - p, err := c.helper.Marshal(c.clientConfig) + p, err := c.helper.Marshal(auth0JWTRequest(c.clientConfig)) if err != nil { return res, err } @@ -89,6 +109,8 @@ func (c *Auth0Credentials) requestJWTToken() (*http.Response, error) { req.Header.Add("content-type", "application/json") + log.Debug("requesting new jwt token for idp manager") + res, err = c.httpClient.Do(req) if err != nil { return res, err @@ -187,6 +209,8 @@ func (am *Auth0Manager) UpdateUserAppMetadata(userId string, appMetadata AppMeta req.Header.Add("authorization", "Bearer "+jwtToken.AccessToken) req.Header.Add("content-type", "application/json") + log.Debugf("updating metadata for user %s", userId) + res, err := am.httpClient.Do(req) if err != nil { return err diff --git a/management/server/idp/auth0_test.go b/management/server/idp/auth0_test.go index a4b4b5dbe..bded9bf5b 100644 --- a/management/server/idp/auth0_test.go +++ b/management/server/idp/auth0_test.go @@ -3,6 +3,7 @@ package idp import ( "encoding/json" "fmt" + "github.com/stretchr/testify/require" "io/ioutil" "net/http" "strings" @@ -402,3 +403,64 @@ func TestAuth0_UpdateUserAppMetadata(t *testing.T) { }) } } + +func TestNewAuth0Manager(t *testing.T) { + type test struct { + name string + inputConfig Auth0ClientConfig + assertErrFunc require.ErrorAssertionFunc + assertErrFuncMessage string + } + + defaultTestConfig := Auth0ClientConfig{ + AuthIssuer: "https://abc-auth0.eu.auth0.com", + Audience: "https://abc-auth0.eu.auth0.com/api/v2/", + ClientID: "abcdefg", + ClientSecret: "supersecret", + GrantType: "client_credentials", + } + + testCase1 := test{ + name: "Good Scenario With Config", + inputConfig: defaultTestConfig, + assertErrFunc: require.NoError, + assertErrFuncMessage: "shouldn't return error", + } + + testCase2Config := defaultTestConfig + testCase2Config.ClientID = "" + + testCase2 := test{ + name: "Missing Configuration", + inputConfig: testCase2Config, + assertErrFunc: require.Error, + assertErrFuncMessage: "shouldn't return error when field empty", + } + + testCase3Config := defaultTestConfig + testCase3Config.AuthIssuer = "abc-auth0.eu.auth0.com" + + testCase3 := test{ + name: "Wrong Auth Issuer Format", + inputConfig: testCase3Config, + assertErrFunc: require.Error, + assertErrFuncMessage: "should return error when wrong auth issuer format", + } + + testCase4Config := defaultTestConfig + testCase4Config.GrantType = "spa" + + testCase4 := test{ + name: "Wrong Grant Type", + inputConfig: testCase4Config, + assertErrFunc: require.Error, + assertErrFuncMessage: "should return error when wrong grant type", + } + + for _, testCase := range []test{testCase1, testCase2, testCase3, testCase4} { + t.Run(testCase.name, func(t *testing.T) { + _, err := NewAuth0Manager(testCase.inputConfig) + testCase.assertErrFunc(t, err, testCase.assertErrFuncMessage) + }) + } +} diff --git a/management/server/idp/idp.go b/management/server/idp/idp.go index fc6d82010..0b31b2357 100644 --- a/management/server/idp/idp.go +++ b/management/server/idp/idp.go @@ -56,7 +56,7 @@ func NewManager(config Config) (Manager, error) { case "none", "": return nil, nil case "auth0": - return NewAuth0Manager(config.Auth0ClientCredentials), nil + return NewAuth0Manager(config.Auth0ClientCredentials) default: return nil, fmt.Errorf("invalid manager type: %s", config.ManagerType) } diff --git a/management/server/testdata/management.json b/management/server/testdata/management.json index 631a8deda..d29491118 100644 --- a/management/server/testdata/management.json +++ b/management/server/testdata/management.json @@ -35,11 +35,11 @@ "AuthKeysLocation": "" }, "IdpManagerConfig": { - "Manager": "", + "ManagerType": "", "Auth0ClientCredentials": { "Audience": "", - "AuthIssuer": "", - "ClientId": "", + "AuthIssuer": "https://", + "ClientID": "", "ClientSecret": "", "GrantType": "client_credentials" }