client: add public client to data model

This commit is contained in:
Bobby Rullo 2016-06-15 15:39:04 -07:00
parent a530cc8d7c
commit 09e889e7bc
6 changed files with 92 additions and 9 deletions

View file

@ -15,13 +15,26 @@ import (
)
var (
ErrorInvalidClientID = errors.New("not a valid client ID")
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.")
ErrorNotFound = errors.New("no data found")
ErrorInvalidClientID = errors.New("not a valid client ID")
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.")
ErrorPublicClientRedirectURIs = errors.New("native clients cannot have redirect URIs")
ErrorPublicClientMissingName = errors.New("native clients must have a name")
ErrorMissingRedirectURI = errors.New("no client redirect url given")
ErrorNotFound = errors.New("no data found")
)
type ValidationError struct {
Err error
}
func (v ValidationError) Error() string {
return v.Err.Error()
}
const (
bcryptHashCost = 10
)
@ -44,6 +57,7 @@ type Client struct {
Credentials oidc.ClientCredentials
Metadata oidc.ClientMetadata
Admin bool
Public bool
}
type ClientRepo interface {
@ -106,6 +120,7 @@ func ClientsFromReader(r io.Reader) ([]LoadableClient, error) {
Secret string `json:"secret"`
RedirectURLs []string `json:"redirectURLs"`
Admin bool `json:"admin"`
Public bool `json:"public"`
TrustedPeers []string `json:"trustedPeers"`
}
if err := json.NewDecoder(r).Decode(&c); err != nil {
@ -137,7 +152,8 @@ func ClientsFromReader(r io.Reader) ([]LoadableClient, error) {
Metadata: oidc.ClientMetadata{
RedirectURIs: redirectURIs,
},
Admin: client.Admin,
Admin: client.Admin,
Public: client.Public,
},
TrustedPeers: client.TrustedPeers,
}

View file

@ -35,6 +35,13 @@ var (
"trustedPeers":["goodClient1", "goodClient2"]
}`
publicClient = `{
"id": "public_client",
"secret": "` + goodSecret3 + `",
"redirectURLs": ["http://localhost:8080","urn:ietf:wg:oauth:2.0:oob"],
"public": true
}`
badURLClient = `{
"id": "my_id",
"secret": "` + goodSecret1 + `",
@ -139,6 +146,26 @@ func TestClientsFromReader(t *testing.T) {
},
},
},
{
json: "[" + publicClient + "]",
want: []LoadableClient{
{
Client: Client{
Credentials: oidc.ClientCredentials{
ID: "public_client",
Secret: goodSecret3,
},
Metadata: oidc.ClientMetadata{
RedirectURIs: []url.URL{
mustParseURL(t, "http://localhost:8080"),
mustParseURL(t, "urn:ietf:wg:oauth:2.0:oob"),
},
},
Public: true,
},
},
},
},
{
json: "[" + badURLClient + "]",
wantErr: true,

View file

@ -5,6 +5,7 @@ import (
"encoding/json"
"errors"
"fmt"
"net/url"
"reflect"
"github.com/coreos/go-oidc/oidc"
@ -23,6 +24,10 @@ const (
pgErrorCodeUniqueViolation = "23505" // unique_violation
)
var (
localHostRedirectURL = mustParseURL("http://localhost:0")
)
func init() {
register(table{
name: clientTableName,
@ -44,6 +49,16 @@ func newClientModel(cli client.Client) (*clientModel, error) {
if err != nil {
return nil, err
}
if cli.Public {
// Metadata.Valid(), and therefore json.Unmarshal(metadata) complains
// when there's no RedirectURIs, so we set them to a fixed value here,
// and remove it when translating back to a client.Client
cli.Metadata.RedirectURIs = []url.URL{
localHostRedirectURL,
}
}
bmeta, err := json.Marshal(&cli.Metadata)
if err != nil {
return nil, err
@ -54,6 +69,7 @@ func newClientModel(cli client.Client) (*clientModel, error) {
Secret: hashed,
Metadata: string(bmeta),
DexAdmin: cli.Admin,
Public: cli.Public,
}
return &cim, nil
@ -64,6 +80,7 @@ type clientModel struct {
Secret []byte `db:"secret"`
Metadata string `db:"metadata"`
DexAdmin bool `db:"dex_admin"`
Public bool `db:"public"`
}
type trustedPeerModel struct {
@ -76,13 +93,18 @@ func (m *clientModel) Client() (*client.Client, error) {
Credentials: oidc.ClientCredentials{
ID: m.ID,
},
Admin: m.DexAdmin,
Admin: m.DexAdmin,
Public: m.Public,
}
if err := json.Unmarshal([]byte(m.Metadata), &ci.Metadata); err != nil {
return nil, err
}
if ci.Public {
ci.Metadata.RedirectURIs = []url.URL{}
}
return &ci, nil
}
@ -168,7 +190,6 @@ func isAlreadyExistsErr(err error) bool {
func (r *clientRepo) New(tx repo.Transaction, cli client.Client) (*oidc.ClientCredentials, error) {
cim, err := newClientModel(cli)
if err != nil {
return nil, err
}
@ -328,3 +349,11 @@ func (r *clientRepo) SetTrustedPeers(tx repo.Transaction, clientID string, clien
return nil
}
func mustParseURL(s string) url.URL {
u, err := url.Parse(s)
if err != nil {
panic(err)
}
return *u
}

View file

@ -16,7 +16,8 @@ CREATE TABLE client_identity (
id text NOT NULL UNIQUE,
secret blob,
metadata text,
dex_admin integer
dex_admin integer,
public integer
);
CREATE TABLE connector_config (

View file

@ -0,0 +1,4 @@
-- +migrate Up
ALTER TABLE client_identity ADD COLUMN "public" boolean;
UPDATE "client_identity" SET "public" = false;

View file

@ -78,6 +78,12 @@ var PostgresMigrations migrate.MigrationSource = &migrate.MemoryMigrationSource{
"-- +migrate Up\nCREATE TABLE IF NOT EXISTS \"trusted_peers\" (\n \"client_id\" text not null,\n \"trusted_client_id\" text not null,\n primary key (\"client_id\", \"trusted_client_id\")) ;\n",
},
},
{
Id: "0013_add_public_clients.sql",
Up: []string{
"-- +migrate Up\nALTER TABLE client_identity ADD COLUMN \"public\" boolean;\n\nUPDATE \"client_identity\" SET \"public\" = false;\n",
},
},
{
Id: "0013_add_scopes_to_refresh_tokens.sql",
Up: []string{