Fix IDP Manager config structs with correct tags (#253)

* Fix IDP Manager config structs with correct tags

When loading the configuration from file
we will use the Auth0ClientConfig and when
sending the post to retrieve a token
 we use the auth0JWTRequest with proper tags

 Also, removed the idle timeout as it was closing
 all idle connections
This commit is contained in:
Maycon Santos 2022-03-09 17:22:47 +01:00 committed by GitHub
parent ff62fec956
commit 605ca03519
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 96 additions and 10 deletions

View File

@ -23,9 +23,18 @@ type Auth0Manager struct {
// Auth0ClientConfig auth0 manager client configurations // Auth0ClientConfig auth0 manager client configurations
type Auth0ClientConfig struct { 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"` AuthIssuer string `json:"auth_issuer"`
ClientId string `json:"client_id"` ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"` ClientSecret string `json:"client_secret"`
GrantType string `json:"grant_type"` GrantType string `json:"grant_type"`
} }
@ -40,11 +49,10 @@ type Auth0Credentials struct {
} }
// NewAuth0Manager creates a new instance of the Auth0Manager // 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 := http.DefaultTransport.(*http.Transport).Clone()
httpTransport.MaxIdleConns = 5 httpTransport.MaxIdleConns = 5
httpTransport.IdleConnTimeout = 30
httpClient := &http.Client{ httpClient := &http.Client{
Timeout: 10 * time.Second, Timeout: 10 * time.Second,
@ -53,6 +61,18 @@ func NewAuth0Manager(config Auth0ClientConfig) *Auth0Manager {
helper := JsonParser{} 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{ credentials := &Auth0Credentials{
clientConfig: config, clientConfig: config,
httpClient: httpClient, httpClient: httpClient,
@ -63,7 +83,7 @@ func NewAuth0Manager(config Auth0ClientConfig) *Auth0Manager {
credentials: credentials, credentials: credentials,
httpClient: httpClient, httpClient: httpClient,
helper: helper, helper: helper,
} }, nil
} }
// jwtStillValid returns true if the token still valid and have enough time to be used and get a response from Auth0 // 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 var res *http.Response
url := c.clientConfig.AuthIssuer + "/oauth/token" url := c.clientConfig.AuthIssuer + "/oauth/token"
p, err := c.helper.Marshal(c.clientConfig) p, err := c.helper.Marshal(auth0JWTRequest(c.clientConfig))
if err != nil { if err != nil {
return res, err return res, err
} }
@ -89,6 +109,8 @@ func (c *Auth0Credentials) requestJWTToken() (*http.Response, error) {
req.Header.Add("content-type", "application/json") req.Header.Add("content-type", "application/json")
log.Debug("requesting new jwt token for idp manager")
res, err = c.httpClient.Do(req) res, err = c.httpClient.Do(req)
if err != nil { if err != nil {
return res, err 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("authorization", "Bearer "+jwtToken.AccessToken)
req.Header.Add("content-type", "application/json") req.Header.Add("content-type", "application/json")
log.Debugf("updating metadata for user %s", userId)
res, err := am.httpClient.Do(req) res, err := am.httpClient.Do(req)
if err != nil { if err != nil {
return err return err

View File

@ -3,6 +3,7 @@ package idp
import ( import (
"encoding/json" "encoding/json"
"fmt" "fmt"
"github.com/stretchr/testify/require"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
"strings" "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)
})
}
}

View File

@ -56,7 +56,7 @@ func NewManager(config Config) (Manager, error) {
case "none", "": case "none", "":
return nil, nil return nil, nil
case "auth0": case "auth0":
return NewAuth0Manager(config.Auth0ClientCredentials), nil return NewAuth0Manager(config.Auth0ClientCredentials)
default: default:
return nil, fmt.Errorf("invalid manager type: %s", config.ManagerType) return nil, fmt.Errorf("invalid manager type: %s", config.ManagerType)
} }

View File

@ -35,11 +35,11 @@
"AuthKeysLocation": "<PASTE YOUR AUTH0 PUBLIC JWT KEYS LOCATION HERE>" "AuthKeysLocation": "<PASTE YOUR AUTH0 PUBLIC JWT KEYS LOCATION HERE>"
}, },
"IdpManagerConfig": { "IdpManagerConfig": {
"Manager": "<none|auth0>", "ManagerType": "<none|auth0>",
"Auth0ClientCredentials": { "Auth0ClientCredentials": {
"Audience": "<PASTE YOUR AUTH0 AUDIENCE HERE>", "Audience": "<PASTE YOUR AUTH0 AUDIENCE HERE>",
"AuthIssuer": "<PASTE YOUR AUTH0 Auth Issuer HERE>", "AuthIssuer": "https://<PASTE YOUR AUTH0 Auth Issuer HERE>",
"ClientId": "<PASTE YOUR AUTH0 Application Client ID HERE>", "ClientID": "<PASTE YOUR AUTH0 Application Client ID HERE>",
"ClientSecret": "<PASTE YOUR AUTH0 Application Client Secret HERE>", "ClientSecret": "<PASTE YOUR AUTH0 Application Client Secret HERE>",
"GrantType": "client_credentials" "GrantType": "client_credentials"
} }