mirror of https://github.com/dexidp/dex.git
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
110 lines
3.1 KiB
110 lines
3.1 KiB
package server |
|
|
|
import ( |
|
"encoding/json" |
|
"fmt" |
|
"net/http" |
|
"path" |
|
|
|
"github.com/coreos/dex/client" |
|
phttp "github.com/coreos/dex/pkg/http" |
|
"github.com/coreos/dex/pkg/log" |
|
schema "github.com/coreos/dex/schema/workerschema" |
|
"github.com/coreos/go-oidc/oidc" |
|
) |
|
|
|
type clientResource struct { |
|
repo client.ClientIdentityRepo |
|
} |
|
|
|
func registerClientResource(prefix string, repo client.ClientIdentityRepo) (string, http.Handler) { |
|
mux := http.NewServeMux() |
|
c := &clientResource{ |
|
repo: repo, |
|
} |
|
relPath := "clients" |
|
absPath := path.Join(prefix, relPath) |
|
mux.Handle(absPath, c) |
|
return relPath, mux |
|
} |
|
|
|
func (c *clientResource) ServeHTTP(w http.ResponseWriter, r *http.Request) { |
|
switch r.Method { |
|
case "GET": |
|
c.list(w, r) |
|
case "POST": |
|
c.create(w, r) |
|
default: |
|
msg := fmt.Sprintf("HTTP %s method not supported for this resource", r.Method) |
|
writeAPIError(w, http.StatusMethodNotAllowed, newAPIError(errorInvalidRequest, msg)) |
|
} |
|
} |
|
|
|
func (c *clientResource) list(w http.ResponseWriter, r *http.Request) { |
|
cs, err := c.repo.All() |
|
if err != nil { |
|
writeAPIError(w, http.StatusInternalServerError, newAPIError(errorServerError, "error listing clients")) |
|
return |
|
} |
|
|
|
scs := make([]*schema.Client, len(cs)) |
|
for i, ci := range cs { |
|
sc := schema.MapClientIdentityToSchemaClient(ci) |
|
scs[i] = &sc |
|
} |
|
|
|
page := schema.ClientPage{ |
|
Clients: scs, |
|
} |
|
writeResponseWithBody(w, http.StatusOK, page) |
|
} |
|
|
|
func (c *clientResource) create(w http.ResponseWriter, r *http.Request) { |
|
ct := r.Header.Get("content-type") |
|
if ct != "application/json" { |
|
log.Debugf("Unsupported request content-type: %v", ct) |
|
writeAPIError(w, http.StatusBadRequest, newAPIError(errorInvalidRequest, "unsupported content-type")) |
|
return |
|
} |
|
|
|
var sc schema.Client |
|
dec := json.NewDecoder(r.Body) |
|
err := dec.Decode(&sc) |
|
if err != nil { |
|
log.Debugf("Error decoding request body: %v", err) |
|
writeAPIError(w, http.StatusBadRequest, newAPIError(errorInvalidRequest, "unable to decode request body")) |
|
return |
|
} |
|
|
|
ci, err := schema.MapSchemaClientToClientIdentity(sc) |
|
if err != nil { |
|
log.Debugf("Invalid request data: %v", err) |
|
writeAPIError(w, http.StatusBadRequest, newAPIError(errorInvalidClientMetadata, "missing or invalid field: redirectURIs")) |
|
return |
|
} |
|
|
|
if err := ci.Metadata.Valid(); err != nil { |
|
log.Debugf("ClientMetadata invalid: %v", err) |
|
writeAPIError(w, http.StatusBadRequest, newAPIError(errorInvalidClientMetadata, err.Error())) |
|
return |
|
} |
|
|
|
clientID, err := oidc.GenClientID(ci.Metadata.RedirectURLs[0].Host) |
|
if err != nil { |
|
log.Errorf("Failed generating ID for new client: %v", err) |
|
writeAPIError(w, http.StatusInternalServerError, newAPIError(errorServerError, "unable to generate client ID")) |
|
return |
|
} |
|
|
|
creds, err := c.repo.New(clientID, ci.Metadata) |
|
if err != nil { |
|
log.Errorf("Failed creating client: %v", err) |
|
writeAPIError(w, http.StatusInternalServerError, newAPIError(errorServerError, "unable to create client")) |
|
return |
|
} |
|
ci.Credentials = *creds |
|
|
|
ssc := schema.MapClientIdentityToSchemaClientWithSecret(ci) |
|
w.Header().Add("Location", phttp.NewResourceLocation(r.URL, ci.Credentials.ID)) |
|
writeResponseWithBody(w, http.StatusCreated, ssc) |
|
}
|
|
|