Skip to content

Commit

Permalink
all: access request api draft
Browse files Browse the repository at this point in the history
  • Loading branch information
Aeneas Rekkas committed Jan 10, 2016
1 parent 5da857b commit 9f482ef
Show file tree
Hide file tree
Showing 16 changed files with 500 additions and 96 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ mockgen -destination internal/token_handler.go github.com/ory-am/fosite TokenEnd
**Create stateful "context" mocks**
```
mockgen -destination internal/access_request.go github.com/ory-am/fosite AccessRequester
mockgen -destination internal/access__response.go github.com/ory-am/fosite AccessResponder
mockgen -destination internal/access_response.go github.com/ory-am/fosite AccessResponder
mockgen -destination internal/authorize_request.go github.com/ory-am/fosite AuthorizeRequester
mockgen -destination internal/authorize_response.go github.com/ory-am/fosite AuthorizeResponder
```
Expand Down
25 changes: 25 additions & 0 deletions access_error.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package fosite

import (
"encoding/json"
"fmt"
"net/http"
)

func (c *Fosite) WriteAccessError(rw http.ResponseWriter, requester AccessRequester, err error) {
rw.Header().Set("Content-Type", "application/json;charset=UTF-8")

rfcerr := ErrorToRFC6749Error(err)
js, err := json.Marshal(rfcerr)
if err != nil {
http.Error(rw, fmt.Sprintf(`{"error": "%s"}`, err.Error()), http.StatusInternalServerError)
return
}

rw.WriteHeader(http.StatusBadRequest)
if rfcerr.Name == errServerErrorName {
rw.WriteHeader(http.StatusInternalServerError)
}

rw.Write(js)
}
115 changes: 30 additions & 85 deletions access_request.go
Original file line number Diff line number Diff line change
@@ -1,112 +1,57 @@
package fosite

import (
"github.com/go-errors/errors"
"github.com/ory-am/fosite/client"
"golang.org/x/net/context"
"net/http"
"time"
)

type AccessRequester interface {
// GetGrantType returns the requests grant type.
GetGrantType() string

// GetClient returns the requests client.
GetClient() client.Client

// GetRequestedAt returns the time the request was created.
GetRequestedAt() time.Time
}

type AccessRequest struct {
GrantType string
RequestedAt time.Time
Client client.Client
}
// SetGrantTypeHandled marks a grant type as handled indicating that the response type is supported.
SetGrantTypeHandled(string)

func (a *AccessRequest) GetGrantType() string {
return a.GrantType
// DidHandleGrantType returns if the requested grant type has been handled correctly.
DidHandleGrantType() bool
}

func (a *AccessRequest) GetRequestedAt() time.Time {
return a.RequestedAt
}

func (a *AccessRequest) GetClient() client.Client {
return a.Client
type AccessRequest struct {
GrantType string
HandledGrantType []string
RequestedAt time.Time
Client client.Client
}

func NewAccessRequest() *AccessRequest {
return &AccessRequest{
RequestedAt: time.Now(),
RequestedAt: time.Now(),
HandledGrantType: []string{},
}
}

//
// Implements
// * https://tools.ietf.org/html/rfc6749#section-2.3.1
// Clients in possession of a client password MAY use the HTTP Basic
// authentication scheme as defined in [RFC2617] to authenticate with
// the authorization server. The client identifier is encoded using the
// "application/x-www-form-urlencoded" encoding algorithm per
// Appendix B, and the encoded value is used as the username; the client
// password is encoded using the same algorithm and used as the
// password. The authorization server MUST support the HTTP Basic
// authentication scheme for authenticating clients that were issued a
// client password.
// Including the client credentials in the request-body using the two
// parameters is NOT RECOMMENDED and SHOULD be limited to clients unable
// to directly utilize the HTTP Basic authentication scheme (or other
// password-based HTTP authentication schemes). The parameters can only
// be transmitted in the request-body and MUST NOT be included in the
// request URI.
// * https://tools.ietf.org/html/rfc6749#section-3.2.1
// - Confidential clients or other clients issued client credentials MUST
// authenticate with the authorization server as described in
// Section 2.3 when making requests to the token endpoint.
// - If the client type is confidential or the client was issued client
// credentials (or assigned other authentication requirements), the
// client MUST authenticate with the authorization server as described
// in Section 3.2.1.
func (c *Fosite) NewAccessRequest(ctx context.Context, r *http.Request, session interface{}) (AccessRequester, error) {
ar := NewAccessRequest()
if c.RequiredScope == "" {
c.RequiredScope = DefaultRequiredScopeName
}

if err := r.ParseForm(); err != nil {
return ar, errors.New(ErrInvalidRequest)
}

if session == nil {
return ar, errors.New("Session must not be nil")
}

ar.GrantType = r.Form.Get("grant_type")
if ar.GrantType == "" {
return ar, errors.New(ErrInvalidRequest)
}

clientID, clientSecret, ok := r.BasicAuth()
if !ok {
clientID = r.Form.Get("client_id")
}
if clientID == "" {
return ar, errors.New(ErrInvalidRequest)
}
func (a *AccessRequest) DidHandleGrantType() bool {
return StringInSlice(a.GrantType, a.HandledGrantType)
}

client, err := c.Store.GetClient(clientID)
if err != nil {
return ar, errors.New(ErrInvalidClient)
}
func (a *AccessRequest) SetGrantTypeHandled(name string) {
a.HandledGrantType = append(a.HandledGrantType, name)
}

// Enforce client authentication
if !client.CompareSecretWith([]byte(clientSecret)) {
return ar, errors.New(ErrInvalidClient)
}
ar.Client = client
func (a *AccessRequest) GetGrantType() string {
return a.GrantType
}

for _, loader := range c.TokenEndpointHandlers {
if err := loader.HandleTokenEndpointRequest(ctx, ar, r, session); err != nil {
return ar, err
}
}
func (a *AccessRequest) GetRequestedAt() time.Time {
return a.RequestedAt
}

return ar, nil
func (a *AccessRequest) GetClient() client.Client {
return a.Client
}
84 changes: 84 additions & 0 deletions access_request_handler.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
package fosite

import (
"github.com/go-errors/errors"
"golang.org/x/net/context"
"net/http"
)

// Implements
// * https://tools.ietf.org/html/rfc6749#section-2.3.1
// Clients in possession of a client password MAY use the HTTP Basic
// authentication scheme as defined in [RFC2617] to authenticate with
// the authorization server. The client identifier is encoded using the
// "application/x-www-form-urlencoded" encoding algorithm per
// Appendix B, and the encoded value is used as the username; the client
// password is encoded using the same algorithm and used as the
// password. The authorization server MUST support the HTTP Basic
// authentication scheme for authenticating clients that were issued a
// client password.
// Including the client credentials in the request-body using the two
// parameters is NOT RECOMMENDED and SHOULD be limited to clients unable
// to directly utilize the HTTP Basic authentication scheme (or other
// password-based HTTP authentication schemes). The parameters can only
// be transmitted in the request-body and MUST NOT be included in the
// request URI.
// * https://tools.ietf.org/html/rfc6749#section-3.2.1
// - Confidential clients or other clients issued client credentials MUST
// authenticate with the authorization server as described in
// Section 2.3 when making requests to the token endpoint.
// - If the client type is confidential or the client was issued client
// credentials (or assigned other authentication requirements), the
// client MUST authenticate with the authorization server as described
// in Section 3.2.1.
func (c *Fosite) NewAccessRequest(ctx context.Context, r *http.Request, session interface{}) (AccessRequester, error) {
ar := NewAccessRequest()
if r.Method != "POST" {
return ar, errors.New(ErrInvalidRequest)
}

if c.RequiredScope == "" {
c.RequiredScope = DefaultRequiredScopeName
}

if err := r.ParseForm(); err != nil {
return ar, errors.New(ErrInvalidRequest)
}

if session == nil {
return ar, errors.New("Session must not be nil")
}

ar.GrantType = r.Form.Get("grant_type")
if ar.GrantType == "" {
return ar, errors.New(ErrInvalidRequest)
}

clientID, clientSecret, ok := r.BasicAuth()
if !ok {
return ar, errors.New(ErrInvalidRequest)
}

client, err := c.Store.GetClient(clientID)
if err != nil {
return ar, errors.New(ErrInvalidClient)
}

// Enforce client authentication
if !client.CompareSecretWith([]byte(clientSecret)) {
return ar, errors.New(ErrInvalidClient)
}
ar.Client = client

for _, loader := range c.TokenEndpointHandlers {
if err := loader.HandleTokenEndpointRequest(ctx, ar, r, session); err != nil {
return ar, err
}
}

if !ar.DidHandleGrantType() {
return ar, errors.New(ErrUnsupportedGrantType)
}

return ar, nil
}
Loading

0 comments on commit 9f482ef

Please sign in to comment.