Skip to content

Commit

Permalink
fix(openid): session not deleted after final use (#44)
Browse files Browse the repository at this point in the history
This fixes an issue where the OpenID Connect 1.0 session was not deleted after it being used.
  • Loading branch information
james-d-elliott authored Feb 14, 2024
1 parent c835349 commit 5f39274
Show file tree
Hide file tree
Showing 3 changed files with 30 additions and 3 deletions.
8 changes: 7 additions & 1 deletion handler/openid/flow_explicit_token.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,9 @@ func (c *OpenIDConnectExplicitHandler) PopulateTokenEndpointResponse(ctx context
return errorsx.WithStack(oauth2.ErrUnknownRequest)
}

authorize, err := c.OpenIDConnectRequestStorage.GetOpenIDConnectSession(ctx, requester.GetRequestForm().Get(consts.FormParameterAuthorizationCode), requester)
authorizeCode := requester.GetRequestForm().Get(consts.FormParameterAuthorizationCode)

authorize, err := c.OpenIDConnectRequestStorage.GetOpenIDConnectSession(ctx, authorizeCode, requester)
if errors.Is(err, ErrNoSessionFound) {
return errorsx.WithStack(oauth2.ErrUnknownRequest.WithWrap(err).WithDebugError(err))
} else if err != nil {
Expand All @@ -42,6 +44,10 @@ func (c *OpenIDConnectExplicitHandler) PopulateTokenEndpointResponse(ctx context
return errorsx.WithStack(oauth2.ErrServerError.WithDebug("Failed to generate id token because session must be of type oauth2/handler/openid.Session."))
}

if err = c.OpenIDConnectRequestStorage.DeleteOpenIDConnectSession(ctx, authorizeCode); err != nil {
return errorsx.WithStack(oauth2.ErrServerError.WithWrap(err).WithDebugError(err))
}

claims := sess.IDTokenClaims()
if claims.Subject == "" {
return errorsx.WithStack(oauth2.ErrServerError.WithDebug("Failed to generate id token because subject is an empty string."))
Expand Down
22 changes: 22 additions & 0 deletions handler/openid/flow_explicit_token_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ func TestExplicit_PopulateTokenEndpointResponse(t *testing.T) {
storedReq.GrantedScope = oauth2.Arguments{consts.ScopeOpenID}
storedReq.Form.Set(consts.FormParameterNonce, "1111111111111111")
store.EXPECT().GetOpenIDConnectSession(context.TODO(), "foobar", req).Return(storedReq, nil)
store.EXPECT().DeleteOpenIDConnectSession(gomock.Any(), "foobar").Return(nil)
},
check: func(t *testing.T, aresp *oauth2.AccessResponse) {
assert.NotEmpty(t, aresp.GetExtra(consts.AccessResponseIDToken))
Expand Down Expand Up @@ -133,6 +134,7 @@ func TestExplicit_PopulateTokenEndpointResponse(t *testing.T) {
storedReq.GrantedScope = oauth2.Arguments{consts.ScopeOpenID}
storedReq.Form.Set("nonce", "1111111111111111")
store.EXPECT().GetOpenIDConnectSession(context.TODO(), "foobar", req).Return(storedReq, nil)
store.EXPECT().DeleteOpenIDConnectSession(gomock.Any(), "foobar").Return(nil)
},
check: func(t *testing.T, aresp *oauth2.AccessResponse) {
assert.NotEmpty(t, aresp.GetExtra("id_token"))
Expand All @@ -159,6 +161,7 @@ func TestExplicit_PopulateTokenEndpointResponse(t *testing.T) {
storedReq.Session = storedSession
storedReq.GrantedScope = oauth2.Arguments{consts.ScopeOpenID}
store.EXPECT().GetOpenIDConnectSession(context.TODO(), "foobar", req).Return(storedReq, nil)
store.EXPECT().DeleteOpenIDConnectSession(gomock.Any(), "foobar").Return(nil)
},
expectErr: oauth2.ErrServerError,
},
Expand All @@ -174,6 +177,25 @@ func TestExplicit_PopulateTokenEndpointResponse(t *testing.T) {
},
expectErr: oauth2.ErrServerError,
},
{
description: "should fail because storage returns error when deleting openid session",
setup: func(store *internal.MockOpenIDConnectRequestStorage, req *oauth2.AccessRequest) {
req.Client = &oauth2.DefaultClient{
GrantTypes: oauth2.Arguments{"authorization_code"},
}
req.GrantTypes = oauth2.Arguments{"authorization_code"}
req.Form.Set("code", "foobar")
storedSession := &DefaultSession{
Claims: &jwt.IDTokenClaims{Subject: "peter"},
}
storedReq := oauth2.NewAuthorizeRequest()
storedReq.Session = storedSession
storedReq.GrantedScope = oauth2.Arguments{"openid"}
store.EXPECT().GetOpenIDConnectSession(gomock.Any(), "foobar", req).Return(storedReq, nil)
store.EXPECT().DeleteOpenIDConnectSession(gomock.Any(), "foobar").Return(errors.New("delete openid session err"))
},
expectErr: oauth2.ErrServerError,
},
} {
t.Run(fmt.Sprintf("case=%d/description=%s", k, c.description), func(t *testing.T) {
ctrl := gomock.NewController(t)
Expand Down
3 changes: 1 addition & 2 deletions handler/openid/storage.go
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ type OpenIDConnectRequestStorage interface {
// - or an arbitrary error if an error occurred.
GetOpenIDConnectSession(ctx context.Context, authorizeCode string, requester oauth2.Requester) (oauth2.Requester, error)

// Deprecated: DeleteOpenIDConnectSession is not called from anywhere.
// Originally, it should remove an open id connect session from the store.
// DeleteOpenIDConnectSession deletes the OpenID Connect 1.0 session from storage.
DeleteOpenIDConnectSession(ctx context.Context, authorizeCode string) error
}

0 comments on commit 5f39274

Please sign in to comment.