Skip to content

Commit

Permalink
docs: document reasoning for interface{} in compose package - closes #94
Browse files Browse the repository at this point in the history
  • Loading branch information
Aeneas Rekkas (arekkas) authored and arekkas committed Oct 16, 2016
1 parent 5ec5cff commit f193012
Show file tree
Hide file tree
Showing 31 changed files with 534 additions and 188 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ language: go
go:
- 1.5
- 1.6
- 1.7

env:
- GO15VENDOREXPERIMENT=1
Expand Down
2 changes: 1 addition & 1 deletion access_error.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,4 +22,4 @@ func writeJsonError(rw http.ResponseWriter, err error) {

rw.WriteHeader(rfcerr.StatusCode)
rw.Write(js)
}
}
2 changes: 1 addition & 1 deletion client.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ type DefaultClient struct {
GrantTypes []string `json:"grant_types"`
ResponseTypes []string `json:"response_types"`
Scopes []string `json:"scopes"`
Public bool `json:"public"`
Public bool `json:"public"`
}

func (c *DefaultClient) GetID() string {
Expand Down
14 changes: 8 additions & 6 deletions compose/compose.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,17 @@ type handler func(config *Config, storage interface{}, strategy interface{}) int
// OAuth2ClientCredentialsGrantFactory,
// // for a complete list refer to the docs of this package
// )
//
// Compose makes use of interface{} types in order to be able to handle a all types of stores, strategies and handlers.
func Compose(config *Config, storage interface{}, strategy interface{}, handlers ...handler) fosite.OAuth2Provider {
f := &fosite.Fosite{
Store: storage.(fosite.Storage),
AuthorizeEndpointHandlers: fosite.AuthorizeEndpointHandlers{},
TokenEndpointHandlers: fosite.TokenEndpointHandlers{},
TokenIntrospectionHandlers: fosite.TokenIntrospectionHandlers{},
RevocationHandlers: fosite.RevocationHandlers{},
Hasher: &fosite.BCrypt{WorkFactor: config.GetHashCost()},
ScopeStrategy: fosite.HierarchicScopeStrategy,
AuthorizeEndpointHandlers: fosite.AuthorizeEndpointHandlers{},
TokenEndpointHandlers: fosite.TokenEndpointHandlers{},
TokenIntrospectionHandlers: fosite.TokenIntrospectionHandlers{},
RevocationHandlers: fosite.RevocationHandlers{},
Hasher: &fosite.BCrypt{WorkFactor: config.GetHashCost()},
ScopeStrategy: fosite.HierarchicScopeStrategy,
}

for _, h := range handlers {
Expand Down
15 changes: 15 additions & 0 deletions compose/compose_oauth2.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,10 @@ import (
// an access token, refresh token and authorize code validator.
func OAuth2AuthorizeExplicitFactory(config *Config, storage interface{}, strategy interface{}) interface{} {
return &struct {
// register the handler
*oauth2.AuthorizeExplicitGrantHandler

// also register the validator for access tokens
*oauth2.CoreValidator
}{
AuthorizeExplicitGrantHandler: &oauth2.AuthorizeExplicitGrantHandler{
Expand All @@ -33,7 +36,10 @@ func OAuth2AuthorizeExplicitFactory(config *Config, storage interface{}, strateg
// an access token, refresh token and authorize code validator.
func OAuth2ClientCredentialsGrantFactory(config *Config, storage interface{}, strategy interface{}) interface{} {
return &struct {
// register the handler
*oauth2.ClientCredentialsGrantHandler

// also register the validator for access tokens
*oauth2.CoreValidator
}{
ClientCredentialsGrantHandler: &oauth2.ClientCredentialsGrantHandler{
Expand All @@ -56,7 +62,10 @@ func OAuth2ClientCredentialsGrantFactory(config *Config, storage interface{}, st
// an access token, refresh token and authorize code validator.
func OAuth2RefreshTokenGrantFactory(config *Config, storage interface{}, strategy interface{}) interface{} {
return &struct {
// register the handler
*oauth2.RefreshTokenGrantHandler

// also register the validator for access tokens
*oauth2.CoreValidator
}{
RefreshTokenGrantHandler: &oauth2.RefreshTokenGrantHandler{
Expand All @@ -77,7 +86,10 @@ func OAuth2RefreshTokenGrantFactory(config *Config, storage interface{}, strateg
// an access token, refresh token and authorize code validator.
func OAuth2AuthorizeImplicitFactory(config *Config, storage interface{}, strategy interface{}) interface{} {
return &struct {
// register the handler
*oauth2.AuthorizeImplicitGrantTypeHandler

// also register the validator for access tokens
*oauth2.CoreValidator
}{
AuthorizeImplicitGrantTypeHandler: &oauth2.AuthorizeImplicitGrantTypeHandler{
Expand All @@ -98,7 +110,10 @@ func OAuth2AuthorizeImplicitFactory(config *Config, storage interface{}, strateg
// an access token, refresh token and authorize code validator.
func OAuth2ResourceOwnerPasswordCredentialsFactory(config *Config, storage interface{}, strategy interface{}) interface{} {
return &struct {
// register the handler
*oauth2.ResourceOwnerPasswordCredentialsGrantHandler

// also register the validator for access tokens
*oauth2.CoreValidator
}{
ResourceOwnerPasswordCredentialsGrantHandler: &oauth2.ResourceOwnerPasswordCredentialsGrantHandler{
Expand Down
2 changes: 1 addition & 1 deletion generate-mocks.sh
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ mockgen -package internal -destination internal/id_token_strategy.go github.com/
mockgen -package internal -destination internal/authorize_handler.go github.com/ory-am/fosite AuthorizeEndpointHandler
mockgen -package internal -destination internal/revoke_handler.go github.com/ory-am/fosite RevocationHandler
mockgen -package internal -destination internal/token_handler.go github.com/ory-am/fosite TokenEndpointHandler
mockgen -package internal -destination internal/validator.go github.com/ory-am/fosite TokenValidator
mockgen -package internal -destination internal/introspector.go github.com/ory-am/fosite TokenIntrospector
mockgen -package internal -destination internal/client.go github.com/ory-am/fosite Client
mockgen -package internal -destination internal/request.go github.com/ory-am/fosite Requester
mockgen -package internal -destination internal/access_request.go github.com/ory-am/fosite AccessRequester
Expand Down
7 changes: 6 additions & 1 deletion glide.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions handler/oauth2/flow_refresh_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ func TestRefreshFlow_HandleTokenEndpointRequest(t *testing.T) {
description: "should fail because validation failed",
setup: func() {
store.EXPECT().GetRefreshTokenSession(nil, "refreshtokensig", nil).Return(&fosite.Request{
GrantedScopes:[]string{"offline"},
GrantedScopes: []string{"offline"},
}, nil)
chgen.EXPECT().ValidateRefreshToken(nil, areq, "some.refreshtokensig").Return(errors.New(""))
},
Expand All @@ -70,8 +70,8 @@ func TestRefreshFlow_HandleTokenEndpointRequest(t *testing.T) {
GrantTypes: fosite.Arguments{"refresh_token"},
}
store.EXPECT().GetRefreshTokenSession(nil, "refreshtokensig", nil).Return(&fosite.Request{
Client: &fosite.DefaultClient{ID: ""},
GrantedScopes:[]string{"offline"},
Client: &fosite.DefaultClient{ID: ""},
GrantedScopes: []string{"offline"},
}, nil)
chgen.EXPECT().ValidateRefreshToken(nil, areq, "some.refreshtokensig").AnyTimes().Return(nil)
},
Expand Down
93 changes: 93 additions & 0 deletions handler/oauth2/introspector.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,93 @@
package oauth2

import (
"github.com/ory-am/fosite"
"github.com/pkg/errors"
"golang.org/x/net/context"
)

type CoreValidator struct {
CoreStrategy
CoreStorage
ScopeStrategy fosite.ScopeStrategy
}

func (c *CoreValidator) IntrospectToken(ctx context.Context, token string, tokenType fosite.TokenType, accessRequest fosite.AccessRequester, scopes []string) (err error) {
switch tokenType {
case fosite.RefreshToken:
if err = c.introspectRefreshToken(ctx, token, accessRequest); err == nil {
return err
} else if err = c.introspectAuthorizeCode(ctx, token, accessRequest); err == nil {
return err
} else if err = c.introspectAccessToken(ctx, token, accessRequest, scopes); err == nil {
return err
}
return err
case fosite.AuthorizeCode:
if err = c.introspectAuthorizeCode(ctx, token, accessRequest); err == nil {
return err
} else if err := c.introspectAccessToken(ctx, token, accessRequest, scopes); err == nil {
return err
} else if err := c.introspectRefreshToken(ctx, token, accessRequest); err == nil {
return err
}
return err
}
if err = c.introspectAccessToken(ctx, token, accessRequest, scopes); err == nil {
return err
} else if err := c.introspectRefreshToken(ctx, token, accessRequest); err == nil {
return err
} else if err := c.introspectAuthorizeCode(ctx, token, accessRequest); err == nil {
return err
}
return err
}

func (c *CoreValidator) introspectAccessToken(ctx context.Context, token string, accessRequest fosite.AccessRequester, scopes []string) error {
sig := c.CoreStrategy.AccessTokenSignature(token)
or, err := c.CoreStorage.GetAccessTokenSession(ctx, sig, accessRequest.GetSession())
if err != nil {
return errors.Wrap(fosite.ErrRequestUnauthorized, err.Error())
} else if err := c.CoreStrategy.ValidateAccessToken(ctx, or, token); err != nil {
return err
}

for _, scope := range scopes {
if scope == "" {
continue
}

if !c.ScopeStrategy(or.GetGrantedScopes(), scope) {
return errors.Wrap(fosite.ErrInvalidScope, "")
}
}

accessRequest.Merge(or)
return nil
}

func (c *CoreValidator) introspectRefreshToken(ctx context.Context, token string, accessRequest fosite.AccessRequester) error {
sig := c.CoreStrategy.RefreshTokenSignature(token)
if or, err := c.CoreStorage.GetRefreshTokenSession(ctx, sig, accessRequest.GetSession()); err != nil {
return errors.Wrap(fosite.ErrRequestUnauthorized, err.Error())
} else if err := c.CoreStrategy.ValidateRefreshToken(ctx, or, token); err != nil {
return err
} else {
accessRequest.Merge(or)
}

return nil
}

func (c *CoreValidator) introspectAuthorizeCode(ctx context.Context, token string, accessRequest fosite.AccessRequester) error {
sig := c.CoreStrategy.AuthorizeCodeSignature(token)
if or, err := c.CoreStorage.GetAuthorizeCodeSession(ctx, sig, accessRequest.GetSession()); err != nil {
return errors.Wrap(err, fosite.ErrRequestUnauthorized.Error())
} else if err := c.CoreStrategy.ValidateAuthorizeCode(ctx, or, token); err != nil {
return err
} else {
accessRequest.Merge(or)
}

return nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,10 @@ func TestIntrospectToken(t *testing.T) {
httpreq.Header.Set("Authorization", "bearer")
chgen.EXPECT().AccessTokenSignature("").Return("")
store.EXPECT().GetAccessTokenSession(nil, "", nil).Return(nil, errors.New(""))
chgen.EXPECT().RefreshTokenSignature("").Return("")
store.EXPECT().GetRefreshTokenSession(nil, "", nil).Return(nil, errors.New(""))
chgen.EXPECT().AuthorizeCodeSignature("").Return("")
store.EXPECT().GetAuthorizeCodeSession(nil, "", nil).Return(nil, errors.New(""))
},
expectErr: fosite.ErrRequestUnauthorized,
},
Expand All @@ -44,6 +48,10 @@ func TestIntrospectToken(t *testing.T) {
httpreq.Header.Set("Authorization", "bearer 1234")
chgen.EXPECT().AccessTokenSignature("1234").AnyTimes().Return("asdf")
store.EXPECT().GetAccessTokenSession(nil, "asdf", nil).Return(nil, errors.New(""))
chgen.EXPECT().RefreshTokenSignature("1234").Return("asdf")
store.EXPECT().GetRefreshTokenSession(nil, "asdf", nil).Return(nil, errors.New(""))
chgen.EXPECT().AuthorizeCodeSignature("1234").Return("asdf")
store.EXPECT().GetAuthorizeCodeSession(nil, "asdf", nil).Return(nil, errors.New(""))
},
expectErr: fosite.ErrRequestUnauthorized,
},
Expand All @@ -52,6 +60,10 @@ func TestIntrospectToken(t *testing.T) {
setup: func() {
store.EXPECT().GetAccessTokenSession(nil, "asdf", nil).AnyTimes().Return(areq, nil)
chgen.EXPECT().ValidateAccessToken(nil, areq, "1234").Return(errors.Wrap(fosite.ErrTokenExpired, ""))
chgen.EXPECT().RefreshTokenSignature("1234").Return("asdf")
store.EXPECT().GetRefreshTokenSession(nil, "asdf", nil).Return(nil, errors.New(""))
chgen.EXPECT().AuthorizeCodeSignature("1234").Return("asdf")
store.EXPECT().GetAuthorizeCodeSession(nil, "asdf", nil).Return(nil, errors.New(""))
},
expectErr: fosite.ErrTokenExpired,
},
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package oauth2

import (
"github.com/ory-am/fosite"
"github.com/pkg/errors"
"golang.org/x/net/context"
)

Expand Down Expand Up @@ -39,7 +38,7 @@ func (r *TokenRevocationHandler) RevokeToken(ctx context.Context, token string,
ar, err = discoveryFuncs[1]()
}
if err != nil {
return errors.Wrap(fosite.ErrNotFound, "Nothing to revoke")
return nil
}

requestID := ar.GetID()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,12 +17,12 @@ type TokenRevocationStorage interface {
// revocation of access tokens, then the authorization server SHOULD
// also invalidate all access tokens based on the same authorization
// grant (see Implementation Note).
RevokeRefreshToken(ctx context.Context, requestID string)
RevokeRefreshToken(ctx context.Context, requestID string) error

// RevokeAccessToken revokes an access token as specified in:
// https://tools.ietf.org/html/rfc7009#section-2.1
// If the token passed to the request
// is an access token, the server MAY revoke the respective refresh
// token as well.
RevokeAccessToken(ctx context.Context, requestID string)
RevokeAccessToken(ctx context.Context, requestID string) error
}
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func TestRevokeToken(t *testing.T) {
},
{
description: "should pass - refresh token discovery first; both tokens not found",
expectErr: fosite.ErrNotFound,
expectErr: nil,
mock: func() {
token = "foo"
tokenType = fosite.RefreshToken
Expand All @@ -105,7 +105,7 @@ func TestRevokeToken(t *testing.T) {
},
{
description: "should pass - access token discovery first; both tokens not found",
expectErr: fosite.ErrNotFound,
expectErr: nil,
mock: func() {
token = "foo"
tokenType = fosite.AccessToken
Expand Down
Loading

0 comments on commit f193012

Please sign in to comment.