auth0: support explicit domains in the service account (#2980)

* auth0: support explicit domains in the service account

* also handle FromOptions
This commit is contained in:
Caleb Doxsey 2022-02-02 08:58:05 -07:00 committed by GitHub
parent 72dc9413cc
commit d1c4c55fd9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 52 additions and 15 deletions

View file

@ -4,8 +4,6 @@ package auth0
import ( import (
"context" "context"
"encoding/base64"
"encoding/json"
"errors" "errors"
"fmt" "fmt"
"sort" "sort"
@ -13,6 +11,7 @@ import (
"github.com/rs/zerolog" "github.com/rs/zerolog"
"gopkg.in/auth0.v5/management" "gopkg.in/auth0.v5/management"
"github.com/pomerium/pomerium/internal/encoding"
"github.com/pomerium/pomerium/internal/log" "github.com/pomerium/pomerium/internal/log"
"github.com/pomerium/pomerium/pkg/grpc/directory" "github.com/pomerium/pomerium/pkg/grpc/directory"
) )
@ -36,6 +35,10 @@ type (
type newManagersFunc = func(ctx context.Context, domain string, serviceAccount *ServiceAccount) (RoleManager, UserManager, error) type newManagersFunc = func(ctx context.Context, domain string, serviceAccount *ServiceAccount) (RoleManager, UserManager, error)
func defaultNewManagersFunc(ctx context.Context, domain string, serviceAccount *ServiceAccount) (RoleManager, UserManager, error) { func defaultNewManagersFunc(ctx context.Context, domain string, serviceAccount *ServiceAccount) (RoleManager, UserManager, error) {
// override the domain for the management api if supplied
if serviceAccount.Domain != "" {
domain = serviceAccount.Domain
}
m, err := management.New(domain, m, err := management.New(domain,
management.WithClientCredentials(serviceAccount.ClientID, serviceAccount.Secret), management.WithClientCredentials(serviceAccount.ClientID, serviceAccount.Secret),
management.WithContext(ctx)) management.WithContext(ctx))
@ -224,8 +227,10 @@ func getRoleUserIDs(rm RoleManager, roleID string) ([]string, error) {
// A ServiceAccount is used by the Auth0 provider to query the API. // A ServiceAccount is used by the Auth0 provider to query the API.
type ServiceAccount struct { type ServiceAccount struct {
ClientID string `json:"client_id"` Domain string `json:"domain"`
Secret string `json:"secret"` ClientID string `json:"client_id"`
ClientSecret string `json:"client_secret"`
Secret string `json:"secret"`
} }
// ParseServiceAccount parses the service account in the config options. // ParseServiceAccount parses the service account in the config options.
@ -245,6 +250,15 @@ func parseServiceAccountFromOptions(clientID, clientSecret string) (*ServiceAcco
if serviceAccount.ClientID == "" { if serviceAccount.ClientID == "" {
return nil, fmt.Errorf("auth0: client_id is required") return nil, fmt.Errorf("auth0: client_id is required")
} }
// for backwards compatibility we support secret and client_secret
if serviceAccount.Secret == "" {
serviceAccount.Secret = serviceAccount.ClientSecret
}
if serviceAccount.ClientSecret == "" {
serviceAccount.ClientSecret = serviceAccount.Secret
}
if serviceAccount.Secret == "" { if serviceAccount.Secret == "" {
return nil, fmt.Errorf("auth0: client_secret is required") return nil, fmt.Errorf("auth0: client_secret is required")
} }
@ -253,13 +267,8 @@ func parseServiceAccountFromOptions(clientID, clientSecret string) (*ServiceAcco
} }
func parseServiceAccountFromString(rawServiceAccount string) (*ServiceAccount, error) { func parseServiceAccountFromString(rawServiceAccount string) (*ServiceAccount, error) {
bs, err := base64.StdEncoding.DecodeString(rawServiceAccount)
if err != nil {
return nil, fmt.Errorf("auth0: could not decode base64: %w", err)
}
var serviceAccount ServiceAccount var serviceAccount ServiceAccount
if err := json.Unmarshal(bs, &serviceAccount); err != nil { if err := encoding.DecodeBase64OrJSON(rawServiceAccount, &serviceAccount); err != nil {
return nil, fmt.Errorf("auth0: could not unmarshal json: %w", err) return nil, fmt.Errorf("auth0: could not unmarshal json: %w", err)
} }
@ -267,6 +276,14 @@ func parseServiceAccountFromString(rawServiceAccount string) (*ServiceAccount, e
return nil, errors.New("auth0: client_id is required") return nil, errors.New("auth0: client_id is required")
} }
// for backwards compatibility we support secret and client_secret
if serviceAccount.Secret == "" {
serviceAccount.Secret = serviceAccount.ClientSecret
}
if serviceAccount.ClientSecret == "" {
serviceAccount.ClientSecret = serviceAccount.Secret
}
if serviceAccount.Secret == "" { if serviceAccount.Secret == "" {
return nil, errors.New("auth0: secret is required") return nil, errors.New("auth0: secret is required")
} }

View file

@ -155,8 +155,8 @@ func stringPtr(in string) *string {
} }
func TestProvider_UserGroups(t *testing.T) { func TestProvider_UserGroups(t *testing.T) {
expectedDomain := "example.com" expectedDomain := "login.example.com"
expectedServiceAccount := &ServiceAccount{ClientID: "c_id", Secret: "secret"} expectedServiceAccount := &ServiceAccount{Domain: "login-example.auth0.com", ClientID: "c_id", Secret: "secret"}
tests := []struct { tests := []struct {
name string name string
@ -517,12 +517,32 @@ func TestParseServiceAccount(t *testing.T) {
{ {
"valid", "eyJjbGllbnRfaWQiOiJpLWFtLWNsaWVudC1pZCIsInNlY3JldCI6ImktYW0tc2VjcmV0In0K", "valid", "eyJjbGllbnRfaWQiOiJpLWFtLWNsaWVudC1pZCIsInNlY3JldCI6ImktYW0tc2VjcmV0In0K",
&ServiceAccount{ &ServiceAccount{
ClientID: "i-am-client-id", ClientID: "i-am-client-id",
Secret: "i-am-secret", ClientSecret: "i-am-secret",
Secret: "i-am-secret",
}, },
nil, nil,
}, },
{"base64 err", "!!!!", nil, errors.New("auth0: could not decode base64: illegal base64 data at input byte 0")}, {
"json", `{"client_id": "i-am-client-id", "client_secret": "i-am-secret"}`,
&ServiceAccount{
ClientID: "i-am-client-id",
ClientSecret: "i-am-secret",
Secret: "i-am-secret",
},
nil,
},
{
"domain", `{"domain": "example.auth0.com", "client_id": "i-am-client-id", "client_secret": "i-am-secret"}`,
&ServiceAccount{
ClientID: "i-am-client-id",
ClientSecret: "i-am-secret",
Domain: "example.auth0.com",
Secret: "i-am-secret",
},
nil,
},
{"base64 err", "!!!!", nil, errors.New("auth0: could not unmarshal json: illegal base64 data at input byte 0")},
{"json err", "PAo=", nil, errors.New("auth0: could not unmarshal json: invalid character '<' looking for beginning of value")}, {"json err", "PAo=", nil, errors.New("auth0: could not unmarshal json: invalid character '<' looking for beginning of value")},
{"no client_id", "eyJzZWNyZXQiOiJpLWFtLXNlY3JldCJ9Cg==", nil, errors.New("auth0: client_id is required")}, {"no client_id", "eyJzZWNyZXQiOiJpLWFtLXNlY3JldCJ9Cg==", nil, errors.New("auth0: client_id is required")},
{"no secret", "eyJjbGllbnRfaWQiOiJpLWFtLWNsaWVudC1pZCJ9Cg==", nil, errors.New("auth0: secret is required")}, {"no secret", "eyJjbGllbnRfaWQiOiJpLWFtLWNsaWVudC1pZCJ9Cg==", nil, errors.New("auth0: secret is required")},