Skip to content

Commit

Permalink
all: improve handling of expiry and include a protected api example
Browse files Browse the repository at this point in the history
  • Loading branch information
Aeneas Rekkas (arekkas) committed Jun 29, 2016
1 parent 5876017 commit dfb047d
Show file tree
Hide file tree
Showing 71 changed files with 862 additions and 544 deletions.
10 changes: 7 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -177,24 +177,28 @@ Let's take the explicit authorize handler. He is responsible for handling the
If you want to enable the handler able to handle this workflow, you can do this:

```go
var accessTokenLifespan = time.Hour
var authorizeCodeLifespan = time.Minute * 10

var hmacStrategy = &strategy.HMACSHAStrategy{
Enigma: &enigma.Enigma{
GlobalSecret: []byte("some-super-cool-secret-that-nobody-knows"),
},
AccessTokenLifespan: accessTokenLifespan,
AuthorizeCodeLifespan: authorizeCodeLifespan,
}

// var store = ...

f := NewFosite(store)
accessTokenLifespan := time.Hour
var f = NewFosite(store)

// Let's enable the explicit authorize code grant!
explicitHandler := &explicit.AuthorizeExplicitGrantTypeHandler{
AccessTokenStrategy: hmacStrategy,
RefreshTokenStrategy: hmacStrategy,
AuthorizeCodeStrategy: hmacStrategy,
Store: store,
AuthCodeLifespan: time.Minute * 10,
AuthCodeLifespan: authorizeCodeLifespan,
AccessTokenLifespan: accessTokenLifespan,
}

Expand Down
25 changes: 11 additions & 14 deletions access_request_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"net/http"
"strings"

"github.com/go-errors/errors"
"github.com/pkg/errors"
"golang.org/x/net/context"
)

Expand Down Expand Up @@ -37,58 +37,55 @@ func (f *Fosite) NewAccessRequest(ctx context.Context, r *http.Request, session
accessRequest := NewAccessRequest(session)

if r.Method != "POST" {
return accessRequest, errors.New(ErrInvalidRequest)
}

if err := r.ParseForm(); err != nil {
return accessRequest, errors.New(ErrInvalidRequest)
return accessRequest, errors.Wrap(ErrInvalidRequest, "HTTP method is not POST")
} else if err := r.ParseForm(); err != nil {
return accessRequest, errors.Wrap(ErrInvalidRequest, err.Error())
}

accessRequest.Form = r.PostForm

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

accessRequest.Scopes = removeEmpty(strings.Split(r.Form.Get("scope"), " "))
accessRequest.GrantTypes = removeEmpty(strings.Split(r.Form.Get("grant_type"), " "))
if len(accessRequest.GrantTypes) < 1 {
return accessRequest, errors.New(ErrInvalidRequest)
return accessRequest, errors.Wrap(ErrInvalidRequest, "No grant type given")
}

clientID, clientSecret, ok := r.BasicAuth()
if !ok {
return accessRequest, errors.New(ErrInvalidRequest)
return accessRequest, errors.Wrap(ErrInvalidRequest, "HTTP Authorization header missing or invalid")
}

client, err := f.Store.GetClient(clientID)
if err != nil {
return accessRequest, errors.New(ErrInvalidClient)
return accessRequest, errors.Wrap(ErrInvalidClient, err.Error())
}

// Enforce client authentication
if err := f.Hasher.Compare(client.GetHashedSecret(), []byte(clientSecret)); err != nil {
return accessRequest, errors.New(ErrInvalidClient)
return accessRequest, errors.Wrap(ErrInvalidClient, err.Error())
}
accessRequest.Client = client

var found bool = false
for _, loader := range f.TokenEndpointHandlers {
if err := loader.HandleTokenEndpointRequest(ctx, r, accessRequest); err == nil {
found = true
} else if errors.Is(err, ErrUnknownRequest) {
} else if errors.Cause(err) == ErrUnknownRequest {
// do nothing
} else if err != nil {
return accessRequest, err
}
}

if !found {
return nil, ErrUnsupportedGrantType
return nil, errors.Wrap(ErrInvalidRequest, "")
}

if !accessRequest.GetScopes().Has(f.GetMandatoryScope()) {
return accessRequest, errors.New(ErrInvalidScope)
return accessRequest, errors.Wrap(ErrInvalidScope, "")
}

accessRequest.GrantScope(f.GetMandatoryScope())
Expand Down
12 changes: 5 additions & 7 deletions access_request_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ import (
"net/url"
"testing"

"github.com/go-errors/errors"
"github.com/golang/mock/gomock"
"github.com/ory-am/common/pkg"
. "github.com/ory-am/fosite"
"github.com/ory-am/fosite/internal"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"golang.org/x/net/context"
)
Expand Down Expand Up @@ -182,12 +182,10 @@ func TestNewAccessRequest(t *testing.T) {
ctx := NewContext()
fosite.TokenEndpointHandlers = c.handlers
ar, err := fosite.NewAccessRequest(ctx, r, &struct{}{})
is := errors.Is(c.expectErr, err)
assert.True(t, is, "%d\nwant: %s \ngot: %s", k, c.expectErr, err)
if !is {
t.Logf("Error occured: %s", err.(*errors.Error).ErrorStack())
}
if err == nil {
assert.True(t, errors.Cause(err) == c.expectErr, "%d\nwant: %s \ngot: %s", k, c.expectErr, err)
if err != nil {
t.Logf("Error occured: %v", err)
} else {
pkg.AssertObjectKeysEqual(t, c.expect, ar, "GrantTypes", "Client")
assert.NotNil(t, ar.GetRequestedAt())
}
Expand Down
8 changes: 4 additions & 4 deletions access_response_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ package fosite
import (
"net/http"

"github.com/go-errors/errors"
"github.com/pkg/errors"
"golang.org/x/net/context"
)

Expand All @@ -13,14 +13,14 @@ func (f *Fosite) NewAccessResponse(ctx context.Context, req *http.Request, reque

response := NewAccessResponse()
for _, tk = range f.TokenEndpointHandlers {
if err = tk.PopulateTokenEndpointResponse(ctx, req, requester, response); errors.Is(err, ErrUnknownRequest) {
if err = tk.PopulateTokenEndpointResponse(ctx, req, requester, response); errors.Cause(err) == ErrUnknownRequest {
} else if err != nil {
return nil, errors.Wrap(err, 1)
return nil, err
}
}

if response.GetAccessToken() == "" || response.GetTokenType() == "" {
return nil, ErrServerError
return nil, errors.Wrap(ErrServerError, "Access token or token type not set")
}

return response, nil
Expand Down
4 changes: 2 additions & 2 deletions access_response_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import (
"net/http"
"testing"

"github.com/go-errors/errors"
"github.com/golang/mock/gomock"
. "github.com/ory-am/fosite"
"github.com/ory-am/fosite/internal"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"golang.org/x/net/context"
)
Expand Down Expand Up @@ -70,7 +70,7 @@ func TestNewAccessResponse(t *testing.T) {
f.TokenEndpointHandlers = c.handlers
c.mock()
ar, err := f.NewAccessResponse(nil, nil, nil)
assert.True(t, errors.Is(c.expectErr, err), "%d", k)
assert.True(t, errors.Cause(err) == c.expectErr, "%d", k)
assert.Equal(t, ar, c.expect)
t.Logf("Passed test case %d", k)
}
Expand Down
6 changes: 3 additions & 3 deletions authorize_helper.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import (
"strings"

"github.com/asaskevich/govalidator"
"github.com/go-errors/errors"
"github.com/pkg/errors"
)

// GetRedirectURIFromRequestValues extracts the redirect_uri from values but does not do any sort of validation.
Expand All @@ -21,7 +21,7 @@ func GetRedirectURIFromRequestValues(values url.Values) (string, error) {
// The endpoint URI MAY include an "application/x-www-form-urlencoded" formatted (per Appendix B) query component
redirectURI, err := url.QueryUnescape(values.Get("redirect_uri"))
if err != nil {
return "", errors.Wrap(ErrInvalidRequest, 0)
return "", errors.Wrap(ErrInvalidRequest, "redirect_uri parameter malformed or missing")
}
return redirectURI, nil
}
Expand Down Expand Up @@ -71,7 +71,7 @@ func MatchRedirectURIWithClientRedirectURIs(rawurl string, client Client) (*url.
}
}

return nil, errors.New(ErrInvalidRequest)
return nil, errors.Wrap(ErrInvalidRequest, "redirect_uri parameter does not match with registered client redirect urls")
}

// IsValidRedirectURI validates a redirect_uri as specified in:
Expand Down
22 changes: 9 additions & 13 deletions authorize_request_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,45 +3,41 @@ package fosite
import (
"net/http"
"strings"
"time"

"github.com/go-errors/errors"
"github.com/pkg/errors"
"golang.org/x/net/context"
)

func (c *Fosite) NewAuthorizeRequest(ctx context.Context, r *http.Request) (AuthorizeRequester, error) {
request := &AuthorizeRequest{
ResponseTypes: Arguments{},
HandledResponseTypes: Arguments{},
Request: Request{
Scopes: Arguments{},
RequestedAt: time.Now(),
},
Request: *NewRequest(),
}

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

request.Form = r.Form
client, err := c.Store.GetClient(request.GetRequestForm().Get("client_id"))
if err != nil {
return request, errors.New(ErrInvalidClient)
return request, errors.Wrap(ErrInvalidClient, "")
}
request.Client = client

// Fetch redirect URI from request
rawRedirURI, err := GetRedirectURIFromRequestValues(r.Form)
if err != nil {
return request, errors.New(ErrInvalidRequest)
return request, errors.Wrap(ErrInvalidRequest, err.Error())
}

// Validate redirect uri
redirectURI, err := MatchRedirectURIWithClientRedirectURIs(rawRedirURI, client)
if err != nil {
return request, errors.New(ErrInvalidRequest)
return request, errors.Wrap(ErrInvalidRequest, err.Error())
} else if !IsValidRedirectURI(redirectURI) {
return request, errors.New(ErrInvalidRequest)
return request, errors.Wrap(ErrInvalidRequest, "not a valid redirect uri")
}
request.RedirectURI = redirectURI

Expand All @@ -61,15 +57,15 @@ func (c *Fosite) NewAuthorizeRequest(ctx context.Context, r *http.Request) (Auth
state := r.Form.Get("state")
if len(state) < MinParameterEntropy {
// We're assuming that using less then 8 characters for the state can not be considered "unguessable"
return request, errors.New(ErrInvalidState)
return request, errors.Wrapf(ErrInvalidState, "state length must at least be %d characters long", MinParameterEntropy)
}
request.State = state

// Remove empty items from arrays
request.Scopes = removeEmpty(strings.Split(r.Form.Get("scope"), " "))

if !request.Scopes.Has(c.GetMandatoryScope()) {
return request, errors.New(ErrInvalidScope)
return request, errors.Wrap(ErrInvalidScope, "mandatory scope is missing")
}
request.GrantScope(c.GetMandatoryScope())

Expand Down
4 changes: 2 additions & 2 deletions authorize_request_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,11 +5,11 @@ import (
"net/url"
"testing"

"github.com/go-errors/errors"
"github.com/golang/mock/gomock"
"github.com/ory-am/common/pkg"
. "github.com/ory-am/fosite"
. "github.com/ory-am/fosite/internal"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"golang.org/x/net/context"
)
Expand Down Expand Up @@ -184,7 +184,7 @@ func TestNewAuthorizeRequest(t *testing.T) {
ar, err := c.conf.NewAuthorizeRequest(context.Background(), c.r)
assert.Equal(t, c.expectedError == nil, err == nil, "%d: %s\n%s", k, c.desc, err)
if c.expectedError != nil {
assert.Equal(t, err.Error(), c.expectedError.Error(), "%d: %s\n%s", k, c.desc, err)
assert.Equal(t, errors.Cause(err), c.expectedError, "%d: %s\n%s", k, c.desc, err)
} else {
pkg.AssertObjectKeysEqual(t, c.expect, ar, "ResponseTypes", "Scopes", "Client", "RedirectURI", "State")
assert.NotNil(t, ar.GetRequestedAt())
Expand Down
4 changes: 2 additions & 2 deletions authorize_response_handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ import (
"net/http"
"net/url"

"github.com/go-errors/errors"
"github.com/pkg/errors"
"golang.org/x/net/context"
)

Expand All @@ -23,7 +23,7 @@ func (o *Fosite) NewAuthorizeResponse(ctx context.Context, r *http.Request, ar A
}

if !ar.DidHandleAllResponseTypes() {
return nil, errors.New(ErrUnsupportedResponseType)
return nil, errors.Wrap(ErrUnsupportedResponseType, "")
}

return resp, nil
Expand Down
2 changes: 1 addition & 1 deletion authorize_response_handler_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,10 @@ import (
"net/http"
"testing"

"github.com/go-errors/errors"
"github.com/golang/mock/gomock"
. "github.com/ory-am/fosite"
. "github.com/ory-am/fosite/internal"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"golang.org/x/net/context"
)
Expand Down
Loading

0 comments on commit dfb047d

Please sign in to comment.