Skip to content

Commit

Permalink
fix: include at_hash claim in authcode flow's ID token
Browse files Browse the repository at this point in the history
  • Loading branch information
cfryanr authored and aeneasr committed Jun 23, 2022
1 parent 18477b9 commit 8d5f055
Show file tree
Hide file tree
Showing 2 changed files with 102 additions and 66 deletions.
2 changes: 1 addition & 1 deletion handler/openid/flow_explicit_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ func (c *OpenIDConnectExplicitHandler) PopulateTokenEndpointResponse(ctx context
return errorsx.WithStack(fosite.ErrUnauthorizedClient.WithHint("The OAuth 2.0 Client is not allowed to use the authorization grant \"authorization_code\"."))
}

sess, ok := requester.GetSession().(Session)
sess, ok := authorize.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
166 changes: 101 additions & 65 deletions handler/openid/flow_explicit_token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -46,84 +46,76 @@ func TestHandleTokenEndpointRequest(t *testing.T) {
}

func TestExplicit_PopulateTokenEndpointResponse(t *testing.T) {
ctrl := gomock.NewController(t)
store := internal.NewMockOpenIDConnectRequestStorage(ctrl)
defer ctrl.Finish()

session := &DefaultSession{
Claims: &jwt.IDTokenClaims{
Subject: "peter",
},
Headers: &jwt.Headers{},
}
aresp := fosite.NewAccessResponse()
areq := fosite.NewAccessRequest(session)

var j = &DefaultStrategy{
Signer: &jwt.DefaultSigner{
GetPrivateKey: func(ctx context.Context) (interface{}, error) {
return key, nil
},
},
Config: &fosite.Config{
MinParameterEntropy: fosite.MinParameterEntropy,
},
}

h := &OpenIDConnectExplicitHandler{
OpenIDConnectRequestStorage: store,
IDTokenHandleHelper: &IDTokenHandleHelper{
IDTokenStrategy: j,
},
}
for k, c := range []struct {
description string
setup func()
setup func(store *internal.MockOpenIDConnectRequestStorage, req *fosite.AccessRequest)
expectErr error
check func(t *testing.T, aresp *fosite.AccessResponse)
}{
{
description: "should fail because invalid response type",
setup: func() {},
expectErr: fosite.ErrUnknownRequest,
description: "should fail because current request has invalid grant type",
setup: func(store *internal.MockOpenIDConnectRequestStorage, req *fosite.AccessRequest) {
req.GrantTypes = fosite.Arguments{"some_other_grant_type"}
},
expectErr: fosite.ErrUnknownRequest,
},
{
description: "should fail because lookup returns not found",
setup: func() {
areq.GrantTypes = fosite.Arguments{"authorization_code"}
areq.Client = &fosite.DefaultClient{
GrantTypes: fosite.Arguments{"authorization_code"},
//ResponseTypes: fosite.Arguments{"id_token"},
}
areq.Form.Set("code", "foobar")
store.EXPECT().GetOpenIDConnectSession(nil, "foobar", areq).Return(nil, ErrNoSessionFound)
description: "should fail because storage lookup returns not found",
setup: func(store *internal.MockOpenIDConnectRequestStorage, req *fosite.AccessRequest) {
req.GrantTypes = fosite.Arguments{"authorization_code"}
req.Form.Set("code", "foobar")
store.EXPECT().GetOpenIDConnectSession(nil, "foobar", req).Return(nil, ErrNoSessionFound)
},
expectErr: fosite.ErrUnknownRequest,
},
{
description: "should fail because lookup fails",
setup: func() {
areq.GrantTypes = fosite.Arguments{"authorization_code"}
store.EXPECT().GetOpenIDConnectSession(nil, "foobar", areq).Return(nil, errors.New(""))
description: "should fail because storage lookup fails",
setup: func(store *internal.MockOpenIDConnectRequestStorage, req *fosite.AccessRequest) {
req.GrantTypes = fosite.Arguments{"authorization_code"}
req.Form.Set("code", "foobar")
store.EXPECT().GetOpenIDConnectSession(nil, "foobar", req).Return(nil, errors.New(""))
},
expectErr: fosite.ErrServerError,
},
{
description: "should fail because missing scope in original request",
setup: func() {
areq.GrantTypes = fosite.Arguments{"authorization_code"}
store.EXPECT().GetOpenIDConnectSession(nil, "foobar", areq).Return(fosite.NewAuthorizeRequest(), nil)
description: "should fail because stored request is missing openid scope",
setup: func(store *internal.MockOpenIDConnectRequestStorage, req *fosite.AccessRequest) {
req.GrantTypes = fosite.Arguments{"authorization_code"}
req.Form.Set("code", "foobar")
store.EXPECT().GetOpenIDConnectSession(nil, "foobar", req).Return(fosite.NewAuthorizeRequest(), nil)
},
expectErr: fosite.ErrMisconfiguration,
},
{
description: "should fail because current request's client does not have authorization_code grant type",
setup: func(store *internal.MockOpenIDConnectRequestStorage, req *fosite.AccessRequest) {
req.Client = &fosite.DefaultClient{
GrantTypes: fosite.Arguments{"some_other_grant_type"},
}
req.GrantTypes = fosite.Arguments{"authorization_code"}
req.Form.Set("code", "foobar")
storedReq := fosite.NewAuthorizeRequest()
storedReq.GrantedScope = fosite.Arguments{"openid"}
store.EXPECT().GetOpenIDConnectSession(nil, "foobar", req).Return(storedReq, nil)
},
expectErr: fosite.ErrUnauthorizedClient,
},
{
description: "should pass",
setup: func() {
r := fosite.NewAuthorizeRequest()
r.Session = areq.Session
r.GrantedScope = fosite.Arguments{"openid"}
r.Form.Set("nonce", "1111111111111111")
store.EXPECT().GetOpenIDConnectSession(nil, gomock.Any(), areq).AnyTimes().Return(r, nil)
setup: func(store *internal.MockOpenIDConnectRequestStorage, req *fosite.AccessRequest) {
req.Client = &fosite.DefaultClient{
GrantTypes: fosite.Arguments{"authorization_code"},
}
req.GrantTypes = fosite.Arguments{"authorization_code"}
req.Form.Set("code", "foobar")
storedSession := &DefaultSession{
Claims: &jwt.IDTokenClaims{Subject: "peter"},
}
storedReq := fosite.NewAuthorizeRequest()
storedReq.Session = storedSession
storedReq.GrantedScope = fosite.Arguments{"openid"}
storedReq.Form.Set("nonce", "1111111111111111")
store.EXPECT().GetOpenIDConnectSession(nil, "foobar", req).Return(storedReq, nil)
},
check: func(t *testing.T, aresp *fosite.AccessResponse) {
assert.NotEmpty(t, aresp.GetExtra("id_token"))
Expand All @@ -137,22 +129,66 @@ func TestExplicit_PopulateTokenEndpointResponse(t *testing.T) {
},
},
{
description: "should fail because missing subject claim",
setup: func() {
session.Claims.Subject = ""
description: "should fail because stored request's session is missing subject claim",
setup: func(store *internal.MockOpenIDConnectRequestStorage, req *fosite.AccessRequest) {
req.GrantTypes = fosite.Arguments{"authorization_code"}
req.Form.Set("code", "foobar")
storedSession := &DefaultSession{
Claims: &jwt.IDTokenClaims{Subject: ""},
}
storedReq := fosite.NewAuthorizeRequest()
storedReq.Session = storedSession
storedReq.GrantedScope = fosite.Arguments{"openid"}
store.EXPECT().GetOpenIDConnectSession(nil, "foobar", req).Return(storedReq, nil)
},
expectErr: fosite.ErrServerError,
},
{
description: "should fail because missing session",
setup: func() {
areq.Session = nil
description: "should fail because stored request is missing session",
setup: func(store *internal.MockOpenIDConnectRequestStorage, req *fosite.AccessRequest) {
req.GrantTypes = fosite.Arguments{"authorization_code"}
req.Form.Set("code", "foobar")
storedReq := fosite.NewAuthorizeRequest()
storedReq.Session = nil
storedReq.GrantScope("openid")
store.EXPECT().GetOpenIDConnectSession(nil, "foobar", req).Return(storedReq, nil)
},
expectErr: fosite.ErrServerError,
},
} {
t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) {
c.setup()
t.Run(fmt.Sprintf("case=%d/description=%s", k, c.description), func(t *testing.T) {
ctrl := gomock.NewController(t)
store := internal.NewMockOpenIDConnectRequestStorage(ctrl)
defer ctrl.Finish()

session := &DefaultSession{
Claims: &jwt.IDTokenClaims{
Subject: "peter",
},
Headers: &jwt.Headers{},
}
aresp := fosite.NewAccessResponse()
areq := fosite.NewAccessRequest(session)

var j = &DefaultStrategy{
Signer: &jwt.DefaultSigner{
GetPrivateKey: func(ctx context.Context) (interface{}, error) {
return key, nil
},
},
Config: &fosite.Config{
MinParameterEntropy: fosite.MinParameterEntropy,
},
}

h := &OpenIDConnectExplicitHandler{
OpenIDConnectRequestStorage: store,
IDTokenHandleHelper: &IDTokenHandleHelper{
IDTokenStrategy: j,
},
}

c.setup(store, areq)
err := h.PopulateTokenEndpointResponse(nil, areq, aresp)

if c.expectErr != nil {
Expand Down

0 comments on commit 8d5f055

Please sign in to comment.