Skip to content

Commit

Permalink
chore: resolve comments
Browse files Browse the repository at this point in the history
  • Loading branch information
wood-push-melon committed Mar 12, 2024
1 parent bd62680 commit 15d0e22
Show file tree
Hide file tree
Showing 14 changed files with 378 additions and 190 deletions.
7 changes: 5 additions & 2 deletions compose/compose_oauth2.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,12 @@ func OAuth2AuthorizeExplicitAuthFactory(config fosite.Configurator, storage inte
func Oauth2AuthorizeExplicitTokenFactory(config fosite.Configurator, storage interface{}, strategy interface{}) interface{} {
return &oauth2.AuthorizeExplicitTokenEndpointHandler{
GenericCodeTokenEndpointHandler: oauth2.GenericCodeTokenEndpointHandler{
CodeTokenEndpointHandler: &oauth2.AuthorizeExplicitGrantTokenHandler{
AccessRequestValidator: &oauth2.AuthorizeExplicitGrantAccessRequestValidator{},
CodeHandler: &oauth2.AuthorizeCodeHandler{
AuthorizeCodeStrategy: strategy.(oauth2.AuthorizeCodeStrategy),
AuthorizeCodeStorage: storage.(oauth2.AuthorizeCodeStorage),
},
SessionHandler: &oauth2.AuthorizeExplicitGrantSessionHandler{
AuthorizeCodeStorage: storage.(oauth2.AuthorizeCodeStorage),
},

AccessTokenStrategy: strategy.(oauth2.AccessTokenStrategy),
Expand Down
7 changes: 5 additions & 2 deletions compose/compose_rfc8628.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,10 +26,13 @@ func RFC8628DeviceFactory(config fosite.Configurator, storage interface{}, strat
func RFC8628DeviceAuthorizationTokenFactory(config fosite.Configurator, storage interface{}, strategy interface{}) interface{} {
return &rfc8628.DeviceCodeTokenEndpointHandler{
GenericCodeTokenEndpointHandler: oauth2.GenericCodeTokenEndpointHandler{
CodeTokenEndpointHandler: &rfc8628.DeviceTokenHandler{
AccessRequestValidator: &rfc8628.DeviceAccessRequestValidator{},
CodeHandler: &rfc8628.DeviceCodeHandler{
DeviceRateLimitStrategy: strategy.(rfc8628.DeviceRateLimitStrategy),
DeviceCodeStrategy: strategy.(rfc8628.DeviceCodeStrategy),
DeviceCodeStorage: storage.(rfc8628.DeviceCodeStorage),
},
SessionHandler: &rfc8628.DeviceSessionHandler{
DeviceCodeStorage: storage.(rfc8628.DeviceCodeStorage),
},

AccessTokenStrategy: strategy.(oauth2.AccessTokenStrategy),
Expand Down
24 changes: 0 additions & 24 deletions device_user_request.go

This file was deleted.

1 change: 0 additions & 1 deletion fosite_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,6 @@ func TestAuthorizeEndpointHandlers(t *testing.T) {
}

func TestTokenEndpointHandlers(t *testing.T) {
// h := &oauth2.AuthorizeExplicitGrantHandler{}
h := &oauth2.GenericCodeTokenEndpointHandler{}
hs := TokenEndpointHandlers{}
hs.Append(h)
Expand Down
10 changes: 5 additions & 5 deletions handler.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ import (
)

type AuthorizeEndpointHandler interface {
// HandleAuthorizeEndpointRequest handles an authorize endpoint request. To extend the handler's capabilities, the http request
// HandleAuthorizeRequest handles an authorize endpoint request. To extend the handler's capabilities, the http request
// is passed along, if further information retrieval is required. If the handler feels that he is not responsible for
// the authorize request, he must return nil and NOT modify session nor responder neither requester.
//
Expand All @@ -31,12 +31,12 @@ type TokenEndpointHandler interface {
// the request, this method should return ErrUnknownRequest and otherwise handle the request.
HandleTokenEndpointRequest(ctx context.Context, requester AccessRequester) error

// CanSkipClientAuth indicates if client authentication can be skipped. By default, it MUST be false, unless you are
// CanSkipClientAuth indicates if client authentication can be skipped. By default it MUST be false, unless you are
// implementing extension grant type, which allows unauthenticated client. CanSkipClientAuth must be called
// before HandleTokenEndpointRequest to decide, if AccessRequester will contain authenticated client.
CanSkipClientAuth(ctx context.Context, requester AccessRequester) bool

// CanHandleTokenEndpointRequest indicates, if TokenEndpointHandler can handle this request or not. If true,
// CanHandleRequest indicates, if TokenEndpointHandler can handle this request or not. If true,
// HandleTokenEndpointRequest can be called.
CanHandleTokenEndpointRequest(ctx context.Context, requester AccessRequester) bool
}
Expand All @@ -61,7 +61,7 @@ type RevocationHandler interface {

// PushedAuthorizeEndpointHandler is the interface that handles PAR (https://datatracker.ietf.org/doc/html/rfc9126)
type PushedAuthorizeEndpointHandler interface {
// HandlePushedAuthorizeEndpointRequest handles a pushed authorize endpoint request. To extend the handler's capabilities, the http request
// HandlePushedAuthorizeRequest handles a pushed authorize endpoint request. To extend the handler's capabilities, the http request
// is passed along, if further information retrieval is required. If the handler feels that he is not responsible for
// the pushed authorize request, he must return nil and NOT modify session nor responder neither requester.
HandlePushedAuthorizeEndpointRequest(ctx context.Context, requester AuthorizeRequester, responder PushedAuthorizeResponder) error
Expand All @@ -73,7 +73,7 @@ type DeviceEndpointHandler interface {
// is passed along, if further information retrieval is required. If the handler feels that he is not responsible for
// the device authorize request, he must return nil and NOT modify session nor responder neither requester.
//
// The following spec is a good example of what HandleDeviceUserRequest should do.
// The following spec is a good example of what HandleDeviceEndpointRequest should do.
// * https://tools.ietf.org/html/rfc8628#section-3.2
HandleDeviceEndpointRequest(ctx context.Context, requester DeviceRequester, responder DeviceResponder) error
}
84 changes: 62 additions & 22 deletions handler/oauth2/flow_authorize_code_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,54 +6,94 @@ package oauth2
import (
"context"

"github.com/pkg/errors"

"github.com/ory/x/errorsx"

"github.com/ory/fosite"
)

// AuthorizeExplicitGrantTokenHandler is a response handler for the Authorize Code grant using the explicit grant type
// as defined in https://tools.ietf.org/html/rfc6749#section-4.1
type AuthorizeExplicitGrantTokenHandler struct {
type AuthorizeCodeHandler struct {
AuthorizeCodeStrategy AuthorizeCodeStrategy
AuthorizeCodeStorage AuthorizeCodeStorage
}

func (c AuthorizeExplicitGrantTokenHandler) ValidateGrantTypes(ctx context.Context, requester fosite.AccessRequester) error {
if !requester.GetClient().GetGrantTypes().Has("authorization_code") {
return errorsx.WithStack(fosite.ErrUnauthorizedClient.WithHint("The OAuth 2.0 Client is not allowed to use authorization grant \"authorization_code\"."))
}

return nil
func (c AuthorizeCodeHandler) Code(ctx context.Context, requester fosite.AccessRequester) (code string, signature string, err error) {
code = requester.GetRequestForm().Get("code")
signature = c.AuthorizeCodeStrategy.AuthorizeCodeSignature(ctx, code)
return code, signature, nil
}

func (c AuthorizeExplicitGrantTokenHandler) ValidateCode(ctx context.Context, requester fosite.AccessRequester, code string) error {
func (c AuthorizeCodeHandler) ValidateCode(ctx context.Context, requester fosite.AccessRequester, code string) error {
return c.AuthorizeCodeStrategy.ValidateAuthorizeCode(ctx, requester, code)
}

func (c AuthorizeExplicitGrantTokenHandler) GetCodeAndSession(ctx context.Context, requester fosite.AccessRequester) (code string, signature string, authorizeRequest fosite.Requester, err error) {
code = requester.GetRequestForm().Get("code")
signature = c.AuthorizeCodeStrategy.AuthorizeCodeSignature(ctx, code)
req, err := c.AuthorizeCodeStorage.GetAuthorizeCodeSession(ctx, signature, requester.GetSession())
return code, signature, req, err
type AuthorizeExplicitGrantSessionHandler struct {
AuthorizeCodeStorage AuthorizeCodeStorage
}

func (c AuthorizeExplicitGrantTokenHandler) InvalidateSession(ctx context.Context, signature string) error {
return c.AuthorizeCodeStorage.InvalidateAuthorizeCodeSession(ctx, signature)
func (s AuthorizeExplicitGrantSessionHandler) Session(ctx context.Context, requester fosite.AccessRequester, codeSignature string) (fosite.Requester, error) {
req, err := s.AuthorizeCodeStorage.GetAuthorizeCodeSession(ctx, codeSignature, requester.GetSession())

if err != nil && errors.Is(err, fosite.ErrInvalidatedAuthorizeCode) {
if req == nil {
return req, fosite.ErrServerError.
WithHint("Misconfigured code lead to an error that prohibited the OAuth 2.0 Framework from processing this request.").
WithDebug("\"GetAuthorizeCodeSession\" must return a value for \"fosite.Requester\" when returning \"ErrInvalidatedAuthorizeCode\".")
}

return req, err
}

if err != nil && errors.Is(err, fosite.ErrNotFound) {
return nil, errorsx.WithStack(fosite.ErrInvalidGrant.WithWrap(err).WithDebug(err.Error()))
}

if err != nil {
return nil, errorsx.WithStack(fosite.ErrServerError.WithWrap(err).WithDebug(err.Error()))
}

return req, err
}

func (c AuthorizeExplicitGrantTokenHandler) CanSkipClientAuth(ctx context.Context, requester fosite.AccessRequester) bool {
return false
func (s AuthorizeExplicitGrantSessionHandler) InvalidateSession(ctx context.Context, codeSignature string) error {
return s.AuthorizeCodeStorage.InvalidateAuthorizeCodeSession(ctx, codeSignature)
}

func (c AuthorizeExplicitGrantTokenHandler) CanHandleTokenEndpointRequest(ctx context.Context, requester fosite.AccessRequester) bool {
type AuthorizeExplicitGrantAccessRequestValidator struct{}

func (v AuthorizeExplicitGrantAccessRequestValidator) ValidateRequest(requester fosite.AccessRequester) bool {
return requester.GetGrantTypes().ExactOne("authorization_code")
}

func (v AuthorizeExplicitGrantAccessRequestValidator) ValidateClientAuth(requester fosite.AccessRequester) bool {
return false
}

func (v AuthorizeExplicitGrantAccessRequestValidator) ValidateGrantTypes(requester fosite.AccessRequester) error {
if !requester.GetClient().GetGrantTypes().Has("authorization_code") {
return errorsx.WithStack(fosite.ErrUnauthorizedClient.WithHint("The OAuth 2.0 Client is not allowed to use authorization grant \"authorization_code\"."))
}

return nil
}

func (v AuthorizeExplicitGrantAccessRequestValidator) ValidateRedirectURI(accessRequester fosite.AccessRequester, authorizeRequester fosite.Requester) error {
forcedRedirectURI := authorizeRequester.GetRequestForm().Get("redirect_uri")
requestedRedirectURI := accessRequester.GetRequestForm().Get("redirect_uri")
if forcedRedirectURI != "" && forcedRedirectURI != requestedRedirectURI {
return errorsx.WithStack(fosite.ErrInvalidGrant.WithHint("The \"redirect_uri\" from this request does not match the one from the authorize request."))
}

return nil
}

type AuthorizeExplicitTokenEndpointHandler struct {
GenericCodeTokenEndpointHandler
}

var (
_ CodeTokenEndpointHandler = (*AuthorizeExplicitGrantTokenHandler)(nil)
_ AccessRequestValidator = (*AuthorizeExplicitGrantAccessRequestValidator)(nil)
_ CodeHandler = (*AuthorizeCodeHandler)(nil)
_ SessionHandler = (*AuthorizeExplicitGrantSessionHandler)(nil)
_ fosite.TokenEndpointHandler = (*AuthorizeExplicitTokenEndpointHandler)(nil)
)
19 changes: 14 additions & 5 deletions handler/oauth2/flow_authorize_code_token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -208,9 +208,12 @@ func TestAuthorizeCode_PopulateTokenEndpointResponse(t *testing.T) {
RefreshTokenScopes: []string{"offline"},
}
h = GenericCodeTokenEndpointHandler{
CodeTokenEndpointHandler: &AuthorizeExplicitGrantTokenHandler{
AccessRequestValidator: &AuthorizeExplicitGrantAccessRequestValidator{},
CodeHandler: &AuthorizeCodeHandler{
AuthorizeCodeStrategy: strategy,
AuthorizeCodeStorage: store,
},
SessionHandler: &AuthorizeExplicitGrantSessionHandler{
AuthorizeCodeStorage: store,
},
AccessTokenStrategy: strategy,
RefreshTokenStrategy: strategy,
Expand Down Expand Up @@ -252,9 +255,12 @@ func TestAuthorizeCode_HandleTokenEndpointRequest(t *testing.T) {
AuthorizeCodeLifespan: time.Minute,
}
h := GenericCodeTokenEndpointHandler{
CodeTokenEndpointHandler: &AuthorizeExplicitGrantTokenHandler{
AccessRequestValidator: &AuthorizeExplicitGrantAccessRequestValidator{},
CodeHandler: &AuthorizeCodeHandler{
AuthorizeCodeStrategy: strategy,
AuthorizeCodeStorage: store,
},
SessionHandler: &AuthorizeExplicitGrantSessionHandler{
AuthorizeCodeStorage: store,
},
TokenRevocationStorage: store,
Config: config,
Expand Down Expand Up @@ -668,8 +674,11 @@ func TestAuthorizeCodeTransactional_HandleTokenEndpointRequest(t *testing.T) {
AuthorizeCodeLifespan: time.Minute,
}
handler := GenericCodeTokenEndpointHandler{
CodeTokenEndpointHandler: &AuthorizeExplicitGrantTokenHandler{
AccessRequestValidator: &AuthorizeExplicitGrantAccessRequestValidator{},
CodeHandler: &AuthorizeCodeHandler{
AuthorizeCodeStrategy: &strategy,
},
SessionHandler: &AuthorizeExplicitGrantSessionHandler{
AuthorizeCodeStorage: authorizeTransactionalStore{
mockTransactional,
mockAuthorizeStore,
Expand Down
Loading

0 comments on commit 15d0e22

Please sign in to comment.