Skip to content

Commit

Permalink
handler/oauth2: refresh token does not migrate original access data - c…
Browse files Browse the repository at this point in the history
…loses #103 (#104)
  • Loading branch information
arekkas authored Oct 4, 2016
1 parent e61a25f commit 8ffa0bc
Showing 9 changed files with 119 additions and 96 deletions.
12 changes: 6 additions & 6 deletions client.go
Original file line number Diff line number Diff line change
@@ -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 {
159 changes: 83 additions & 76 deletions errors.go
Original file line number Diff line number Diff line change
@@ -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,
7 changes: 2 additions & 5 deletions handler/oauth2/flow_refresh.go
Original file line number Diff line number Diff line change
@@ -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
}

21 changes: 20 additions & 1 deletion handler/oauth2/flow_refresh_test.go
Original file line number Diff line number Diff line change
@@ -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)
}
}
2 changes: 1 addition & 1 deletion handler/oauth2/strategy_hmacsha.go
Original file line number Diff line number Diff line change
@@ -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 {
6 changes: 3 additions & 3 deletions handler/oauth2/strategy_jwt.go
Original file line number Diff line number Diff line change
@@ -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())
2 changes: 1 addition & 1 deletion handler/openid/flow_hybrid.go
Original file line number Diff line number Diff line change
@@ -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 {
2 changes: 1 addition & 1 deletion handler/openid/flow_implicit.go
Original file line number Diff line number Diff line change
@@ -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 {
4 changes: 2 additions & 2 deletions token/hmac/hmacsha.go
Original file line number Diff line number Diff line change
@@ -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

0 comments on commit 8ffa0bc

Please sign in to comment.