admin: create public clients with admin api
This commit is contained in:
parent
ff933812f5
commit
c0668997ae
4 changed files with 94 additions and 10 deletions
20
admin/api.go
20
admin/api.go
|
@ -69,10 +69,15 @@ func errorMaker(typ string, desc string, code int) func(internal error) Error {
|
|||
var (
|
||||
ErrorMissingClient = errorMaker("bad_request", "The 'client' cannot be empty", http.StatusBadRequest)(nil)
|
||||
|
||||
// Called when oidc.ClientMetadata.Valid() fails.
|
||||
ErrorInvalidClientFunc = errorMaker("bad_request", "Your client could not be validated.", http.StatusBadRequest)
|
||||
|
||||
errorMap = map[error]func(error) Error{
|
||||
client.ErrorMissingRedirectURI: errorMaker("bad_request", "Non-public clients must have at least one redirect URI", http.StatusBadRequest),
|
||||
|
||||
client.ErrorPublicClientRedirectURIs: errorMaker("bad_request", "Public clients cannot specify redirect URIs", http.StatusBadRequest),
|
||||
|
||||
client.ErrorPublicClientMissingName: errorMaker("bad_request", "Public clients require a ClientName", 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),
|
||||
|
@ -86,7 +91,6 @@ var (
|
|||
|
||||
func (a *AdminAPI) GetAdmin(id string) (adminschema.Admin, error) {
|
||||
usr, err := a.userRepo.Get(nil, id)
|
||||
|
||||
if err != nil {
|
||||
return adminschema.Admin{}, mapError(err)
|
||||
}
|
||||
|
@ -136,15 +140,9 @@ func (a *AdminAPI) CreateClient(req adminschema.ClientCreateRequest) (adminschem
|
|||
return adminschema.ClientCreateResponse{}, mapError(err)
|
||||
}
|
||||
|
||||
if err := cli.Metadata.Valid(); err != nil {
|
||||
return adminschema.ClientCreateResponse{}, ErrorInvalidClientFunc(err)
|
||||
}
|
||||
|
||||
// metadata is guaranteed to have at least one redirect_uri by earlier validation.
|
||||
creds, err := a.clientManager.New(cli, &clientmanager.ClientOptions{
|
||||
TrustedPeers: req.Client.TrustedPeers,
|
||||
})
|
||||
|
||||
if err != nil {
|
||||
return adminschema.ClientCreateResponse{}, mapError(err)
|
||||
}
|
||||
|
@ -165,6 +163,12 @@ func (a *AdminAPI) GetConnectors() ([]connector.ConnectorConfig, error) {
|
|||
}
|
||||
|
||||
func mapError(e error) error {
|
||||
switch t := e.(type) {
|
||||
case client.ValidationError:
|
||||
return ErrorInvalidClientFunc(t)
|
||||
default:
|
||||
}
|
||||
|
||||
if mapped, ok := errorMap[e]; ok {
|
||||
return mapped(e)
|
||||
}
|
||||
|
|
|
@ -383,7 +383,11 @@ func TestCreateClient(t *testing.T) {
|
|||
}
|
||||
|
||||
addIDAndSecret := func(cli adminschema.Client) *adminschema.Client {
|
||||
cli.Id = "client_auth.example.com"
|
||||
if cli.Public {
|
||||
cli.Id = "client_" + cli.ClientName
|
||||
} else {
|
||||
cli.Id = "client_auth.example.com"
|
||||
}
|
||||
cli.Secret = base64.URLEncoding.EncodeToString([]byte("client_0"))
|
||||
return &cli
|
||||
}
|
||||
|
@ -400,6 +404,23 @@ func TestCreateClient(t *testing.T) {
|
|||
},
|
||||
}
|
||||
|
||||
clientPublicGood := clientGood
|
||||
clientPublicGood.Public = true
|
||||
clientPublicGood.Metadata.ClientName = "PublicName"
|
||||
clientPublicGood.Metadata.RedirectURIs = []url.URL{}
|
||||
clientPublicGood.Credentials.ID = "client_PublicName"
|
||||
|
||||
adminPublicClientGood := adminClientGood
|
||||
adminPublicClientGood.Public = true
|
||||
adminPublicClientGood.ClientName = "PublicName"
|
||||
adminPublicClientGood.RedirectURIs = []string{}
|
||||
|
||||
adminPublicClientMissingName := adminPublicClientGood
|
||||
adminPublicClientMissingName.ClientName = ""
|
||||
|
||||
adminPublicClientHasARedirect := adminPublicClientGood
|
||||
adminPublicClientHasARedirect.RedirectURIs = []string{"https://auth.example.com/"}
|
||||
|
||||
adminAdminClient := adminClientGood
|
||||
adminAdminClient.IsAdmin = true
|
||||
clientGoodAdmin := clientGood
|
||||
|
@ -479,6 +500,27 @@ func TestCreateClient(t *testing.T) {
|
|||
wantClient: clientGood,
|
||||
wantTrustedPeers: []string{"test_client_0"},
|
||||
},
|
||||
{
|
||||
req: adminschema.ClientCreateRequest{
|
||||
Client: &adminPublicClientGood,
|
||||
},
|
||||
want: adminschema.ClientCreateResponse{
|
||||
Client: addIDAndSecret(adminPublicClientGood),
|
||||
},
|
||||
wantClient: clientPublicGood,
|
||||
},
|
||||
{
|
||||
req: adminschema.ClientCreateRequest{
|
||||
Client: &adminPublicClientMissingName,
|
||||
},
|
||||
wantError: http.StatusBadRequest,
|
||||
},
|
||||
{
|
||||
req: adminschema.ClientCreateRequest{
|
||||
Client: &adminPublicClientHasARedirect,
|
||||
},
|
||||
wantError: http.StatusBadRequest,
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
|
@ -530,6 +572,7 @@ func TestCreateClient(t *testing.T) {
|
|||
repoClient, err := f.cr.Get(nil, resp.Client.Id)
|
||||
if err != nil {
|
||||
t.Errorf("case %d: Unexpected error getting client: %v", i, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if diff := pretty.Compare(tt.wantClient, repoClient); diff != "" {
|
||||
|
|
|
@ -24,6 +24,7 @@ func MapSchemaClientToClient(sc Client) (client.Client, error) {
|
|||
Metadata: oidc.ClientMetadata{
|
||||
RedirectURIs: make([]url.URL, len(sc.RedirectURIs)),
|
||||
},
|
||||
Public: sc.Public,
|
||||
}
|
||||
for i, ru := range sc.RedirectURIs {
|
||||
if ru == "" {
|
||||
|
@ -65,6 +66,8 @@ func MapClientToSchemaClient(c client.Client) Client {
|
|||
Id: c.Credentials.ID,
|
||||
Secret: c.Credentials.Secret,
|
||||
RedirectURIs: make([]string, len(c.Metadata.RedirectURIs)),
|
||||
IsAdmin: c.Admin,
|
||||
Public: c.Public,
|
||||
}
|
||||
for i, u := range c.Metadata.RedirectURIs {
|
||||
cl.RedirectURIs[i] = u.String()
|
||||
|
@ -78,6 +81,5 @@ func MapClientToSchemaClient(c client.Client) Client {
|
|||
if c.Metadata.ClientURI != nil {
|
||||
cl.ClientURI = c.Metadata.ClientURI.String()
|
||||
}
|
||||
cl.IsAdmin = c.Admin
|
||||
return cl
|
||||
}
|
||||
|
|
|
@ -43,6 +43,23 @@ func TestMapSchemaClientToClient(t *testing.T) {
|
|||
ClientURI: mustParseURL(t, "https://clientURI.example.com"),
|
||||
},
|
||||
},
|
||||
}, {
|
||||
sc: Client{
|
||||
Id: "456",
|
||||
Secret: "sec_456",
|
||||
ClientName: "Dave",
|
||||
Public: true,
|
||||
},
|
||||
want: client.Client{
|
||||
Credentials: oidc.ClientCredentials{
|
||||
ID: "456",
|
||||
Secret: "sec_456",
|
||||
},
|
||||
Metadata: oidc.ClientMetadata{
|
||||
ClientName: "Dave",
|
||||
},
|
||||
Public: true,
|
||||
},
|
||||
}, {
|
||||
sc: Client{
|
||||
Id: "123",
|
||||
|
@ -108,6 +125,24 @@ func TestMapClientToClientSchema(t *testing.T) {
|
|||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
want: Client{
|
||||
Id: "456",
|
||||
Secret: "sec_456",
|
||||
ClientName: "Dave",
|
||||
Public: true,
|
||||
},
|
||||
c: client.Client{
|
||||
Credentials: oidc.ClientCredentials{
|
||||
ID: "456",
|
||||
Secret: "sec_456",
|
||||
},
|
||||
Metadata: oidc.ClientMetadata{
|
||||
ClientName: "Dave",
|
||||
},
|
||||
Public: true,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for i, tt := range tests {
|
||||
|
|
Reference in a new issue