Commit 95757e87 authored by Bobby Rullo's avatar Bobby Rullo

*: Client Repo now deals with custom Client object

This is instead of oidc.ClientIdentity. This makes it easier to add new
fields custom to dex to the client.
parent 35cefb7d
......@@ -116,25 +116,38 @@ func (a *AdminAPI) GetState() (adminschema.State, error) {
return state, nil
}
type ClientRegistrationRequest struct {
IsAdmin bool `json:"isAdmin"`
Client oidc.ClientMetadata `json:"client"`
}
func (a *AdminAPI) CreateClient(req adminschema.ClientCreateRequest) (adminschema.ClientCreateResponse, error) {
cli, err := adminschema.MapSchemaClientToClient(*req.Client)
if err != nil {
// TODO should be 400s
return adminschema.ClientCreateResponse{}, mapError(err)
}
func (a *AdminAPI) CreateClient(req ClientRegistrationRequest) (oidc.ClientRegistrationResponse, error) {
if err := req.Client.Valid(); err != nil {
return oidc.ClientRegistrationResponse{}, mapError(err)
if err := cli.Metadata.Valid(); err != nil {
// TODO make sure this is not 500
return adminschema.ClientCreateResponse{}, mapError(err)
}
// metadata is guarenteed to have at least one redirect_uri by earlier validation.
id, err := oidc.GenClientID(req.Client.RedirectURIs[0].Host)
id, err := oidc.GenClientID(cli.Metadata.RedirectURIs[0].Host)
if err != nil {
return oidc.ClientRegistrationResponse{}, mapError(err)
return adminschema.ClientCreateResponse{}, mapError(err)
}
c, err := a.clientIdentityRepo.New(id, req.Client, req.IsAdmin)
cli.Credentials.ID = id
creds, err := a.clientIdentityRepo.New(cli)
if err != nil {
return oidc.ClientRegistrationResponse{}, mapError(err)
return adminschema.ClientCreateResponse{}, mapError(err)
}
return oidc.ClientRegistrationResponse{ClientID: c.ID, ClientSecret: c.Secret, ClientMetadata: req.Client}, nil
req.Client.Id = creds.ID
req.Client.Secret = creds.Secret
return adminschema.ClientCreateResponse{
Client: req.Client,
}, nil
// github.com/coreos/dex/integrationoidc.ClientRegistrationResponse{ClientID: c.ID, ClientSecret: c.Secret, ClientMetadata: req.Client.Metadata}, nil
}
func mapError(e error) error {
......
package client
import (
"encoding/json"
"errors"
"io"
"net/url"
"reflect"
......@@ -15,7 +17,15 @@ var (
ErrorNotFound = errors.New("no data found")
)
type Client struct {
Credentials oidc.ClientCredentials
Metadata oidc.ClientMetadata
Admin bool
}
type ClientIdentityRepo interface {
Get(clientID string) (Client, error)
// Metadata returns one matching ClientMetadata if the given client
// exists, otherwise nil. The returned error will be non-nil only
// if the repo was unable to determine client existence.
......@@ -28,12 +38,12 @@ type ClientIdentityRepo interface {
Authenticate(creds oidc.ClientCredentials) (bool, error)
// All returns all registered Client Identities.
All() ([]oidc.ClientIdentity, error)
All() ([]Client, error)
// New registers a ClientIdentity with the repo for the given metadata.
// An unused ID must be provided. A corresponding secret will be returned
// in a ClientCredentials struct along with the provided ID.
New(id string, meta oidc.ClientMetadata, admin bool) (*oidc.ClientCredentials, error)
New(client Client) (*oidc.ClientCredentials, error)
SetDexAdmin(clientID string, isAdmin bool) error
......@@ -64,3 +74,36 @@ func ValidRedirectURL(rURL *url.URL, redirectURLs []url.URL) (url.URL, error) {
}
return url.URL{}, ErrorInvalidRedirectURL
}
func ClientsFromReader(r io.Reader) ([]Client, error) {
var c []struct {
ID string `json:"id"`
Secret string `json:"secret"`
RedirectURLs []string `json:"redirectURLs"`
}
if err := json.NewDecoder(r).Decode(&c); err != nil {
return nil, err
}
clients := make([]Client, len(c))
for i, client := range c {
redirectURIs := make([]url.URL, len(client.RedirectURLs))
for j, u := range client.RedirectURLs {
uri, err := url.Parse(u)
if err != nil {
return nil, err
}
redirectURIs[j] = *uri
}
clients[i] = Client{
Credentials: oidc.ClientCredentials{
ID: client.ID,
Secret: client.Secret,
},
Metadata: oidc.ClientMetadata{
RedirectURIs: redirectURIs,
},
}
}
return clients, nil
}
......@@ -41,21 +41,29 @@ func init() {
})
}
func newClientIdentityModel(id string, secret []byte, meta *oidc.ClientMetadata) (*clientIdentityModel, error) {
hashed, err := bcrypt.GenerateFromPassword(secret, bcryptHashCost)
func newClientIdentityModel(cli client.Client) (*clientIdentityModel, error) {
secretBytes, err := base64.URLEncoding.DecodeString(cli.Credentials.Secret)
if err != nil {
return nil, err
}
bmeta, err := json.Marshal(meta)
hashed, err := bcrypt.GenerateFromPassword([]byte(
secretBytes),
bcryptHashCost)
if err != nil {
return nil, err
}
bmeta, err := json.Marshal(&cli.Metadata)
if err != nil {
return nil, err
}
cim := clientIdentityModel{
ID: id,
ID: cli.Credentials.ID,
Secret: hashed,
Metadata: string(bmeta),
DexAdmin: cli.Admin,
}
return &cim, nil
......@@ -68,12 +76,13 @@ type clientIdentityModel struct {
DexAdmin bool `db:"dex_admin"`
}
func (m *clientIdentityModel) ClientIdentity() (*oidc.ClientIdentity, error) {
ci := oidc.ClientIdentity{
func (m *clientIdentityModel) Client() (*client.Client, error) {
ci := client.Client{
Credentials: oidc.ClientCredentials{
ID: m.ID,
Secret: string(m.Secret),
},
Admin: m.DexAdmin,
}
if err := json.Unmarshal([]byte(m.Metadata), &ci.Metadata); err != nil {
......@@ -91,7 +100,7 @@ func newClientIdentityRepo(dbm *gorp.DbMap) *clientIdentityRepo {
return &clientIdentityRepo{db: &db{dbm}}
}
func NewClientIdentityRepoFromClients(dbm *gorp.DbMap, clients []oidc.ClientIdentity) (client.ClientIdentityRepo, error) {
func NewClientIdentityRepoFromClients(dbm *gorp.DbMap, clients []client.Client) (client.ClientIdentityRepo, error) {
repo := newClientIdentityRepo(dbm)
tx, err := repo.begin()
if err != nil {
......@@ -103,12 +112,7 @@ func NewClientIdentityRepoFromClients(dbm *gorp.DbMap, clients []oidc.ClientIden
if c.Credentials.Secret == "" {
return nil, fmt.Errorf("client %q has no secret", c.Credentials.ID)
}
dec, err := base64.URLEncoding.DecodeString(c.Credentials.Secret)
if err != nil {
return nil, fmt.Errorf("client secrets must be base64 decodable. See issue #337. Please consider replacing %q with %q",
c.Credentials.Secret, base64.URLEncoding.EncodeToString([]byte(c.Credentials.Secret)))
}
cm, err := newClientIdentityModel(c.Credentials.ID, dec, &c.Metadata)
cm, err := newClientIdentityModel(c)
if err != nil {
return nil, err
}
......@@ -127,27 +131,37 @@ type clientIdentityRepo struct {
*db
}
func (r *clientIdentityRepo) Metadata(clientID string) (*oidc.ClientMetadata, error) {
func (r *clientIdentityRepo) Get(clientID string) (client.Client, error) {
m, err := r.executor(nil).Get(clientIdentityModel{}, clientID)
if err == sql.ErrNoRows || m == nil {
return nil, client.ErrorNotFound
return client.Client{}, client.ErrorNotFound
}
if err != nil {
return nil, err
return client.Client{}, err
}
cim, ok := m.(*clientIdentityModel)
if !ok {
log.Errorf("expected clientIdentityModel but found %v", reflect.TypeOf(m))
return nil, errors.New("unrecognized model")
log.Errorf("expected clientModel but found %v", reflect.TypeOf(m))
return client.Client{}, errors.New("unrecognized model")
}
ci, err := cim.Client()
if err != nil {
return client.Client{}, err
}
ci, err := cim.ClientIdentity()
return *ci, nil
}
func (r *clientIdentityRepo) Metadata(clientID string) (*oidc.ClientMetadata, error) {
c, err := r.Get(clientID)
if err != nil {
return nil, err
}
return &ci.Metadata, nil
return &c.Metadata, nil
}
func (r *clientIdentityRepo) IsDexAdmin(clientID string) (bool, error) {
......@@ -238,17 +252,17 @@ func isAlreadyExistsErr(err error) bool {
return false
}
func (r *clientIdentityRepo) New(id string, meta oidc.ClientMetadata, admin bool) (*oidc.ClientCredentials, error) {
func (r *clientIdentityRepo) New(cli client.Client) (*oidc.ClientCredentials, error) {
secret, err := pcrypto.RandBytes(maxSecretLength)
if err != nil {
return nil, err
}
cim, err := newClientIdentityModel(id, secret, &meta)
cli.Credentials.Secret = base64.URLEncoding.EncodeToString(secret)
cim, err := newClientIdentityModel(cli)
if err != nil {
return nil, err
}
cim.DexAdmin = admin
if err := r.executor(nil).Insert(cim); err != nil {
if isAlreadyExistsErr(err) {
......@@ -258,14 +272,14 @@ func (r *clientIdentityRepo) New(id string, meta oidc.ClientMetadata, admin bool
}
cc := oidc.ClientCredentials{
ID: id,
Secret: base64.URLEncoding.EncodeToString(secret),
ID: cli.Credentials.ID,
Secret: cli.Credentials.Secret,
}
return &cc, nil
}
func (r *clientIdentityRepo) All() ([]oidc.ClientIdentity, error) {
func (r *clientIdentityRepo) All() ([]client.Client, error) {
qt := r.quote(clientIdentityTableName)
q := fmt.Sprintf("SELECT * FROM %s", qt)
objs, err := r.executor(nil).Select(&clientIdentityModel{}, q)
......@@ -273,14 +287,14 @@ func (r *clientIdentityRepo) All() ([]oidc.ClientIdentity, error) {
return nil, err
}
cs := make([]oidc.ClientIdentity, len(objs))
cs := make([]client.Client, len(objs))
for i, obj := range objs {
m, ok := obj.(*clientIdentityModel)
if !ok {
return nil, errors.New("unable to cast client identity to clientIdentityModel")
}
ci, err := m.ClientIdentity()
ci, err := m.Client()
if err != nil {
return nil, err
}
......
......@@ -11,10 +11,10 @@ import (
"github.com/go-gorp/gorp"
"golang.org/x/crypto/bcrypt"
"github.com/coreos/dex/client"
"github.com/coreos/dex/pkg/log"
"github.com/coreos/dex/refresh"
"github.com/coreos/dex/repo"
"github.com/coreos/go-oidc/oidc"
)
const (
......@@ -186,7 +186,7 @@ func (r *refreshTokenRepo) RevokeTokensForClient(userID, clientID string) error
return err
}
func (r *refreshTokenRepo) ClientsWithRefreshTokens(userID string) ([]oidc.ClientIdentity, error) {
func (r *refreshTokenRepo) ClientsWithRefreshTokens(userID string) ([]client.Client, error) {
q := `SELECT c.* FROM %s as c
INNER JOIN %s as r ON c.id = r.client_id WHERE r.user_id = $1;`
q = fmt.Sprintf(q, r.quote(clientIdentityTableName), r.quote(refreshTokenTableName))
......@@ -196,9 +196,9 @@ func (r *refreshTokenRepo) ClientsWithRefreshTokens(userID string) ([]oidc.Clien
return nil, err
}
c := make([]oidc.ClientIdentity, len(clients))
c := make([]client.Client, len(clients))
for i, client := range clients {
ident, err := client.ClientIdentity()
ident, err := client.Client()
if err != nil {
return nil, err
}
......
......@@ -191,7 +191,12 @@ func TestDBClientIdentityRepoMetadata(t *testing.T) {
},
}
_, err := r.New("foo", cm, false)
_, err := r.New(client.Client{
Credentials: oidc.ClientCredentials{
ID: "foo",
},
Metadata: cm,
})
if err != nil {
t.Fatalf(err.Error())
}
......@@ -227,7 +232,12 @@ func TestDBClientIdentityRepoNewDuplicate(t *testing.T) {
},
}
if _, err := r.New("foo", meta1, false); err != nil {
if _, err := r.New(client.Client{
Credentials: oidc.ClientCredentials{
ID: "foo",
},
Metadata: meta1,
}); err != nil {
t.Fatalf("unexpected error: %v", err)
}
......@@ -237,7 +247,12 @@ func TestDBClientIdentityRepoNewDuplicate(t *testing.T) {
},
}
if _, err := r.New("foo", meta2, false); err == nil {
if _, err := r.New(client.Client{
Credentials: oidc.ClientCredentials{
ID: "foo",
},
Metadata: meta2,
}); err == nil {
t.Fatalf("expected non-nil error")
}
}
......@@ -251,7 +266,12 @@ func TestDBClientIdentityRepoAuthenticate(t *testing.T) {
},
}
cc, err := r.New("baz", cm, false)
cc, err := r.New(client.Client{
Credentials: oidc.ClientCredentials{
ID: "baz",
},
Metadata: cm,
})
if err != nil {
t.Fatalf(err.Error())
}
......@@ -299,7 +319,12 @@ func TestDBClientIdentityAll(t *testing.T) {
},
}
_, err := r.New("foo", cm, false)
_, err := r.New(client.Client{
Credentials: oidc.ClientCredentials{
ID: "foo",
},
Metadata: cm,
})
if err != nil {
t.Fatalf(err.Error())
}
......@@ -322,7 +347,12 @@ func TestDBClientIdentityAll(t *testing.T) {
url.URL{Scheme: "http", Host: "foo.com", Path: "/cb"},
},
}
_, err = r.New("bar", cm, false)
_, err = r.New(client.Client{
Credentials: oidc.ClientCredentials{
ID: "bar",
},
Metadata: cm,
})
if err != nil {
t.Fatalf(err.Error())
}
......
......@@ -14,8 +14,8 @@ import (
)
var (
testClients = []oidc.ClientIdentity{
oidc.ClientIdentity{
testClients = []client.Client{
client.Client{
Credentials: oidc.ClientCredentials{
ID: "client1",
Secret: base64.URLEncoding.EncodeToString([]byte("secret-1")),
......@@ -30,7 +30,7 @@ var (
},
},
},
oidc.ClientIdentity{
client.Client{
Credentials: oidc.ClientCredentials{
ID: "client2",
Secret: base64.URLEncoding.EncodeToString([]byte("secret-2")),
......
......@@ -11,12 +11,13 @@ import (
"github.com/go-gorp/gorp"
"github.com/kylelemons/godebug/pretty"
"github.com/coreos/dex/client"
"github.com/coreos/dex/db"
"github.com/coreos/dex/refresh"
"github.com/coreos/dex/user"
)
func newRefreshRepo(t *testing.T, users []user.UserWithRemoteIdentities, clients []oidc.ClientIdentity) refresh.RefreshTokenRepo {
func newRefreshRepo(t *testing.T, users []user.UserWithRemoteIdentities, clients []client.Client) refresh.RefreshTokenRepo {
var dbMap *gorp.DbMap
if dsn := os.Getenv("DEX_TEST_DSN"); dsn == "" {
dbMap = db.NewMemDB()
......@@ -35,7 +36,7 @@ func newRefreshRepo(t *testing.T, users []user.UserWithRemoteIdentities, clients
func TestRefreshTokenRepo(t *testing.T) {
clientID := "client1"
userID := "user1"
clients := []oidc.ClientIdentity{
clients := []client.Client{
{
Credentials: oidc.ClientCredentials{
ID: clientID,
......
......@@ -276,21 +276,24 @@ func TestCreateClient(t *testing.T) {
for i, tt := range tests {
err := func() error {
f := makeAdminAPITestFixtures()
req := &adminschema.ClientCreateRequestClient{}
req := &adminschema.ClientCreateRequest{
Client: &adminschema.Client{},
}
for _, redirectURI := range tt.client.RedirectURIs {
req.Redirect_uris = append(req.Redirect_uris, redirectURI.String())
req.Client.RedirectURIs = append(req.Client.RedirectURIs, redirectURI.String())
}
resp, err := f.adClient.Client.Create(&adminschema.ClientCreateRequest{Client: req}).Do()
resp, err := f.adClient.Client.Create(req).Do()
if err != nil {
if tt.wantError {
return nil
}
return err
}
if resp.Client_id == "" {
if resp.Client.Id == "" {
return errors.New("no client id returned")
}
if resp.Client_secret == "" {
if resp.Client.Secret == "" {
return errors.New("no client secret returned")
}
return nil
......
......@@ -7,12 +7,13 @@ import (
"reflect"
"testing"
"github.com/coreos/dex/client"
schema "github.com/coreos/dex/schema/workerschema"
"github.com/coreos/go-oidc/oidc"
)
func TestClientCreate(t *testing.T) {
ci := oidc.ClientIdentity{
ci := client.Client{
Credentials: oidc.ClientCredentials{
ID: "72de74a9",
Secret: base64.URLEncoding.EncodeToString([]byte("XXX")),
......@@ -23,7 +24,7 @@ func TestClientCreate(t *testing.T) {
},
},
}
cis := []oidc.ClientIdentity{ci}
cis := []client.Client{ci}
srv, err := mockServer(cis)
if err != nil {
......
......@@ -9,6 +9,7 @@ import (
"testing"
"time"
"github.com/coreos/dex/client"
"github.com/coreos/dex/connector"
"github.com/coreos/dex/db"
phttp "github.com/coreos/dex/pkg/http"
......@@ -22,7 +23,7 @@ import (
"github.com/coreos/go-oidc/oidc"
)
func mockServer(cis []oidc.ClientIdentity) (*server.Server, error) {
func mockServer(cis []client.Client) (*server.Server, error) {
dbMap := db.NewMemDB()
k, err := key.GeneratePrivateKey()
if err != nil {
......@@ -50,7 +51,7 @@ func mockServer(cis []oidc.ClientIdentity) (*server.Server, error) {
return srv, nil
}
func mockClient(srv *server.Server, ci oidc.ClientIdentity) (*oidc.Client, error) {
func mockClient(srv *server.Server, ci client.Client) (*oidc.Client, error) {
hdlr := srv.HTTPHandler()
sClient := &phttp.HandlerClient{Handler: hdlr}
......@@ -75,7 +76,7 @@ func mockClient(srv *server.Server, ci oidc.ClientIdentity) (*oidc.Client, error
return oidc.NewClient(ccfg)
}
func verifyUserClaims(claims jose.Claims, ci *oidc.ClientIdentity, user *user.User, issuerURL url.URL) error {
func verifyUserClaims(claims jose.Claims, ci *client.Client, user *user.User, issuerURL url.URL) error {
expectedSub, expectedName := ci.Credentials.ID, ci.Credentials.ID
if user != nil {
expectedSub, expectedName = user.ID, user.DisplayName
......@@ -116,7 +117,7 @@ func TestHTTPExchangeTokenRefreshToken(t *testing.T) {
ID: "local",
}
ci := oidc.ClientIdentity{
ci := client.Client{
Credentials: oidc.ClientCredentials{
ID: "72de74a9",
Secret: base64.URLEncoding.EncodeToString([]byte("XXX")),
......@@ -124,7 +125,7 @@ func TestHTTPExchangeTokenRefreshToken(t *testing.T) {
}
dbMap := db.NewMemDB()
cir, err := db.NewClientIdentityRepoFromClients(dbMap, []oidc.ClientIdentity{ci})
cir, err := db.NewClientIdentityRepoFromClients(dbMap, []client.Client{ci})
if err != nil {
t.Fatalf("Failed to create client identity repo: " + err.Error())
}
......@@ -262,13 +263,13 @@ func TestHTTPExchangeTokenRefreshToken(t *testing.T) {
}
func TestHTTPClientCredsToken(t *testing.T) {
ci := oidc.ClientIdentity{
ci := client.Client{
Credentials: oidc.ClientCredentials{
ID: "72de74a9",
Secret: base64.URLEncoding.EncodeToString([]byte("XXX")),
},
}
cis := []oidc.ClientIdentity{ci}
cis := []client.Client{ci}
srv, err := mockServer(cis)
if err != nil {
......
......@@ -102,8 +102,8 @@ func makeUserAPITestFixtures() *userAPITestFixtures {
dbMap, _, _, um := makeUserObjects(userUsers, userPasswords)
cir := func() client.ClientIdentityRepo {
repo, err := db.NewClientIdentityRepoFromClients(dbMap, []oidc.ClientIdentity{
oidc.ClientIdentity{
repo, err := db.NewClientIdentityRepoFromClients(dbMap, []client.Client{
client.Client{
Credentials: oidc.ClientCredentials{
ID: testClientID,
Secret: testClientSecret,
......@@ -114,7 +114,7 @@ func makeUserAPITestFixtures() *userAPITestFixtures {
},
},
},
oidc.ClientIdentity{
client.Client{
Credentials: oidc.ClientCredentials{
ID: userBadClientID,
Secret: base64.URLEncoding.EncodeToString([]byte("secret")),
......
......@@ -4,7 +4,7 @@ import (
"crypto/rand"
"errors"
"github.com/coreos/go-oidc/oidc"
"github.com/coreos/dex/client"
)
const (
......@@ -54,5 +54,5 @@ type RefreshTokenRepo interface {
RevokeTokensForClient(userID, clientID string) error
// ClientsWithRefreshTokens returns a list of all clients the user has an outstanding client with.
ClientsWithRefreshTokens(userID string) ([]oidc.ClientIdentity, error)
ClientsWithRefreshTokens(userID string) ([]client.Client, error)
}
......@@ -116,7 +116,7 @@ func (s *AdminServer) getState(w http.ResponseWriter, r *http.Request, ps httpro
}
func (s *AdminServer) createClient(w http.ResponseWriter, r *http.Request, ps httprouter.Params) {
var req admin.ClientRegistrationRequest
var req = adminschema.ClientCreateRequest{}
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
writeInvalidRequest(w, "cannot parse JSON body")
return
......
......@@ -26,7 +26,7 @@ func TestClientToken(t *testing.T) {
now := time.Now()
tomorrow := now.Add(24 * time.Hour)
validClientID := "valid-client"
ci := oidc.ClientIdentity{
ci := client.Client{
Credentials: oidc.ClientCredentials{
ID: validClientID,
Secret: base64.URLEncoding.EncodeToString([]byte("secret")),
......@@ -37,7 +37,7 @@ func TestClientToken(t *testing.T) {
},
},
}
repo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []oidc.ClientIdentity{ci})
repo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []client.Client{ci})
if err != nil {
t.Fatalf("Failed to create client identity repo: %v", err)
}
......
......@@ -4,7 +4,9 @@ import (
"encoding/json"
"net/http"
"github.com/coreos/dex/client"
"github.com/coreos/dex/pkg/log"
"github.com/coreos/go-oidc/oauth2"
"github.com/coreos/go-oidc/oidc"
)
......@@ -43,7 +45,12 @@ func (s *Server) handleClientRegistrationRequest(r *http.Request) (*oidc.ClientR
return nil, newAPIError(oauth2.ErrorServerError, "unable to save client metadata")
}
creds, err := s.ClientIdentityRepo.New(id, clientMetadata, false)
creds, err := s.ClientIdentityRepo.New(client.Client{
Credentials: oidc.ClientCredentials{
ID: id,
},
Metadata: clientMetadata,
})
if err != nil {
log.Errorf("Failed to create new client identity: %v", err)
return nil, newAPIError(oauth2.ErrorServerError, "unable to save client metadata")
......
......@@ -49,7 +49,7 @@ func (c *clientResource) list(w http.ResponseWriter, r *http.Request) {
scs := make([]*schema.Client, len(cs))
for i, ci := range cs {
sc := schema.MapClientIdentityToSchemaClient(ci)
sc := schema.MapClientToSchemaClient(ci)
scs[i] = &sc
}
......@@ -76,7 +76,7 @@ func (c *clientResource) create(w http.ResponseWriter, r *http.Request) {
return
}
ci, err := schema.MapSchemaClientToClientIdentity(sc)
ci, err := schema.MapSchemaClientToClient(sc)
if err != nil {
log.Debugf("Invalid request data: %v", err)
writeAPIError(w, http.StatusBadRequest, newAPIError(errorInvalidClientMetadata, "missing or invalid field: redirectURIs"))
......@@ -96,7 +96,9 @@ func (c *clientResource) create(w http.ResponseWriter, r *http.Request) {
return
}
creds, err := c.repo.New(clientID, ci.Metadata, false)
ci.Credentials.ID = clientID
creds, err := c.repo.New(ci)
if err != nil {
log.Errorf("Failed creating client: %v", err)
writeAPIError(w, http.StatusInternalServerError, newAPIError(errorServerError, "unable to create client"))
......@@ -104,7 +106,7 @@ func (c *clientResource) create(w http.ResponseWriter, r *http.Request) {
}
ci.Credentials = *creds
ssc := schema.MapClientIdentityToSchemaClientWithSecret(ci)
ssc := schema.MapClientToSchemaClientWithSecret(ci)
w.Header().Add("Location", phttp.NewResourceLocation(r.URL, ci.Credentials.ID))
writeResponseWithBody(w, http.StatusCreated, ssc)
}
......@@ -14,6 +14,7 @@ import (
"strings"
"testing"
"github.com/coreos/dex/client"
"github.com/coreos/dex/db"
schema "github.com/coreos/dex/schema/workerschema"
"github.com/coreos/go-oidc/oidc"
......@@ -177,7 +178,7 @@ func TestList(t *testing.T) {
}
tests := []struct {
cs []oidc.ClientIdentity
cs []client.Client
want []*schema.Client
}{
// empty repo
......@@ -187,8 +188,8 @@ func TestList(t *testing.T) {
},
// single client
{
cs: []oidc.ClientIdentity{
oidc.ClientIdentity{
cs: []client.Client{
client.Client{
Credentials: oidc.ClientCredentials{ID: "foo", Secret: b64Encode("bar")},
Metadata: oidc.ClientMetadata{
RedirectURIs: []url.URL{
......@@ -206,8 +207,8 @@ func TestList(t *testing.T) {
},
// multi client
{
cs: []oidc.ClientIdentity{
oidc.ClientIdentity{
cs: []client.Client{
client.Client{
Credentials: oidc.ClientCredentials{ID: "foo", Secret: b64Encode("bar")},
Metadata: oidc.ClientMetadata{
RedirectURIs: []url.URL{
......@@ -215,7 +216,7 @@ func TestList(t *testing.T) {
},
},
},
oidc.ClientIdentity{
client.Client{
Credentials: oidc.ClientCredentials{ID: "biz", Secret: b64Encode("bang")},
Metadata: oidc.ClientMetadata{
RedirectURIs: []url.URL{
......
......@@ -13,10 +13,10 @@ import (
"time"
"github.com/coreos/go-oidc/key"
"github.com/coreos/go-oidc/oidc"
"github.com/coreos/pkg/health"
"github.com/go-gorp/gorp"
"github.com/coreos/dex/client"
"github.com/coreos/dex/connector"
"github.com/coreos/dex/db"
"github.com/coreos/dex/email"
......@@ -214,47 +214,14 @@ func loadUsersFromReader(r io.Reader) (users []user.UserWithRemoteIdentities, pw
return
}
// loadClients parses the clients.json file and returns the clients to be created.
func loadClients(filepath string) ([]oidc.ClientIdentity, error) {
// loadClients parses the clients.json file and returns a list of clients.
func loadClients(filepath string) ([]client.Client, error) {
f, err := os.Open(filepath)
if err != nil {
return nil, err
}
defer f.Close()
return loadClientsFromReader(f)
}
func loadClientsFromReader(r io.Reader) ([]oidc.ClientIdentity, error) {
var c []struct {
ID string `json:"id"`
Secret string `json:"secret"`
RedirectURLs []string `json:"redirectURLs"`
}
if err := json.NewDecoder(r).Decode(&c); err != nil {
return nil, err
}
clients := make([]oidc.ClientIdentity, len(c))
for i, client := range c {
redirectURIs := make([]url.URL, len(client.RedirectURLs))
for j, u := range client.RedirectURLs {
uri, err := url.Parse(u)
if err != nil {
return nil, err
}
redirectURIs[j] = *uri
}
clients[i] = oidc.ClientIdentity{
Credentials: oidc.ClientCredentials{
ID: client.ID,
Secret: client.Secret,
},
Metadata: oidc.ClientMetadata{
RedirectURIs: redirectURIs,
},
}
}
return clients, nil
return client.ClientsFromReader(f)
}
func (cfg *MultiServerConfig) Configure(srv *Server) error {
......
......@@ -79,8 +79,8 @@ func TestHandleAuthFuncResponsesSingleRedirectURL(t *testing.T) {
IssuerURL: url.URL{Scheme: "http", Host: "server.example.com"},
SessionManager: manager.NewSessionManager(db.NewSessionRepo(db.NewMemDB()), db.NewSessionKeyRepo(db.NewMemDB())),
ClientIdentityRepo: func() client.ClientIdentityRepo {
repo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []oidc.ClientIdentity{
oidc.ClientIdentity{
repo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []client.Client{
client.Client{
Credentials: oidc.ClientCredentials{
ID: "XXX",
Secret: base64.URLEncoding.EncodeToString([]byte("secrete")),
......@@ -231,8 +231,8 @@ func TestHandleAuthFuncResponsesMultipleRedirectURLs(t *testing.T) {
IssuerURL: url.URL{Scheme: "http", Host: "server.example.com"},
SessionManager: manager.NewSessionManager(db.NewSessionRepo(db.NewMemDB()), db.NewSessionKeyRepo(db.NewMemDB())),
ClientIdentityRepo: func() client.ClientIdentityRepo {
repo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []oidc.ClientIdentity{
oidc.ClientIdentity{
repo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []client.Client{
client.Client{
Credentials: oidc.ClientCredentials{
ID: "XXX",
Secret: base64.URLEncoding.EncodeToString([]byte("secrete")),
......
......@@ -130,7 +130,7 @@ func TestServerNewSession(t *testing.T) {
state := "pants"
nonce := "oncenay"
ci := oidc.ClientIdentity{
ci := client.Client{
Credentials: oidc.ClientCredentials{
ID: "XXX",
Secret: "secrete",
......@@ -179,7 +179,7 @@ func TestServerNewSession(t *testing.T) {
}
func TestServerLogin(t *testing.T) {
ci := oidc.ClientIdentity{
ci := client.Client{
Credentials: oidc.ClientCredentials{
ID: "XXX",
Secret: clientTestSecret,
......@@ -195,7 +195,7 @@ func TestServerLogin(t *testing.T) {
},
}
ciRepo := func() client.ClientIdentityRepo {
repo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []oidc.ClientIdentity{ci})
repo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []client.Client{ci})
if err != nil {
t.Fatalf("Failed to create client identity repo: %v", err)
}
......@@ -245,8 +245,8 @@ func TestServerLogin(t *testing.T) {
func TestServerLoginUnrecognizedSessionKey(t *testing.T) {
ciRepo := func() client.ClientIdentityRepo {
repo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []oidc.ClientIdentity{
oidc.ClientIdentity{
repo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []client.Client{
client.Client{
Credentials: oidc.ClientCredentials{
ID: "XXX", Secret: clientTestSecret,
},
......@@ -281,7 +281,7 @@ func TestServerLoginUnrecognizedSessionKey(t *testing.T) {
}
func TestServerLoginDisabledUser(t *testing.T) {
ci := oidc.ClientIdentity{
ci := client.Client{
Credentials: oidc.ClientCredentials{
ID: "XXX",
Secret: clientTestSecret,
......@@ -297,7 +297,7 @@ func TestServerLoginDisabledUser(t *testing.T) {
},
}
ciRepo := func() client.ClientIdentityRepo {
repo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []oidc.ClientIdentity{ci})
repo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []client.Client{ci})
if err != nil {
t.Fatalf("Failed to create client identity repo: %v", err)
}
......@@ -355,14 +355,14 @@ func TestServerLoginDisabledUser(t *testing.T) {
}
func TestServerCodeToken(t *testing.T) {
ci := oidc.ClientIdentity{
ci := client.Client{
Credentials: oidc.ClientCredentials{
ID: "XXX",
Secret: clientTestSecret,
},
}
ciRepo := func() client.ClientIdentityRepo {
repo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []oidc.ClientIdentity{ci})
repo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []client.Client{ci})
if err != nil {
t.Fatalf("Failed to create client identity repo: %v", err)
}
......@@ -441,14 +441,14 @@ func TestServerCodeToken(t *testing.T) {
}
func TestServerTokenUnrecognizedKey(t *testing.T) {
ci := oidc.ClientIdentity{
ci := client.Client{
Credentials: oidc.ClientCredentials{
ID: "XXX",
Secret: clientTestSecret,
},
}
ciRepo := func() client.ClientIdentityRepo {
repo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []oidc.ClientIdentity{ci})
repo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []client.Client{ci})
if err != nil {
t.Fatalf("Failed to create client identity repo: %v", err)
}
......@@ -569,8 +569,8 @@ func TestServerTokenFail(t *testing.T) {
km := &StaticKeyManager{
signer: tt.signer,
}
ciRepo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []oidc.ClientIdentity{
oidc.ClientIdentity{Credentials: ccFixture},
ciRepo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []client.Client{
client.Client{Credentials: ccFixture},
})
if err != nil {
t.Errorf("case %d: failed to create client identity repo: %v", i, err)
......@@ -731,9 +731,9 @@ func TestServerRefreshToken(t *testing.T) {
signer: tt.signer,
}
ciRepo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []oidc.ClientIdentity{
oidc.ClientIdentity{Credentials: credXXX},
oidc.ClientIdentity{Credentials: credYYY},
ciRepo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []client.Client{
client.Client{Credentials: credXXX},
client.Client{Credentials: credYYY},
})
if err != nil {
t.Errorf("case %d: failed to create client identity repo: %v", i, err)
......@@ -784,9 +784,9 @@ func TestServerRefreshToken(t *testing.T) {
signer: signerFixture,
}
ciRepo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []oidc.ClientIdentity{
oidc.ClientIdentity{Credentials: credXXX},
oidc.ClientIdentity{Credentials: credYYY},
ciRepo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []client.Client{
client.Client{Credentials: credXXX},
client.Client{Credentials: credYYY},
})
if err != nil {
t.Fatalf("failed to create client identity repo: %v", err)
......
......@@ -136,8 +136,8 @@ func makeTestFixtures() (*testFixtures, error) {
return nil, err
}
clientIdentityRepo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []oidc.ClientIdentity{
oidc.ClientIdentity{
clientIdentityRepo, err := db.NewClientIdentityRepoFromClients(db.NewMemDB(), []client.Client{
client.Client{
Credentials: oidc.ClientCredentials{
ID: "XXX",
Secret: base64.URLEncoding.EncodeToString([]byte("secrete")),
......
......@@ -11,6 +11,7 @@ import (
"github.com/jonboulle/clockwork"
"github.com/kylelemons/godebug/pretty"
"github.com/coreos/dex/client"
"github.com/coreos/dex/connector"
"github.com/coreos/dex/db"
schema "github.com/coreos/dex/schema/workerschema"
......@@ -155,7 +156,7 @@ func makeTestFixtures() (*UsersAPI, *testEmailer) {
mgr := manager.NewUserManager(ur, pwr, ccr, db.TransactionFactory(dbMap), manager.ManagerOptions{})
mgr.Clock = clock
ci := oidc.ClientIdentity{
ci := client.Client{
Credentials: oidc.ClientCredentials{
ID: "XXX",
Secret: base64.URLEncoding.EncodeToString([]byte("secrete")),
......@@ -166,8 +167,9 @@ func makeTestFixtures() (*UsersAPI, *testEmailer) {
},
},
}
if _, err := db.NewClientIdentityRepoFromClients(dbMap, []oidc.ClientIdentity{ci}); err != nil {
panic("Failed to create client identity repo: " + err.Error())
if _, err := db.NewClientIdentityRepoFromClients(dbMap, []client.Client{ci}); err != nil {
panic("Failed to create client repo: " + err.Error())
}
// Used in TestRevokeRefreshToken test.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment