forked from mystiq/dex
client: admin API allows user defined creds
You can specify your own client ID and secret!
This commit is contained in:
parent
3b8d704c9c
commit
41740179af
4 changed files with 94 additions and 34 deletions
|
@ -78,6 +78,8 @@ var (
|
|||
|
||||
client.ErrorPublicClientMissingName: errorMaker("bad_request", "Public clients require a ClientName", http.StatusBadRequest),
|
||||
|
||||
client.ErrorInvalidClientSecret: errorMaker("bad_request", "Secret must be a base64 encoded string", http.StatusBadRequest),
|
||||
|
||||
user.ErrorNotFound: errorMaker("resource_not_found", "Resource could not be found.", http.StatusNotFound),
|
||||
user.ErrorDuplicateEmail: errorMaker("bad_request", "Email already in use.", http.StatusBadRequest),
|
||||
user.ErrorInvalidEmail: errorMaker("bad_request", "invalid email.", http.StatusBadRequest),
|
||||
|
|
|
@ -16,7 +16,10 @@ import (
|
|||
)
|
||||
|
||||
var (
|
||||
ErrorInvalidClientID = errors.New("not a valid client ID")
|
||||
ErrorInvalidClientID = errors.New("not a valid client ID")
|
||||
|
||||
ErrorInvalidClientSecret = errors.New("not a valid client Secret")
|
||||
|
||||
ErrorInvalidRedirectURL = errors.New("not a valid redirect url for the given client")
|
||||
ErrorCantChooseRedirectURL = errors.New("must provide a redirect url; client has many")
|
||||
ErrorNoValidRedirectURLs = errors.New("no valid redirect URLs for this client.")
|
||||
|
@ -46,7 +49,7 @@ const (
|
|||
func HashSecret(creds oidc.ClientCredentials) ([]byte, error) {
|
||||
secretBytes, err := base64.URLEncoding.DecodeString(creds.Secret)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
return nil, ErrorInvalidClientSecret
|
||||
}
|
||||
hashed, err := bcrypt.GenerateFromPassword([]byte(
|
||||
secretBytes),
|
||||
|
|
|
@ -196,18 +196,30 @@ func (m *ClientManager) addClientCredentials(cli *client.Client) error {
|
|||
seed = cli.Metadata.RedirectURIs[0].Host
|
||||
}
|
||||
|
||||
// Generate Client ID
|
||||
clientID, err := m.clientIDGenerator(seed)
|
||||
if err != nil {
|
||||
return err
|
||||
var err error
|
||||
var clientID string
|
||||
if cli.Credentials.ID != "" {
|
||||
clientID = cli.Credentials.ID
|
||||
} else {
|
||||
// Generate Client ID
|
||||
clientID, err = m.clientIDGenerator(seed)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Generate Secret
|
||||
secret, err := m.secretGenerator()
|
||||
if err != nil {
|
||||
return err
|
||||
var clientSecret string
|
||||
if cli.Credentials.Secret != "" {
|
||||
clientSecret = cli.Credentials.Secret
|
||||
} else {
|
||||
// Generate Secret
|
||||
secret, err := m.secretGenerator()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
clientSecret = base64.URLEncoding.EncodeToString(secret)
|
||||
}
|
||||
clientSecret := base64.URLEncoding.EncodeToString(secret)
|
||||
|
||||
cli.Credentials = oidc.ClientCredentials{
|
||||
ID: clientID,
|
||||
Secret: clientSecret,
|
||||
|
|
|
@ -383,12 +383,17 @@ func TestCreateClient(t *testing.T) {
|
|||
}
|
||||
|
||||
addIDAndSecret := func(cli adminschema.Client) *adminschema.Client {
|
||||
if cli.Public {
|
||||
cli.Id = "client_" + cli.ClientName
|
||||
} else {
|
||||
cli.Id = "client_auth.example.com"
|
||||
if cli.Id == "" {
|
||||
if cli.Public {
|
||||
cli.Id = "client_" + cli.ClientName
|
||||
} else {
|
||||
cli.Id = "client_auth.example.com"
|
||||
}
|
||||
}
|
||||
|
||||
if cli.Secret == "" {
|
||||
cli.Secret = base64.URLEncoding.EncodeToString([]byte("client_0"))
|
||||
}
|
||||
cli.Secret = base64.URLEncoding.EncodeToString([]byte("client_0"))
|
||||
return &cli
|
||||
}
|
||||
|
||||
|
@ -436,6 +441,24 @@ func TestCreateClient(t *testing.T) {
|
|||
adminClientWithPeers := adminClientGood
|
||||
adminClientWithPeers.TrustedPeers = []string{"test_client_0"}
|
||||
|
||||
adminClientOwnID := adminClientGood
|
||||
adminClientOwnID.Id = "my_own_id"
|
||||
|
||||
clientGoodOwnID := clientGood
|
||||
clientGoodOwnID.Credentials.ID = "my_own_id"
|
||||
|
||||
adminClientOwnSecret := adminClientGood
|
||||
adminClientOwnSecret.Secret = base64.URLEncoding.EncodeToString([]byte("my_own_secret"))
|
||||
clientGoodOwnSecret := clientGood
|
||||
|
||||
adminClientOwnIDAndSecret := adminClientGood
|
||||
adminClientOwnIDAndSecret.Id = "my_own_id"
|
||||
adminClientOwnIDAndSecret.Secret = base64.URLEncoding.EncodeToString([]byte("my_own_secret"))
|
||||
clientGoodOwnIDAndSecret := clientGoodOwnID
|
||||
|
||||
adminClientBadSecret := adminClientGood
|
||||
adminClientBadSecret.Secret = "not_base64_encoded"
|
||||
|
||||
tests := []struct {
|
||||
req adminschema.ClientCreateRequest
|
||||
want adminschema.ClientCreateResponse
|
||||
|
@ -446,24 +469,21 @@ func TestCreateClient(t *testing.T) {
|
|||
{
|
||||
req: adminschema.ClientCreateRequest{},
|
||||
wantError: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
}, {
|
||||
req: adminschema.ClientCreateRequest{
|
||||
Client: &adminschema.Client{
|
||||
IsAdmin: true,
|
||||
},
|
||||
},
|
||||
wantError: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
}, {
|
||||
req: adminschema.ClientCreateRequest{
|
||||
Client: &adminschema.Client{
|
||||
RedirectURIs: []string{"909090"},
|
||||
},
|
||||
},
|
||||
wantError: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
}, {
|
||||
req: adminschema.ClientCreateRequest{
|
||||
Client: &adminClientGood,
|
||||
},
|
||||
|
@ -471,8 +491,7 @@ func TestCreateClient(t *testing.T) {
|
|||
Client: addIDAndSecret(adminClientGood),
|
||||
},
|
||||
wantClient: clientGood,
|
||||
},
|
||||
{
|
||||
}, {
|
||||
req: adminschema.ClientCreateRequest{
|
||||
Client: &adminAdminClient,
|
||||
},
|
||||
|
@ -480,8 +499,7 @@ func TestCreateClient(t *testing.T) {
|
|||
Client: addIDAndSecret(adminAdminClient),
|
||||
},
|
||||
wantClient: clientGoodAdmin,
|
||||
},
|
||||
{
|
||||
}, {
|
||||
req: adminschema.ClientCreateRequest{
|
||||
Client: &adminMultiRedirect,
|
||||
},
|
||||
|
@ -489,8 +507,7 @@ func TestCreateClient(t *testing.T) {
|
|||
Client: addIDAndSecret(adminMultiRedirect),
|
||||
},
|
||||
wantClient: clientMultiRedirect,
|
||||
},
|
||||
{
|
||||
}, {
|
||||
req: adminschema.ClientCreateRequest{
|
||||
Client: &adminClientWithPeers,
|
||||
},
|
||||
|
@ -499,8 +516,7 @@ func TestCreateClient(t *testing.T) {
|
|||
},
|
||||
wantClient: clientGood,
|
||||
wantTrustedPeers: []string{"test_client_0"},
|
||||
},
|
||||
{
|
||||
}, {
|
||||
req: adminschema.ClientCreateRequest{
|
||||
Client: &adminPublicClientGood,
|
||||
},
|
||||
|
@ -508,18 +524,45 @@ func TestCreateClient(t *testing.T) {
|
|||
Client: addIDAndSecret(adminPublicClientGood),
|
||||
},
|
||||
wantClient: clientPublicGood,
|
||||
},
|
||||
{
|
||||
}, {
|
||||
req: adminschema.ClientCreateRequest{
|
||||
Client: &adminPublicClientMissingName,
|
||||
},
|
||||
wantError: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
}, {
|
||||
req: adminschema.ClientCreateRequest{
|
||||
Client: &adminPublicClientHasARedirect,
|
||||
},
|
||||
wantError: http.StatusBadRequest,
|
||||
}, {
|
||||
req: adminschema.ClientCreateRequest{
|
||||
Client: &adminClientOwnID,
|
||||
},
|
||||
want: adminschema.ClientCreateResponse{
|
||||
Client: addIDAndSecret(adminClientOwnID),
|
||||
},
|
||||
wantClient: clientGoodOwnID,
|
||||
}, {
|
||||
req: adminschema.ClientCreateRequest{
|
||||
Client: &adminClientOwnSecret,
|
||||
},
|
||||
want: adminschema.ClientCreateResponse{
|
||||
Client: addIDAndSecret(adminClientOwnSecret),
|
||||
},
|
||||
wantClient: clientGoodOwnSecret,
|
||||
}, {
|
||||
req: adminschema.ClientCreateRequest{
|
||||
Client: &adminClientOwnIDAndSecret,
|
||||
},
|
||||
want: adminschema.ClientCreateResponse{
|
||||
Client: addIDAndSecret(adminClientOwnIDAndSecret),
|
||||
},
|
||||
wantClient: clientGoodOwnIDAndSecret,
|
||||
}, {
|
||||
req: adminschema.ClientCreateRequest{
|
||||
Client: &adminClientBadSecret,
|
||||
},
|
||||
wantError: http.StatusBadRequest,
|
||||
},
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue