diff --git a/client.go b/client.go index 7387ff5e1..d5c89d536 100644 --- a/client.go +++ b/client.go @@ -23,12 +23,12 @@ type Client interface { // DefaultClient is a simple default implementation of the Client interface. type DefaultClient struct { - ID string `json:"id"` - Secret []byte `json:"client_secret,omitempty"` - RedirectURIs []string `json:"redirect_uris"` - GrantTypes []string `json:"grant_types"` - ResponseTypes []string `json:"response_types"` - Scopes []string `json:"scopes"` + ID string `json:"id"` + Secret []byte `json:"client_secret,omitempty"` + RedirectURIs []string `json:"redirect_uris"` + GrantTypes []string `json:"grant_types"` + ResponseTypes []string `json:"response_types"` + Scopes []string `json:"scopes"` } func (c *DefaultClient) GetID() string { diff --git a/errors.go b/errors.go index 1cfd801c7..274acfc95 100644 --- a/errors.go +++ b/errors.go @@ -23,16 +23,16 @@ var ( ErrInsufficientEntropy = errors.Errorf("The request used a security parameter (e.g., anti-replay, anti-csrf) with insufficient entropy (minimum of %d characters)", MinParameterEntropy) ErrMisconfiguration = errors.New("The request failed because of an internal error that is probably caused by misconfiguration") ErrNotFound = errors.New("Could not find the requested resource(s)") - ErrInvalidTokenFormat = errors.New("Invalid token format") - ErrTokenSignatureMismatch = errors.New("Token signature mismatch") - ErrTokenExpired = errors.New("Token expired") - ErrScopeNotGranted = errors.New("The token was not granted the requested scope") - ErrTokenClaim = errors.New("The token failed validation due to a claim mismatch") + ErrInvalidTokenFormat = errors.New("Invalid token format") + ErrTokenSignatureMismatch = errors.New("Token signature mismatch") + ErrTokenExpired = errors.New("Token expired") + ErrScopeNotGranted = errors.New("The token was not granted the requested scope") + ErrTokenClaim = errors.New("The token failed validation due to a claim mismatch") ) const ( - errRequestUnauthorized = "request_unauthorized" - errRequestForbidden = "request_forbidden" + errRequestUnauthorized = "request_unauthorized" + errRequestForbidden = "request_forbidden" errInvalidRequestName = "invalid_request" errUnauthorizedClientName = "unauthorized_client" errAccessDeniedName = "acccess_denied" @@ -43,16 +43,16 @@ const ( errUnsupportedGrantTypeName = "unsupported_grant_type" errInvalidGrantName = "invalid_grant" errInvalidClientName = "invalid_client" - UnknownErrorName = "unknown_error" - errNotFound = "not_found" + UnknownErrorName = "unknown_error" + errNotFound = "not_found" errInvalidState = "invalid_state" errMisconfiguration = "misconfiguration" errInsufficientEntropy = "insufficient_entropy" - errInvalidTokenFormat = "invalid_token" - errTokenSignatureMismatch = "token_signature_mismatch" - errTokenExpired = "token_expired" - errScopeNotGranted = "scope_not_granted" - errTokenClaim = "token_claim" + errInvalidTokenFormat = "invalid_token" + errTokenSignatureMismatch = "token_signature_mismatch" + errTokenExpired = "token_expired" + errScopeNotGranted = "scope_not_granted" + errTokenClaim = "token_claim" ) type RFC6749Error struct { @@ -65,69 +65,76 @@ type RFC6749Error struct { func ErrorToRFC6749Error(err error) *RFC6749Error { switch errors.Cause(err) { - case ErrTokenClaim: { - return &RFC6749Error{ - Name: errTokenClaim, - Description: ErrTokenClaim.Error(), - Debug: err.Error(), - Hint: "One or more token claims failed validation.", - StatusCode: http.StatusUnauthorized, - } - } - case ErrScopeNotGranted: { - return &RFC6749Error{ - Name: errScopeNotGranted, - Description: ErrScopeNotGranted.Error(), - Debug: err.Error(), - Hint: "The resource owner did not grant the requested scope.", - StatusCode: http.StatusForbidden, - } - } - case ErrTokenExpired: { - return &RFC6749Error{ - Name: errTokenExpired, - Description: ErrTokenExpired.Error(), - Debug: err.Error(), - Hint: "The token expired.", - StatusCode: http.StatusUnauthorized, - } - } - case ErrInvalidTokenFormat: { - return &RFC6749Error{ - Name: errInvalidTokenFormat, - Description: ErrInvalidTokenFormat.Error(), - Debug: err.Error(), - Hint: "Check that you provided a valid token in the right format.", - StatusCode: http.StatusBadRequest, + case ErrTokenClaim: + { + return &RFC6749Error{ + Name: errTokenClaim, + Description: ErrTokenClaim.Error(), + Debug: err.Error(), + Hint: "One or more token claims failed validation.", + StatusCode: http.StatusUnauthorized, + } + } + case ErrScopeNotGranted: + { + return &RFC6749Error{ + Name: errScopeNotGranted, + Description: ErrScopeNotGranted.Error(), + Debug: err.Error(), + Hint: "The resource owner did not grant the requested scope.", + StatusCode: http.StatusForbidden, + } + } + case ErrTokenExpired: + { + return &RFC6749Error{ + Name: errTokenExpired, + Description: ErrTokenExpired.Error(), + Debug: err.Error(), + Hint: "The token expired.", + StatusCode: http.StatusUnauthorized, + } + } + case ErrInvalidTokenFormat: + { + return &RFC6749Error{ + Name: errInvalidTokenFormat, + Description: ErrInvalidTokenFormat.Error(), + Debug: err.Error(), + Hint: "Check that you provided a valid token in the right format.", + StatusCode: http.StatusBadRequest, + } + } + case ErrTokenSignatureMismatch: + { + return &RFC6749Error{ + Name: errTokenSignatureMismatch, + Description: ErrTokenSignatureMismatch.Error(), + Debug: err.Error(), + Hint: "Check that you provided a valid token in the right format.", + StatusCode: http.StatusBadRequest, + } + } + case ErrRequestUnauthorized: + { + return &RFC6749Error{ + Name: errRequestUnauthorized, + Description: ErrRequestUnauthorized.Error(), + Debug: err.Error(), + Hint: "Check that you provided valid credentials in the right format.", + StatusCode: http.StatusUnauthorized, + } + } + case ErrRequestForbidden: + { + return &RFC6749Error{ + Name: errRequestForbidden, + Description: ErrRequestForbidden.Error(), + Debug: err.Error(), + Hint: "You are not allowed to perform this action.", + StatusCode: http.StatusForbidden, + } } - } - case ErrTokenSignatureMismatch: { - return &RFC6749Error{ - Name: errTokenSignatureMismatch, - Description: ErrTokenSignatureMismatch.Error(), - Debug: err.Error(), - Hint: "Check that you provided a valid token in the right format.", - StatusCode: http.StatusBadRequest, - } - } - case ErrRequestUnauthorized: { - return &RFC6749Error{ - Name: errRequestUnauthorized, - Description: ErrRequestUnauthorized.Error(), - Debug: err.Error(), - Hint: "Check that you provided valid credentials in the right format.", - StatusCode: http.StatusUnauthorized, - } - } - case ErrRequestForbidden: { - return &RFC6749Error{ - Name: errRequestForbidden, - Description: ErrRequestForbidden.Error(), - Debug: err.Error(), - Hint: "You are not allowed to perform this action.", - StatusCode: http.StatusForbidden, - } - } case ErrInvalidRequest: return &RFC6749Error{ Name: errInvalidRequestName, diff --git a/handler/oauth2/flow_refresh.go b/handler/oauth2/flow_refresh.go index 85b7e543d..3dfda7658 100644 --- a/handler/oauth2/flow_refresh.go +++ b/handler/oauth2/flow_refresh.go @@ -47,15 +47,12 @@ func (c *RefreshTokenGrantHandler) HandleTokenEndpointRequest(ctx context.Contex return errors.Wrap(fosite.ErrInvalidRequest, err.Error()) } - request.SetRequestedScopes(accessRequest.GetRequestedScopes()) - for _, scope := range accessRequest.GetGrantedScopes() { - request.GrantScope(scope) - } - // The authorization server MUST ... and ensure that the refresh token was issued to the authenticated client if accessRequest.GetClient().GetID() != request.GetClient().GetID() { return errors.Wrap(fosite.ErrInvalidRequest, "Client ID mismatch") } + + request.Merge(accessRequest) return nil } diff --git a/handler/oauth2/flow_refresh_test.go b/handler/oauth2/flow_refresh_test.go index 3a9ac3709..c01ca1657 100644 --- a/handler/oauth2/flow_refresh_test.go +++ b/handler/oauth2/flow_refresh_test.go @@ -20,6 +20,7 @@ func TestRefreshFlow_HandleTokenEndpointRequest(t *testing.T) { defer ctrl.Finish() areq := fosite.NewAccessRequest(nil) + sess := struct{ Subject string }{Subject: "othersub"} httpreq := &http.Request{PostForm: url.Values{}} h := RefreshTokenGrantHandler{ @@ -31,6 +32,7 @@ func TestRefreshFlow_HandleTokenEndpointRequest(t *testing.T) { description string setup func() expectErr error + expect func() }{ { description: "should fail because not responsible", @@ -73,13 +75,30 @@ func TestRefreshFlow_HandleTokenEndpointRequest(t *testing.T) { { description: "should pass", setup: func() { - store.EXPECT().GetRefreshTokenSession(nil, "refreshtokensig", nil).Return(&fosite.Request{Client: &fosite.DefaultClient{ID: "foo"}}, nil) + store.EXPECT().GetRefreshTokenSession(nil, "refreshtokensig", nil).Return(&fosite.Request{ + Client: &fosite.DefaultClient{ID: "foo"}, + GrantedScopes: fosite.Arguments{"foo"}, + Scopes: fosite.Arguments{"foo", "bar"}, + Session: sess, + Form: url.Values{"foo": []string{"bar"}}, + RequestedAt: time.Now().Round(time.Hour), + }, nil) + }, + expect: func() { + assert.Equal(t, sess, areq.Session) + assert.Equal(t, time.Now().Round(time.Hour), areq.RequestedAt) + assert.Equal(t, fosite.Arguments{"foo"}, areq.GrantedScopes) + assert.Equal(t, fosite.Arguments{"foo", "bar"}, areq.Scopes) + assert.Equal(t, url.Values{"foo": []string{"bar"}}, areq.Form) }, }, } { c.setup() err := h.HandleTokenEndpointRequest(nil, httpreq, areq) assert.True(t, errors.Cause(err) == c.expectErr, "(%d) %s\n%s\n%s", k, c.description, err, c.expectErr) + if c.expect != nil { + c.expect() + } t.Logf("Passed test case %d", k) } } diff --git a/handler/oauth2/strategy_hmacsha.go b/handler/oauth2/strategy_hmacsha.go index 94db67bf9..3a3c0e0c9 100644 --- a/handler/oauth2/strategy_hmacsha.go +++ b/handler/oauth2/strategy_hmacsha.go @@ -4,11 +4,11 @@ import ( "reflect" "time" + "fmt" "github.com/ory-am/fosite" enigma "github.com/ory-am/fosite/token/hmac" "github.com/pkg/errors" "golang.org/x/net/context" - "fmt" ) type HMACSHAStrategy struct { diff --git a/handler/oauth2/strategy_jwt.go b/handler/oauth2/strategy_jwt.go index 83caf0131..7d50aac62 100644 --- a/handler/oauth2/strategy_jwt.go +++ b/handler/oauth2/strategy_jwt.go @@ -3,9 +3,9 @@ package oauth2 import ( "strings" + jwtx "github.com/dgrijalva/jwt-go" "github.com/ory-am/fosite" "github.com/ory-am/fosite/token/jwt" - jwtx "github.com/dgrijalva/jwt-go" "github.com/pkg/errors" "golang.org/x/net/context" ) @@ -82,13 +82,13 @@ func (h *RS256JWTStrategy) validate(token string) error { return errors.Wrap(fosite.ErrTokenExpired, err.Error()) case jwtx.ValidationErrorIssuedAt: return errors.Wrap(fosite.ErrTokenClaim, err.Error()) - case jwtx.ValidationErrorIssuer : + case jwtx.ValidationErrorIssuer: return errors.Wrap(fosite.ErrTokenClaim, err.Error()) case jwtx.ValidationErrorNotValidYet: return errors.Wrap(fosite.ErrTokenClaim, err.Error()) case jwtx.ValidationErrorId: return errors.Wrap(fosite.ErrTokenClaim, err.Error()) - case jwtx.ValidationErrorClaimsInvalid : + case jwtx.ValidationErrorClaimsInvalid: return errors.Wrap(fosite.ErrTokenClaim, err.Error()) } return errors.Wrap(fosite.ErrRequestUnauthorized, err.Error()) diff --git a/handler/openid/flow_hybrid.go b/handler/openid/flow_hybrid.go index 894a34424..742333ca6 100644 --- a/handler/openid/flow_hybrid.go +++ b/handler/openid/flow_hybrid.go @@ -5,12 +5,12 @@ import ( "fmt" + "encoding/base64" "github.com/ory-am/fosite" "github.com/ory-am/fosite/handler/oauth2" "github.com/ory-am/fosite/token/jwt" "github.com/pkg/errors" "golang.org/x/net/context" - "encoding/base64" ) type OpenIDConnectHybridHandler struct { diff --git a/handler/openid/flow_implicit.go b/handler/openid/flow_implicit.go index 6a0592fad..02441460e 100644 --- a/handler/openid/flow_implicit.go +++ b/handler/openid/flow_implicit.go @@ -5,12 +5,12 @@ import ( "fmt" + "encoding/base64" "github.com/ory-am/fosite" "github.com/ory-am/fosite/handler/oauth2" "github.com/ory-am/fosite/token/jwt" "github.com/pkg/errors" "golang.org/x/net/context" - "encoding/base64" ) type OpenIDConnectImplicitHandler struct { diff --git a/token/hmac/hmacsha.go b/token/hmac/hmacsha.go index 034e816e8..d8f2cf6be 100644 --- a/token/hmac/hmacsha.go +++ b/token/hmac/hmacsha.go @@ -9,9 +9,9 @@ import ( "fmt" "strings" + "github.com/ory-am/fosite" "github.com/ory-am/fosite/rand" "github.com/pkg/errors" - "github.com/ory-am/fosite" ) // HMACStrategy is responsible for generating and validating challenges. @@ -102,7 +102,7 @@ func (c *HMACStrategy) Validate(token string) error { if !hmac.Equal(decodedSignature, mac.Sum([]byte{})) { // Hash is invalid - return errors.Wrap(fosite.ErrTokenSignatureMismatch, "") + return errors.Wrap(fosite.ErrTokenSignatureMismatch, "") } return nil