diff --git a/client/client.go b/client/client.go new file mode 100644 index 00000000000..ec1cfcbadf1 --- /dev/null +++ b/client/client.go @@ -0,0 +1,65 @@ +package client + +import "github.com/ory-am/fosite" + +type Client struct { + ID string `json:"id" gorethink:"id"` + Name string `json:"client_name" gorethink:"client_name"` + Secret string `json:"client_secret,omitempty" gorethink:"client_secret"` + RedirectURIs []string `json:"redirect_uris" gorethink:"redirect_uris"` + GrantTypes []string `json:"grant_types" gorethink:"grant_types"` + ResponseTypes []string `json:"response_types" gorethink:"response_types"` + GrantedScopes []string `json:"granted_scopes" gorethink:"granted_scopes"` + Owner string `json:"owner" gorethink:"owner"` + PolicyURI string `json:"policy_uri" gorethink:"policy_uri"` + TermsOfServiceURI string `json:"tos_uri" gorethink:"tos_uri"` + ClientURI string `json:"client_uri" gorethink:"client_uri"` + LogoURI string `json:"logo_uri" gorethink:"logo_uri"` + Contacts []string `json:"contacts" gorethink:"contacts"` +} + +func (c *Client) GetID() string { + return c.ID +} + +func (c *Client) GetRedirectURIs() []string { + return c.RedirectURIs +} + +func (c *Client) GetHashedSecret() []byte { + return []byte(c.Secret) +} + +func (c *Client) GetGrantedScopes() fosite.Scopes { + return &fosite.DefaultScopes{ + Scopes: c.GrantedScopes, + } +} + +func (c *Client) GetGrantTypes() fosite.Arguments { + // https://openid.net/specs/openid-connect-registration-1_0.html#ClientMetadata + // + // JSON array containing a list of the OAuth 2.0 Grant Types that the Client is declaring + // that it will restrict itself to using. + // If omitted, the default is that the Client will use only the authorization_code Grant Type. + if len(c.GrantTypes) == 0 { + return fosite.Arguments{"authorization_code"} + } + return fosite.Arguments(c.GrantTypes) +} + +func (c *Client) GetResponseTypes() fosite.Arguments { + // https://openid.net/specs/openid-connect-registration-1_0.html#ClientMetadata + // + // ")) if err != nil { h.H.WriteError(ctx, w, r, errors.New(err)) return } - c.Secret = []byte(string(secret)) + c.Secret = string(secret) + } else if len(c.Secret) < 6 { + h.H.WriteError(ctx, w, r, errors.New("The client secret must be at least 6 characters long")) } - secret := c.Secret + secret := c.Secret if err := h.Manager.CreateClient(&c); err != nil { h.H.WriteError(ctx, w, r, err) return @@ -94,7 +95,7 @@ func (h *Handler) GetAll(w http.ResponseWriter, r *http.Request, ps httprouter.P } for k, cc := range c { - cc.Secret = []byte{} + cc.Secret = "" c[k] = cc } @@ -122,7 +123,7 @@ func (h *Handler) Get(w http.ResponseWriter, r *http.Request, ps httprouter.Para return } - c.(*fosite.DefaultClient).Secret = []byte{} + c.(*Client).Secret = "" h.H.Write(ctx, w, r, c) } diff --git a/client/manager.go b/client/manager.go index a343c023457..46b20fccfcf 100644 --- a/client/manager.go +++ b/client/manager.go @@ -7,15 +7,15 @@ import ( type Manager interface { Storage - Authenticate(id string, secret []byte) (*fosite.DefaultClient, error) + Authenticate(id string, secret []byte) (*Client, error) } type Storage interface { fosite.Storage - CreateClient(c *fosite.DefaultClient) error + CreateClient(c *Client) error DeleteClient(id string) error - GetClients() (map[string]*fosite.DefaultClient, error) + GetClients() (map[string]*Client, error) } diff --git a/client/manager_http.go b/client/manager_http.go index 15094516085..87ac00bd29f 100644 --- a/client/manager_http.go +++ b/client/manager_http.go @@ -15,7 +15,7 @@ type HTTPManager struct { } func (m *HTTPManager) GetClient(id string) (fosite.Client, error) { - var c fosite.DefaultClient + var c Client var r = pkg.NewSuperAgent(pkg.JoinURL(m.Endpoint, id).String()) r.Client = m.Client r.Dry = m.Dry @@ -26,7 +26,7 @@ func (m *HTTPManager) GetClient(id string) (fosite.Client, error) { return &c, nil } -func (m *HTTPManager) CreateClient(c *fosite.DefaultClient) error { +func (m *HTTPManager) CreateClient(c *Client) error { var r = pkg.NewSuperAgent(m.Endpoint.String()) r.Client = m.Client r.Dry = m.Dry @@ -40,8 +40,8 @@ func (m *HTTPManager) DeleteClient(id string) error { return r.Delete() } -func (m *HTTPManager) GetClients() (map[string]*fosite.DefaultClient, error) { - cs := make(map[string]*fosite.DefaultClient) +func (m *HTTPManager) GetClients() (map[string]*Client, error) { + cs := make(map[string]*Client) var r = pkg.NewSuperAgent(m.Endpoint.String()) r.Client = m.Client r.Dry = m.Dry diff --git a/client/manager_memory.go b/client/manager_memory.go index 28dec670547..4bb2cd7dc62 100644 --- a/client/manager_memory.go +++ b/client/manager_memory.go @@ -11,7 +11,7 @@ import ( ) type MemoryManager struct { - Clients map[string]fosite.DefaultClient + Clients map[string]Client Hasher hash.Hasher sync.RWMutex } @@ -24,11 +24,10 @@ func (m *MemoryManager) GetClient(id string) (fosite.Client, error) { if !ok { return nil, errors.New(pkg.ErrNotFound) } - return &c, nil } -func (m *MemoryManager) Authenticate(id string, secret []byte) (*fosite.DefaultClient, error) { +func (m *MemoryManager) Authenticate(id string, secret []byte) (*Client, error) { m.Lock() defer m.Unlock() @@ -44,7 +43,7 @@ func (m *MemoryManager) Authenticate(id string, secret []byte) (*fosite.DefaultC return &c, nil } -func (m *MemoryManager) CreateClient(c *fosite.DefaultClient) error { +func (m *MemoryManager) CreateClient(c *Client) error { m.Lock() defer m.Unlock() @@ -52,11 +51,11 @@ func (m *MemoryManager) CreateClient(c *fosite.DefaultClient) error { c.ID = uuid.New() } - hash, err := m.Hasher.Hash(c.Secret) + hash, err := m.Hasher.Hash([]byte(c.Secret)) if err != nil { return errors.New(err) } - c.Secret = hash + c.Secret = string(hash) m.Clients[c.GetID()] = *c return nil @@ -70,10 +69,10 @@ func (m *MemoryManager) DeleteClient(id string) error { return nil } -func (m *MemoryManager) GetClients() (clients map[string]*fosite.DefaultClient, err error) { +func (m *MemoryManager) GetClients() (clients map[string]*Client, err error) { m.Lock() defer m.Unlock() - clients = make(map[string]*fosite.DefaultClient) + clients = make(map[string]*Client) for _, c := range m.Clients { clients[c.ID] = &c } diff --git a/client/manager_rethinkdb.go b/client/manager_rethinkdb.go index 628f115b105..d123c6e1c88 100644 --- a/client/manager_rethinkdb.go +++ b/client/manager_rethinkdb.go @@ -2,7 +2,6 @@ package client import ( "sync" - "time" "github.com/go-errors/errors" @@ -19,7 +18,7 @@ type RethinkManager struct { Table r.Term sync.RWMutex - Clients map[string]fosite.DefaultClient + Clients map[string]Client Hasher hash.Hasher } @@ -34,7 +33,7 @@ func (m *RethinkManager) GetClient(id string) (fosite.Client, error) { return &c, nil } -func (m *RethinkManager) Authenticate(id string, secret []byte) (*fosite.DefaultClient, error) { +func (m *RethinkManager) Authenticate(id string, secret []byte) (*Client, error) { m.Lock() defer m.Unlock() @@ -50,16 +49,16 @@ func (m *RethinkManager) Authenticate(id string, secret []byte) (*fosite.Default return &c, nil } -func (m *RethinkManager) CreateClient(c *fosite.DefaultClient) error { +func (m *RethinkManager) CreateClient(c *Client) error { if c.ID == "" { c.ID = uuid.New() } - hash, err := m.Hasher.Hash(c.Secret) + hash, err := m.Hasher.Hash([]byte(c.Secret)) if err != nil { return errors.New(err) } - c.Secret = hash + c.Secret = string(hash) if err := m.publishCreate(c); err != nil { return err @@ -76,10 +75,10 @@ func (m *RethinkManager) DeleteClient(id string) error { return nil } -func (m *RethinkManager) GetClients() (clients map[string]*fosite.DefaultClient, err error) { +func (m *RethinkManager) GetClients() (clients map[string]*Client, err error) { m.Lock() defer m.Unlock() - clients = make(map[string]*fosite.DefaultClient) + clients = make(map[string]*Client) for _, c := range m.Clients { clients[c.ID] = &c } @@ -88,13 +87,13 @@ func (m *RethinkManager) GetClients() (clients map[string]*fosite.DefaultClient, } func (m *RethinkManager) ColdStart() error { - m.Clients = map[string]fosite.DefaultClient{} + m.Clients = map[string]Client{} clients, err := m.Table.Run(m.Session) if err != nil { return errors.New(err) } - var client fosite.DefaultClient + var client Client m.Lock() defer m.Unlock() for clients.Next(&client) { @@ -104,7 +103,7 @@ func (m *RethinkManager) ColdStart() error { return nil } -func (m *RethinkManager) publishCreate(client *fosite.DefaultClient) error { +func (m *RethinkManager) publishCreate(client *Client) error { if _, err := m.Table.Insert(client).RunWrite(m.Session); err != nil { return errors.New(err) } @@ -126,7 +125,7 @@ func (m *RethinkManager) Watch(ctx context.Context) { } defer clients.Close() - var update map[string]*fosite.DefaultClient + var update map[string]*Client for clients.Next(&update) { newVal := update["new_val"] oldVal := update["old_val"] diff --git a/client/manager_test.go b/client/manager_test.go index 4975bd845b8..8e1b8672b1e 100644 --- a/client/manager_test.go +++ b/client/manager_test.go @@ -31,7 +31,7 @@ var ts *httptest.Server func init() { clientManagers["memory"] = &MemoryManager{ - Clients: map[string]fosite.DefaultClient{}, + Clients: map[string]Client{}, Hasher: &hash.BCrypt{}, } @@ -45,7 +45,7 @@ func init() { s := &Handler{ Manager: &MemoryManager{ - Clients: map[string]fosite.DefaultClient{}, + Clients: map[string]Client{}, Hasher: &hash.BCrypt{}, }, H: &herodot.JSON{}, @@ -83,7 +83,7 @@ func TestMain(m *testing.M) { rethinkManager = &RethinkManager{ Session: session, Table: r.Table("hydra_clients"), - Clients: make(map[string]fosite.DefaultClient), + Clients: make(map[string]Client), Hasher: &hash.BCrypt{ // Low workfactor reduces test time WorkFactor: 4, @@ -108,12 +108,12 @@ func TestMain(m *testing.M) { func TestAuthenticateClient(t *testing.T) { var mem = &MemoryManager{ - Clients: map[string]fosite.DefaultClient{}, + Clients: map[string]Client{}, Hasher: &hash.BCrypt{}, } - mem.CreateClient(&fosite.DefaultClient{ + mem.CreateClient(&Client{ ID: "1234", - Secret: []byte("secret"), + Secret: "secret", RedirectURIs: []string{"http://redirect"}, }) @@ -130,9 +130,9 @@ func BenchmarkRethinkGet(b *testing.B) { m := rethinkManager id := uuid.New() - c := &fosite.DefaultClient{ + c := &Client{ ID: id, - Secret: []byte("secret"), + Secret: "secret", RedirectURIs: []string{"http://redirect"}, TermsOfServiceURI: "foo", } @@ -155,9 +155,9 @@ func BenchmarkRethinkAuthenticate(b *testing.B) { m := rethinkManager id := uuid.New() - c := &fosite.DefaultClient{ + c := &Client{ ID: id, - Secret: []byte("secret"), + Secret: "secret", RedirectURIs: []string{"http://redirect"}, TermsOfServiceURI: "foo", } @@ -176,9 +176,9 @@ func BenchmarkRethinkAuthenticate(b *testing.B) { } func TestColdStartRethinkManager(t *testing.T) { - err := rethinkManager.CreateClient(&fosite.DefaultClient{ + err := rethinkManager.CreateClient(&Client{ ID: "2341234", - Secret: []byte("secret"), + Secret: "secret", RedirectURIs: []string{"http://redirect"}, TermsOfServiceURI: "foo", }) @@ -187,7 +187,7 @@ func TestColdStartRethinkManager(t *testing.T) { _, err = rethinkManager.GetClient("2341234") assert.Nil(t, err) - rethinkManager.Clients = make(map[string]fosite.DefaultClient) + rethinkManager.Clients = make(map[string]Client) _, err = rethinkManager.GetClient("2341234") assert.NotNil(t, err) @@ -195,7 +195,7 @@ func TestColdStartRethinkManager(t *testing.T) { _, err = rethinkManager.GetClient("2341234") assert.Nil(t, err) - rethinkManager.Clients = make(map[string]fosite.DefaultClient) + rethinkManager.Clients = make(map[string]Client) } func TestCreateGetDeleteClient(t *testing.T) { @@ -203,9 +203,9 @@ func TestCreateGetDeleteClient(t *testing.T) { _, err := m.GetClient("4321") pkg.AssertError(t, true, err, "%s", k) - c := &fosite.DefaultClient{ + c := &Client{ ID: "1234", - Secret: []byte("secret"), + Secret: "secret", RedirectURIs: []string{"http://redirect"}, TermsOfServiceURI: "foo", } diff --git a/cmd/cli/handler_client.go b/cmd/cli/handler_client.go index be71c06f323..96edc76c58b 100644 --- a/cmd/cli/handler_client.go +++ b/cmd/cli/handler_client.go @@ -1,12 +1,10 @@ package cli import ( - "fmt" - "encoding/json" + "fmt" "os" - "github.com/ory-am/fosite" "github.com/ory-am/hydra/client" "github.com/ory-am/hydra/config" "github.com/ory-am/hydra/pkg" @@ -35,7 +33,7 @@ func (h *ClientHandler) ImportClients(cmd *cobra.Command, args []string) { for _, path := range args { reader, err := os.Open(path) pkg.Must(err, "Could not open file %s: %s", path, err) - var client fosite.DefaultClient + var client client.Client err = json.NewDecoder(reader).Decode(&client) pkg.Must(err, "Could not parse JSON: %s", err) @@ -66,9 +64,9 @@ func (h *ClientHandler) CreateClient(cmd *cobra.Command, args []string) { secret, err := pkg.GenerateSecret(26) pkg.Must(err, "Could not generate secret: %s", err) - client := &fosite.DefaultClient{ + client := &client.Client{ ID: id, - Secret: secret, + Secret: string(secret), ResponseTypes: responseTypes, GrantedScopes: allowedScopes, GrantTypes: grantTypes, diff --git a/cmd/server/handler.go b/cmd/server/handler.go index e8ffdfbb14d..3578eba5457 100644 --- a/cmd/server/handler.go +++ b/cmd/server/handler.go @@ -4,7 +4,6 @@ import ( "github.com/Sirupsen/logrus" "github.com/go-errors/errors" "github.com/julienschmidt/httprouter" - "github.com/ory-am/fosite" "github.com/ory-am/fosite/handler/core" "github.com/ory-am/hydra/client" "github.com/ory-am/hydra/config" @@ -84,10 +83,10 @@ func (h *Handler) createRootIfNewInstall(c *config.Config) { rs, err := pkg.GenerateSecret(16) pkg.Must(err, "Could notgenerate secret because %s", err) - secret := []byte(string(rs)) + secret := string(rs) logrus.Warn("No clients were found. Creating a temporary root client...") - root := &fosite.DefaultClient{ + root := &client.Client{ Name: "This temporary client is generated by hydra and is granted all of hydra's administrative privileges. It must be removed when everything is set up.", GrantTypes: []string{"client_credentials", "authorization_code"}, ResponseTypes: []string{"token", "code"}, diff --git a/cmd/server/handler_client_factory.go b/cmd/server/handler_client_factory.go index 68b73f34e6a..49c95d4978c 100644 --- a/cmd/server/handler_client_factory.go +++ b/cmd/server/handler_client_factory.go @@ -3,7 +3,6 @@ package server import ( "github.com/Sirupsen/logrus" "github.com/julienschmidt/httprouter" - "github.com/ory-am/fosite" "github.com/ory-am/hydra/client" "github.com/ory-am/hydra/config" "github.com/ory-am/hydra/herodot" @@ -17,7 +16,7 @@ func newClientManager(c *config.Config) client.Manager { switch con := ctx.Connection.(type) { case *config.MemoryConnection: return &client.MemoryManager{ - Clients: map[string]fosite.DefaultClient{}, + Clients: map[string]client.Client{}, Hasher: ctx.Hasher, } case *config.RethinkDBConnection: diff --git a/glide.lock b/glide.lock index 92e5210789b..b5c8a6f1075 100644 --- a/glide.lock +++ b/glide.lock @@ -1,5 +1,5 @@ hash: 175acff756341dd7fa75a3e1e2e1a042a957a1b2482f017ae0bb38a2e8b9c625 -updated: 2016-06-23T14:29:39.727085824+02:00 +updated: 2016-06-26T13:19:40.0602745+02:00 imports: - name: github.com/asaskevich/govalidator version: df81827fdd59d8b4fb93d8910b286ab7a3919520 @@ -24,7 +24,7 @@ imports: - name: github.com/hailocab/go-hostpool version: e80d13ce29ede4452c43dea11e79b9bc8a15b478 - name: github.com/hashicorp/hcl - version: 5b7dbf7eefffea49afb3c9655d6582c72fae5fd1 + version: 61f5143284c041681f76a5b63efcb232aaa94737 subpackages: - hcl/ast - hcl/parser @@ -106,7 +106,7 @@ imports: - name: github.com/toqueteos/webbrowser version: 21fc9f95c83442fd164094666f7cb4f9fdd56cd6 - name: golang.org/x/crypto - version: f3241ce8505855877cc8a9717bd61a0f7c4ea83c + version: 811831de4c4dd03a0b8737233af3b36852386373 subpackages: - bcrypt - pbkdf2 diff --git a/internal/fosite_store_rethinkdb.go b/internal/fosite_store_rethinkdb.go index 7fb852c9edb..e9429282a65 100644 --- a/internal/fosite_store_rethinkdb.go +++ b/internal/fosite_store_rethinkdb.go @@ -37,13 +37,13 @@ type FositeRehinkDBStore struct { } type RdbSchema struct { - ID string `json:"id" gorethink:"id"` - RequestedAt time.Time `json:"requestedAt" gorethink:"requestedAt"` - Client *fosite.DefaultClient `json:"client" gorethink:"client"` - Scopes fosite.Arguments `json:"scopes" gorethink:"scopes"` - GrantedScopes fosite.Arguments `json:"grantedScopes" gorethink:"grantedScopes"` - Form url.Values `json:"form" gorethink:"form"` - Session json.RawMessage `json:"session" gorethink:"session"` + ID string `json:"id" gorethink:"id"` + RequestedAt time.Time `json:"requestedAt" gorethink:"requestedAt"` + Client *client.Client `json:"client" gorethink:"client"` + Scopes fosite.Arguments `json:"scopes" gorethink:"scopes"` + GrantedScopes fosite.Arguments `json:"grantedScopes" gorethink:"grantedScopes"` + Form url.Values `json:"form" gorethink:"form"` + Session json.RawMessage `json:"session" gorethink:"session"` } func requestFromRDB(s *RdbSchema, proto interface{}) (*fosite.Request, error) { @@ -89,7 +89,7 @@ func (s *FositeRehinkDBStore) publishInsert(table r.Term, id string, requester f if _, err := table.Insert(&RdbSchema{ ID: id, RequestedAt: requester.GetRequestedAt(), - Client: requester.GetClient().(*fosite.DefaultClient), + Client: requester.GetClient().(*client.Client), Scopes: requester.GetScopes(), GrantedScopes: requester.GetGrantedScopes(), Form: requester.GetRequestForm(), diff --git a/internal/fosite_store_test.go b/internal/fosite_store_test.go index 273efd998ed..4666a7b0e52 100644 --- a/internal/fosite_store_test.go +++ b/internal/fosite_store_test.go @@ -9,6 +9,7 @@ import ( "github.com/Sirupsen/logrus" c "github.com/ory-am/common/pkg" "github.com/ory-am/fosite" + "github.com/ory-am/hydra/client" "github.com/ory-am/hydra/pkg" "github.com/pborman/uuid" "golang.org/x/net/context" @@ -94,7 +95,7 @@ type testSession struct { var defaultRequest = fosite.Request{ RequestedAt: time.Now().Round(time.Second), - Client: &fosite.DefaultClient{ID: "foobar"}, + Client: &client.Client{ID: "foobar"}, Scopes: fosite.Arguments{"fa", "ba"}, GrantedScopes: fosite.Arguments{"fa", "ba"}, Form: url.Values{"foo": []string{"bar", "baz"}}, diff --git a/oauth2/oauth2_test.go b/oauth2/oauth2_test.go index 89fe637b695..3a01ef7da00 100644 --- a/oauth2/oauth2_test.go +++ b/oauth2/oauth2_test.go @@ -16,6 +16,8 @@ import ( "github.com/ory-am/fosite/handler/core/strategy" "github.com/ory-am/fosite/hash" "github.com/ory-am/fosite/token/hmac" + hc "github.com/ory-am/hydra/client" + "github.com/ory-am/hydra/internal" "github.com/ory-am/hydra/jwk" . "github.com/ory-am/hydra/oauth2" "github.com/ory-am/hydra/pkg" @@ -24,7 +26,19 @@ import ( "gopkg.in/dgrijalva/jwt-go.v2" ) -var store = pkg.FositeStore() +var hasher = &hash.BCrypt{} + +var store = &internal.FositeMemoryStore{ + Manager: &hc.MemoryManager{ + Clients: map[string]hc.Client{}, + Hasher: hasher, + }, + AuthorizeCodes: make(map[string]fosite.Requester), + IDSessions: make(map[string]fosite.Requester), + AccessTokens: make(map[string]fosite.Requester), + Implicit: make(map[string]fosite.Requester), + RefreshTokens: make(map[string]fosite.Requester), +} var keyManager = &jwk.MemoryManager{} @@ -45,8 +59,6 @@ var authCodeHandler = &explicit.AuthorizeExplicitGrantTypeHandler{ AccessTokenLifespan: time.Hour, } -var hasher = &hash.BCrypt{} - var handler = &Handler{ OAuth2: &fosite.Fosite{ Store: store, @@ -92,9 +104,9 @@ func init() { ts = httptest.NewServer(router) handler.SetRoutes(router) - store.Clients["app"] = &fosite.DefaultClient{ + store.Manager.(*hc.MemoryManager).Clients["app"] = hc.Client{ ID: "app", - Secret: []byte("secret"), + Secret: "secret", RedirectURIs: []string{ts.URL + "/callback"}, ResponseTypes: []string{"id_token", "code", "token"}, GrantTypes: []string{"implicit", "refresh_token", "authorization_code", "password", "client_credentials"}, @@ -104,9 +116,9 @@ func init() { handler.ConsentURL = *c h, _ := hasher.Hash([]byte("secret")) - store.Clients["app-client"] = &fosite.DefaultClient{ + store.Manager.(*hc.MemoryManager).Clients["app-client"] = hc.Client{ ID: "app-client", - Secret: h, + Secret: string(h), RedirectURIs: []string{ts.URL + "/callback"}, ResponseTypes: []string{"id_token", "code", "token"}, GrantTypes: []string{"implicit", "refresh_token", "authorization_code", "password", "client_credentials"}, diff --git a/warden/handler.go b/warden/handler.go index b16af37c854..ca8cd709955 100644 --- a/warden/handler.go +++ b/warden/handler.go @@ -111,7 +111,8 @@ func (h *WardenHandler) Allowed(w http.ResponseWriter, r *http.Request, _ httpro func (h *WardenHandler) authorizeClient(ctx context.Context, w http.ResponseWriter, r *http.Request, action string) (*firewall.Context, error) { authctx, err := h.Warden.ActionAllowed(ctx, TokenFromRequest(r), &ladon.Request{ - Action: action, + Action: action, + Resource: "rn:hydra:warden", }, "hydra.warden") if err != nil { return nil, err diff --git a/warden/warden_local.go b/warden/warden_local.go index eb1cbff4d96..aa5a605b4c3 100644 --- a/warden/warden_local.go +++ b/warden/warden_local.go @@ -25,15 +25,36 @@ type LocalWarden struct { func (w *LocalWarden) actionAllowed(ctx context.Context, a *ladon.Request, scopes []string, oauthRequest fosite.AccessRequester, session *oauth2.Session) (*Context, error) { session = oauthRequest.GetSession().(*oauth2.Session) if a.Subject != "" && a.Subject != session.Subject { + logrus.WithFields(logrus.Fields{ + "scopes": scopes, + "subject": a.Subject, + "audience": oauthRequest.GetClient().GetID(), + "request": a, + "reason": "subject mismatch", + }).Infof("Access denied") return nil, errors.New("Subject mismatch " + a.Subject + " - " + session.Subject) } if !matchScopes(oauthRequest.GetGrantedScopes(), scopes, session, oauthRequest.GetClient()) { + logrus.WithFields(logrus.Fields{ + "scopes": scopes, + "subject": a.Subject, + "audience": oauthRequest.GetClient().GetID(), + "request": a, + "reason": "scope mismatch", + }).Infof("Access denied") return nil, errors.New(herodot.ErrForbidden) } a.Subject = session.Subject if err := w.Warden.IsAllowed(a); err != nil { + logrus.WithFields(logrus.Fields{ + "scopes": scopes, + "subject": a.Subject, + "audience": oauthRequest.GetClient().GetID(), + "request": a, + "reason": "policy effect is deny", + }).Infof("Access denied") return nil, err } @@ -68,8 +89,22 @@ func (w *LocalWarden) HTTPActionAllowed(ctx context.Context, r *http.Request, a var oauthRequest = fosite.NewAccessRequest(session) if err := w.TokenValidator.ValidateRequest(ctx, r, oauthRequest); errors.Is(err, fosite.ErrUnknownRequest) { - return nil, pkg.ErrUnauthorized + logrus.WithFields(logrus.Fields{ + "scopes": scopes, + "subject": a.Subject, + "audience": oauthRequest.GetClient().GetID(), + "request": a, + "reason": "unknown request", + }).Infof("Access denied") + return nil, errors.New(pkg.ErrUnauthorized) } else if err != nil { + logrus.WithFields(logrus.Fields{ + "scopes": scopes, + "subject": a.Subject, + "audience": oauthRequest.GetClient().GetID(), + "request": a, + "reason": "token validation failed", + }).Infof("Access denied") return nil, err } @@ -81,11 +116,23 @@ func (w *LocalWarden) Authorized(ctx context.Context, token string, scopes ...st var oauthRequest = fosite.NewAccessRequest(session) if err := w.TokenValidator.ValidateToken(ctx, oauthRequest, token); err != nil { + logrus.WithFields(logrus.Fields{ + "scopes": scopes, + "subject": session.Subject, + "audience": oauthRequest.GetClient().GetID(), + "reason": "token validation failed", + }).Infof("Access denied") return nil, err } session = oauthRequest.GetSession().(*oauth2.Session) if !matchScopes(oauthRequest.GetGrantedScopes(), scopes, session, oauthRequest.Client) { + logrus.WithFields(logrus.Fields{ + "scopes": scopes, + "subject": session, + "audience": oauthRequest.GetClient().GetID(), + "reason": "scope mismatch", + }).Infof("Access denied") return nil, errors.New(herodot.ErrForbidden) } @@ -103,13 +150,31 @@ func (w *LocalWarden) HTTPAuthorized(ctx context.Context, r *http.Request, scope var oauthRequest = fosite.NewAccessRequest(session) if err := w.TokenValidator.ValidateRequest(ctx, r, oauthRequest); errors.Is(err, fosite.ErrUnknownRequest) { - return nil, fosite.ErrRequestUnauthorized + logrus.WithFields(logrus.Fields{ + "scopes": scopes, + "subject": session.Subject, + "audience": oauthRequest.GetClient().GetID(), + "reason": "unknown request", + }).Infof("Access denied") + return nil, errors.New(pkg.ErrUnauthorized) } else if err != nil { + logrus.WithFields(logrus.Fields{ + "scopes": scopes, + "subject": session.Subject, + "audience": oauthRequest.GetClient().GetID(), + "reason": "token validation failed", + }).Infof("Access denied") return nil, err } session = oauthRequest.GetSession().(*oauth2.Session) if !matchScopes(oauthRequest.GetGrantedScopes(), scopes, session, oauthRequest.Client) { + logrus.WithFields(logrus.Fields{ + "scopes": scopes, + "subject": session.Subject, + "audience": oauthRequest.GetClient().GetID(), + "reason": "scope mismatch", + }).Infof("Access denied") return nil, errors.New(herodot.ErrForbidden) }