Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

fix: fix the refresh token issue #14

Merged
merged 3 commits into from
Apr 12, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
274 changes: 198 additions & 76 deletions handler/oauth2/flow_authorize_code_token_test.go

Large diffs are not rendered by default.

11 changes: 7 additions & 4 deletions handler/oauth2/flow_generic_code_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func (c *GenericCodeTokenEndpointHandler) PopulateTokenEndpointResponse(ctx cont
return errorsx.WithStack(err)
}

for _, scope := range ar.GetRequestedScopes() {
for _, scope := range ar.GetGrantedScopes() {
wood-push-melon marked this conversation as resolved.
Show resolved Hide resolved
requester.GrantScope(scope)
}

Expand All @@ -105,7 +105,7 @@ func (c *GenericCodeTokenEndpointHandler) PopulateTokenEndpointResponse(ctx cont
}

var refreshToken, refreshTokenSignature string
if c.canIssueRefreshToken(ctx, ar) {
if c.canIssueRefreshToken(ctx, requester) {
wood-push-melon marked this conversation as resolved.
Show resolved Hide resolved
refreshToken, refreshTokenSignature, err = c.RefreshTokenStrategy.GenerateRefreshToken(ctx, requester)
if err != nil {
return errorsx.WithStack(fosite.ErrServerError.WithWrap(err).WithDebug(err.Error()))
Expand Down Expand Up @@ -229,11 +229,14 @@ func (c *GenericCodeTokenEndpointHandler) CanHandleTokenEndpointRequest(ctx cont
}

func (c *GenericCodeTokenEndpointHandler) canIssueRefreshToken(ctx context.Context, requester fosite.Requester) bool {
scope := c.Config.GetRefreshTokenScopes(ctx)
if len(scope) > 0 && !requester.GetGrantedScopes().HasOneOf(scope...) {
scopes := c.Config.GetRefreshTokenScopes(ctx)

// Require one of the refresh token scopes, if set.
if len(scopes) > 0 && !requester.GetGrantedScopes().HasOneOf(scopes...) {
return false
}

// Do not issue a refresh token to clients that cannot use the refresh token grant type.
if !requester.GetClient().GetGrantTypes().Has("refresh_token") {
return false
}
Expand Down
4 changes: 2 additions & 2 deletions handler/openid/flow_device_auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,15 +25,15 @@ type OpenIDConnectDeviceHandler struct {
}

func (c *OpenIDConnectDeviceHandler) HandleDeviceEndpointRequest(ctx context.Context, dar fosite.DeviceRequester, resp fosite.DeviceResponder) error {
if !(dar.GetGrantedScopes().Has("openid")) {
if !(dar.GetRequestedScopes().Has("openid")) {
wood-push-melon marked this conversation as resolved.
Show resolved Hide resolved
return nil
}

if !dar.GetClient().GetGrantTypes().Has(string(fosite.GrantTypeDeviceCode)) {
return nil
}

if len(resp.GetDeviceCode()) == 0 {
if resp.GetDeviceCode() == "" {
return errorsx.WithStack(fosite.ErrMisconfiguration.WithDebug("The device code has not been issued yet, indicating a broken code configuration."))
}

Expand Down
24 changes: 12 additions & 12 deletions handler/openid/flow_device_auth_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ func TestDeviceAuth_HandleDeviceEndpointRequest(t *testing.T) {

client := &fosite.DefaultClient{
ID: "foo",
GrantTypes: fosite.Arguments{string(fosite.GrantTypeDeviceCode)},
GrantTypes: fosite.Arguments{"urn:ietf:params:oauth:grant-type:device_code"},
}

testCases := []struct {
Expand All @@ -78,17 +78,17 @@ func TestDeviceAuth_HandleDeviceEndpointRequest(t *testing.T) {
description: "should ignore because scope openid is not set",
authreq: &fosite.DeviceRequest{
Request: fosite.Request{
GrantedScope: fosite.Arguments{"email"},
RequestedScope: fosite.Arguments{"email"},
},
},
},
{
description: "should ignore because client grant type is invalid",
authreq: &fosite.DeviceRequest{
Request: fosite.Request{
GrantedScope: fosite.Arguments{"openid", "email"},
RequestedScope: fosite.Arguments{"openid", "email"},
Client: &fosite.DefaultClient{
GrantTypes: []string{string(fosite.GrantTypeAuthorizationCode)},
GrantTypes: []string{"authorization_code"},
},
},
},
Expand All @@ -97,8 +97,8 @@ func TestDeviceAuth_HandleDeviceEndpointRequest(t *testing.T) {
description: "should fail because device code is not issued",
authreq: &fosite.DeviceRequest{
Request: fosite.Request{
GrantedScope: fosite.Arguments{"openid", "email"},
Client: client,
RequestedScope: fosite.Arguments{"openid", "email"},
Client: client,
},
},
authresp: &fosite.DeviceResponse{},
Expand All @@ -108,9 +108,9 @@ func TestDeviceAuth_HandleDeviceEndpointRequest(t *testing.T) {
description: "should fail because cannot create session",
authreq: &fosite.DeviceRequest{
Request: fosite.Request{
GrantedScope: fosite.Arguments{"openid", "email"},
Client: client,
Session: session,
RequestedScope: fosite.Arguments{"openid", "email"},
Client: client,
Session: session,
},
},
authresp: &fosite.DeviceResponse{
Expand All @@ -128,9 +128,9 @@ func TestDeviceAuth_HandleDeviceEndpointRequest(t *testing.T) {
description: "should pass",
authreq: &fosite.DeviceRequest{
Request: fosite.Request{
GrantedScope: fosite.Arguments{"openid", "email"},
Client: client,
Session: session,
RequestedScope: fosite.Arguments{"openid", "email"},
Client: client,
Session: session,
},
},
authresp: &fosite.DeviceResponse{
Expand Down
8 changes: 4 additions & 4 deletions handler/openid/flow_device_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,10 @@ func (c *OpenIDConnectDeviceHandler) PopulateTokenEndpointResponse(ctx context.C
return errorsx.WithStack(fosite.ErrUnknownRequest)
}

if !requester.GetClient().GetGrantTypes().Has(string(fosite.GrantTypeDeviceCode)) {
return errorsx.WithStack(fosite.ErrUnauthorizedClient.WithHint("The OAuth 2.0 Client is not allowed to use the authorization grant \"urn:ietf:params:oauth:grant-type:device_code\"."))
}

deviceCode := requester.GetRequestForm().Get("device_code")
signature, err := c.DeviceCodeStrategy.DeviceCodeSignature(ctx, deviceCode)
ar, err := c.OpenIDConnectRequestStorage.GetOpenIDConnectSession(ctx, signature, requester)
Expand All @@ -35,10 +39,6 @@ func (c *OpenIDConnectDeviceHandler) PopulateTokenEndpointResponse(ctx context.C
return errorsx.WithStack(fosite.ErrMisconfiguration.WithDebug("An OpenID Connect session was found but the openid scope is missing, probably due to a broken code configuration."))
}

if !requester.GetClient().GetGrantTypes().Has(string(fosite.GrantTypeDeviceCode)) {
return errorsx.WithStack(fosite.ErrUnauthorizedClient.WithHint("The OAuth 2.0 Client is not allowed to use the authorization grant \"urn:ietf:params:oauth:grant-type:device_code\"."))
}

session, ok := ar.GetSession().(Session)
if !ok {
return errorsx.WithStack(fosite.ErrServerError.WithDebug("Failed to generate id token because session must be of type fosite/handler/openid.Session."))
Expand Down
46 changes: 15 additions & 31 deletions handler/openid/flow_device_token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,7 +81,7 @@ func TestDeviceToken_PopulateTokenEndpointResponse(t *testing.T) {

client := &fosite.DefaultClient{
ID: "foo",
GrantTypes: fosite.Arguments{string(fosite.GrantTypeDeviceCode)},
GrantTypes: fosite.Arguments{"urn:ietf:params:oauth:grant-type:device_code"},
}

testCases := []struct {
Expand All @@ -95,8 +95,9 @@ func TestDeviceToken_PopulateTokenEndpointResponse(t *testing.T) {
{
description: "should fail because the grant type is invalid",
areq: &fosite.AccessRequest{
GrantTypes: fosite.Arguments{string(fosite.GrantTypeAuthorizationCode)},
GrantTypes: fosite.Arguments{"authorization_code"},
Request: fosite.Request{
Client: client,
Form: url.Values{"device_code": []string{"device_code"}},
Session: session,
},
Expand All @@ -107,8 +108,9 @@ func TestDeviceToken_PopulateTokenEndpointResponse(t *testing.T) {
{
description: "should fail because session not found",
areq: &fosite.AccessRequest{
GrantTypes: fosite.Arguments{string(fosite.GrantTypeDeviceCode)},
GrantTypes: fosite.Arguments{"urn:ietf:params:oauth:grant-type:device_code"},
Request: fosite.Request{
Client: client,
Form: url.Values{"device_code": []string{"device_code"}},
Session: session,
},
Expand All @@ -122,8 +124,9 @@ func TestDeviceToken_PopulateTokenEndpointResponse(t *testing.T) {
{
description: "should fail because session lookup fails",
areq: &fosite.AccessRequest{
GrantTypes: fosite.Arguments{string(fosite.GrantTypeDeviceCode)},
GrantTypes: fosite.Arguments{"urn:ietf:params:oauth:grant-type:device_code"},
Request: fosite.Request{
Client: client,
Form: url.Values{"device_code": []string{"device_code"}},
Session: session,
},
Expand All @@ -136,15 +139,17 @@ func TestDeviceToken_PopulateTokenEndpointResponse(t *testing.T) {
{
description: "should fail because auth request grant scope is invalid",
areq: &fosite.AccessRequest{
GrantTypes: fosite.Arguments{string(fosite.GrantTypeDeviceCode)},
GrantTypes: fosite.Arguments{"urn:ietf:params:oauth:grant-type:device_code"},
Request: fosite.Request{
Client: client,
Form: url.Values{"device_code": []string{"device_code"}},
Session: session,
},
},
setup: func(areq *fosite.AccessRequest) {
authreq := &fosite.DeviceRequest{
Request: fosite.Request{
Client: client,
GrantedScope: fosite.Arguments{"email"},
Session: session,
},
Expand All @@ -153,33 +158,10 @@ func TestDeviceToken_PopulateTokenEndpointResponse(t *testing.T) {
},
expectErr: fosite.ErrMisconfiguration,
},
{
description: "should fail because auth request's client grant type is invalid",
areq: &fosite.AccessRequest{
GrantTypes: fosite.Arguments{string(fosite.GrantTypeDeviceCode)},
Request: fosite.Request{
Client: &fosite.DefaultClient{
GrantTypes: fosite.Arguments{string(fosite.GrantTypeAuthorizationCode)},
},
Form: url.Values{"device_code": []string{"device_code"}},
Session: session,
},
},
setup: func(areq *fosite.AccessRequest) {
authreq := &fosite.DeviceRequest{
Request: fosite.Request{
GrantedScope: fosite.Arguments{"openid", "email"},
Session: session,
},
}
store.EXPECT().GetOpenIDConnectSession(gomock.Any(), gomock.Any(), areq).Return(authreq, nil)
},
expectErr: fosite.ErrUnauthorizedClient,
},
{
description: "should fail because auth request is missing session",
areq: &fosite.AccessRequest{
GrantTypes: fosite.Arguments{string(fosite.GrantTypeDeviceCode)},
GrantTypes: fosite.Arguments{"urn:ietf:params:oauth:grant-type:device_code"},
Request: fosite.Request{
Client: client,
Form: url.Values{"device_code": []string{"device_code"}},
Expand All @@ -189,6 +171,7 @@ func TestDeviceToken_PopulateTokenEndpointResponse(t *testing.T) {
setup: func(areq *fosite.AccessRequest) {
authreq := &fosite.DeviceRequest{
Request: fosite.Request{
Client: client,
GrantedScope: fosite.Arguments{"openid", "email"},
},
}
Expand All @@ -199,7 +182,7 @@ func TestDeviceToken_PopulateTokenEndpointResponse(t *testing.T) {
{
description: "should fail because auth request session is missing subject claims",
areq: &fosite.AccessRequest{
GrantTypes: fosite.Arguments{string(fosite.GrantTypeDeviceCode)},
GrantTypes: fosite.Arguments{"urn:ietf:params:oauth:grant-type:device_code"},
Request: fosite.Request{
Client: client,
Form: url.Values{"device_code": []string{"device_code"}},
Expand All @@ -209,6 +192,7 @@ func TestDeviceToken_PopulateTokenEndpointResponse(t *testing.T) {
setup: func(areq *fosite.AccessRequest) {
authreq := &fosite.DeviceRequest{
Request: fosite.Request{
Client: client,
GrantedScope: fosite.Arguments{"openid", "email"},
Session: NewDefaultSession(),
},
Expand All @@ -220,7 +204,7 @@ func TestDeviceToken_PopulateTokenEndpointResponse(t *testing.T) {
{
description: "should pass",
areq: &fosite.AccessRequest{
GrantTypes: fosite.Arguments{string(fosite.GrantTypeDeviceCode)},
GrantTypes: fosite.Arguments{"urn:ietf:params:oauth:grant-type:device_code"},
Request: fosite.Request{
Client: client,
Form: url.Values{"device_code": []string{"device_code"}},
Expand Down
Loading
Loading