...

Source file src/github.com/ory/fosite/handler/oauth2/flow_authorize_code_token_test.go

Documentation: github.com/ory/fosite/handler/oauth2

     1  /*
     2   * Copyright © 2015-2018 Aeneas Rekkas <aeneas+oss@aeneas.io>
     3   *
     4   * Licensed under the Apache License, Version 2.0 (the "License");
     5   * you may not use this file except in compliance with the License.
     6   * You may obtain a copy of the License at
     7   *
     8   *     http://www.apache.org/licenses/LICENSE-2.0
     9   *
    10   * Unless required by applicable law or agreed to in writing, software
    11   * distributed under the License is distributed on an "AS IS" BASIS,
    12   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    13   * See the License for the specific language governing permissions and
    14   * limitations under the License.
    15   *
    16   * @author		Aeneas Rekkas <aeneas+oss@aeneas.io>
    17   * @copyright 	2015-2018 Aeneas Rekkas <aeneas+oss@aeneas.io>
    18   * @license 	Apache-2.0
    19   *
    20   */
    21  
    22  package oauth2
    23  
    24  import (
    25  	"context"
    26  	"fmt"
    27  	"net/url"
    28  	"testing" //"time"
    29  
    30  	"github.com/golang/mock/gomock"
    31  
    32  	"github.com/ory/fosite/internal"
    33  
    34  	//"github.com/golang/mock/gomock"
    35  	"time"
    36  
    37  	"github.com/ory/fosite" //"github.com/ory/fosite/internal"
    38  	"github.com/ory/fosite/storage"
    39  	"github.com/pkg/errors"
    40  	"github.com/stretchr/testify/assert"
    41  	"github.com/stretchr/testify/require"
    42  )
    43  
    44  func TestAuthorizeCode_PopulateTokenEndpointResponse(t *testing.T) {
    45  	for k, strategy := range map[string]CoreStrategy{
    46  		"hmac": &hmacshaStrategy,
    47  	} {
    48  		t.Run("strategy="+k, func(t *testing.T) {
    49  			store := storage.NewMemoryStore()
    50  
    51  			var h AuthorizeExplicitGrantHandler
    52  
    53  			for _, c := range []struct {
    54  				areq        *fosite.AccessRequest
    55  				description string
    56  				setup       func(t *testing.T, areq *fosite.AccessRequest)
    57  				check       func(t *testing.T, aresp *fosite.AccessResponse)
    58  				expectErr   error
    59  			}{
    60  				{
    61  					areq: &fosite.AccessRequest{
    62  						GrantTypes: fosite.Arguments{"123"},
    63  					},
    64  					description: "should fail because not responsible",
    65  					expectErr:   fosite.ErrUnknownRequest,
    66  				},
    67  				{
    68  					areq: &fosite.AccessRequest{
    69  						GrantTypes: fosite.Arguments{"authorization_code"},
    70  						Request: fosite.Request{
    71  							Form: url.Values{},
    72  							Client: &fosite.DefaultClient{
    73  								GrantTypes: fosite.Arguments{"authorization_code"},
    74  							},
    75  							Session:     &fosite.DefaultSession{},
    76  							RequestedAt: time.Now().UTC(),
    77  						},
    78  					},
    79  					description: "should fail because authcode not found",
    80  					setup: func(t *testing.T, areq *fosite.AccessRequest) {
    81  						code, _, err := strategy.GenerateAuthorizeCode(nil, nil)
    82  						require.NoError(t, err)
    83  						areq.Form.Set("code", code)
    84  					},
    85  					expectErr: fosite.ErrServerError,
    86  				},
    87  				{
    88  					areq: &fosite.AccessRequest{
    89  						GrantTypes: fosite.Arguments{"authorization_code"},
    90  						Request: fosite.Request{
    91  							Form: url.Values{"code": []string{"foo.bar"}},
    92  							Client: &fosite.DefaultClient{
    93  								GrantTypes: fosite.Arguments{"authorization_code"},
    94  							},
    95  							Session:     &fosite.DefaultSession{},
    96  							RequestedAt: time.Now().UTC(),
    97  						},
    98  					},
    99  					description: "should fail because validation failed",
   100  					setup: func(t *testing.T, areq *fosite.AccessRequest) {
   101  						require.NoError(t, store.CreateAuthorizeCodeSession(nil, "bar", areq))
   102  					},
   103  					expectErr: fosite.ErrInvalidRequest,
   104  				},
   105  				{
   106  					areq: &fosite.AccessRequest{
   107  						GrantTypes: fosite.Arguments{"authorization_code"},
   108  						Request: fosite.Request{
   109  							Form: url.Values{},
   110  							Client: &fosite.DefaultClient{
   111  								GrantTypes: fosite.Arguments{"authorization_code", "refresh_token"},
   112  							},
   113  							GrantedScope: fosite.Arguments{"foo", "offline"},
   114  							Session:      &fosite.DefaultSession{},
   115  							RequestedAt:  time.Now().UTC(),
   116  						},
   117  					},
   118  					setup: func(t *testing.T, areq *fosite.AccessRequest) {
   119  						code, sig, err := strategy.GenerateAuthorizeCode(nil, nil)
   120  						require.NoError(t, err)
   121  						areq.Form.Add("code", code)
   122  
   123  						require.NoError(t, store.CreateAuthorizeCodeSession(nil, sig, areq))
   124  					},
   125  					description: "should pass with offline scope and refresh token",
   126  					check: func(t *testing.T, aresp *fosite.AccessResponse) {
   127  						assert.NotEmpty(t, aresp.AccessToken)
   128  						assert.Equal(t, "bearer", aresp.TokenType)
   129  						assert.NotEmpty(t, aresp.GetExtra("refresh_token"))
   130  						assert.NotEmpty(t, aresp.GetExtra("expires_in"))
   131  						assert.Equal(t, "foo offline", aresp.GetExtra("scope"))
   132  					},
   133  				},
   134  				{
   135  					areq: &fosite.AccessRequest{
   136  						GrantTypes: fosite.Arguments{"authorization_code"},
   137  						Request: fosite.Request{
   138  							Form: url.Values{},
   139  							Client: &fosite.DefaultClient{
   140  								GrantTypes: fosite.Arguments{"authorization_code", "refresh_token"},
   141  							},
   142  							GrantedScope: fosite.Arguments{"foo"},
   143  							Session:      &fosite.DefaultSession{},
   144  							RequestedAt:  time.Now().UTC(),
   145  						},
   146  					},
   147  					setup: func(t *testing.T, areq *fosite.AccessRequest) {
   148  						h.RefreshTokenScopes = []string{}
   149  						code, sig, err := strategy.GenerateAuthorizeCode(nil, nil)
   150  						require.NoError(t, err)
   151  						areq.Form.Add("code", code)
   152  
   153  						require.NoError(t, store.CreateAuthorizeCodeSession(nil, sig, areq))
   154  					},
   155  					description: "should pass with refresh token always provided",
   156  					check: func(t *testing.T, aresp *fosite.AccessResponse) {
   157  						assert.NotEmpty(t, aresp.AccessToken)
   158  						assert.Equal(t, "bearer", aresp.TokenType)
   159  						assert.NotEmpty(t, aresp.GetExtra("refresh_token"))
   160  						assert.NotEmpty(t, aresp.GetExtra("expires_in"))
   161  						assert.Equal(t, "foo", aresp.GetExtra("scope"))
   162  					},
   163  				},
   164  				{
   165  					areq: &fosite.AccessRequest{
   166  						GrantTypes: fosite.Arguments{"authorization_code"},
   167  						Request: fosite.Request{
   168  							Form: url.Values{},
   169  							Client: &fosite.DefaultClient{
   170  								GrantTypes: fosite.Arguments{"authorization_code"},
   171  							},
   172  							GrantedScope: fosite.Arguments{},
   173  							Session:      &fosite.DefaultSession{},
   174  							RequestedAt:  time.Now().UTC(),
   175  						},
   176  					},
   177  					setup: func(t *testing.T, areq *fosite.AccessRequest) {
   178  						h.RefreshTokenScopes = []string{}
   179  						code, sig, err := strategy.GenerateAuthorizeCode(nil, nil)
   180  						require.NoError(t, err)
   181  						areq.Form.Add("code", code)
   182  
   183  						require.NoError(t, store.CreateAuthorizeCodeSession(nil, sig, areq))
   184  					},
   185  					description: "should pass with no refresh token",
   186  					check: func(t *testing.T, aresp *fosite.AccessResponse) {
   187  						assert.NotEmpty(t, aresp.AccessToken)
   188  						assert.Equal(t, "bearer", aresp.TokenType)
   189  						assert.Empty(t, aresp.GetExtra("refresh_token"))
   190  						assert.NotEmpty(t, aresp.GetExtra("expires_in"))
   191  						assert.Empty(t, aresp.GetExtra("scope"))
   192  					},
   193  				},
   194  				{
   195  					areq: &fosite.AccessRequest{
   196  						GrantTypes: fosite.Arguments{"authorization_code"},
   197  						Request: fosite.Request{
   198  							Form: url.Values{},
   199  							Client: &fosite.DefaultClient{
   200  								GrantTypes: fosite.Arguments{"authorization_code"},
   201  							},
   202  							GrantedScope: fosite.Arguments{"foo"},
   203  							Session:      &fosite.DefaultSession{},
   204  							RequestedAt:  time.Now().UTC(),
   205  						},
   206  					},
   207  					setup: func(t *testing.T, areq *fosite.AccessRequest) {
   208  						code, sig, err := strategy.GenerateAuthorizeCode(nil, nil)
   209  						require.NoError(t, err)
   210  						areq.Form.Add("code", code)
   211  
   212  						require.NoError(t, store.CreateAuthorizeCodeSession(nil, sig, areq))
   213  					},
   214  					description: "should not have refresh token",
   215  					check: func(t *testing.T, aresp *fosite.AccessResponse) {
   216  						assert.NotEmpty(t, aresp.AccessToken)
   217  						assert.Equal(t, "bearer", aresp.TokenType)
   218  						assert.Empty(t, aresp.GetExtra("refresh_token"))
   219  						assert.NotEmpty(t, aresp.GetExtra("expires_in"))
   220  						assert.Equal(t, "foo", aresp.GetExtra("scope"))
   221  					},
   222  				},
   223  			} {
   224  				t.Run("case="+c.description, func(t *testing.T) {
   225  					h = AuthorizeExplicitGrantHandler{
   226  						CoreStorage:              store,
   227  						AuthorizeCodeStrategy:    strategy,
   228  						AccessTokenStrategy:      strategy,
   229  						RefreshTokenStrategy:     strategy,
   230  						ScopeStrategy:            fosite.HierarchicScopeStrategy,
   231  						AudienceMatchingStrategy: fosite.DefaultAudienceMatchingStrategy,
   232  						AccessTokenLifespan:      time.Minute,
   233  						RefreshTokenScopes:       []string{"offline"},
   234  					}
   235  
   236  					if c.setup != nil {
   237  						c.setup(t, c.areq)
   238  					}
   239  
   240  					aresp := fosite.NewAccessResponse()
   241  					err := h.PopulateTokenEndpointResponse(nil, c.areq, aresp)
   242  
   243  					if c.expectErr != nil {
   244  						require.EqualError(t, err, c.expectErr.Error(), "%+v", err)
   245  					} else {
   246  						require.NoError(t, err, "%+v", err)
   247  					}
   248  
   249  					if c.check != nil {
   250  						c.check(t, aresp)
   251  					}
   252  				})
   253  			}
   254  		})
   255  	}
   256  }
   257  
   258  func TestAuthorizeCode_HandleTokenEndpointRequest(t *testing.T) {
   259  	for k, strategy := range map[string]CoreStrategy{
   260  		"hmac": &hmacshaStrategy,
   261  	} {
   262  		t.Run("strategy="+k, func(t *testing.T) {
   263  			store := storage.NewMemoryStore()
   264  
   265  			h := AuthorizeExplicitGrantHandler{
   266  				CoreStorage:              store,
   267  				AuthorizeCodeStrategy:    hmacshaStrategy,
   268  				ScopeStrategy:            fosite.HierarchicScopeStrategy,
   269  				AudienceMatchingStrategy: fosite.DefaultAudienceMatchingStrategy,
   270  				TokenRevocationStorage:   store,
   271  				AuthCodeLifespan:         time.Minute,
   272  			}
   273  			for i, c := range []struct {
   274  				areq        *fosite.AccessRequest
   275  				authreq     *fosite.AuthorizeRequest
   276  				description string
   277  				setup       func(t *testing.T, areq *fosite.AccessRequest, authreq *fosite.AuthorizeRequest)
   278  				check       func(t *testing.T, areq *fosite.AccessRequest, authreq *fosite.AuthorizeRequest)
   279  				expectErr   error
   280  			}{
   281  				{
   282  					areq: &fosite.AccessRequest{
   283  						GrantTypes: fosite.Arguments{"12345678"},
   284  					},
   285  					description: "should fail because not responsible",
   286  					expectErr:   fosite.ErrUnknownRequest,
   287  				},
   288  				{
   289  					areq: &fosite.AccessRequest{
   290  						GrantTypes: fosite.Arguments{"authorization_code"},
   291  						Request: fosite.Request{
   292  							Client:      &fosite.DefaultClient{ID: "foo", GrantTypes: []string{""}},
   293  							Session:     &fosite.DefaultSession{},
   294  							RequestedAt: time.Now().UTC(),
   295  						},
   296  					},
   297  					description: "should fail because client is not granted this grant type",
   298  					expectErr:   fosite.ErrUnauthorizedClient,
   299  				},
   300  				{
   301  					areq: &fosite.AccessRequest{
   302  						GrantTypes: fosite.Arguments{"authorization_code"},
   303  						Request: fosite.Request{
   304  							Client:      &fosite.DefaultClient{GrantTypes: []string{"authorization_code"}},
   305  							Session:     &fosite.DefaultSession{},
   306  							RequestedAt: time.Now().UTC(),
   307  						},
   308  					},
   309  					description: "should fail because authcode could not be retrieved (1)",
   310  					setup: func(t *testing.T, areq *fosite.AccessRequest, authreq *fosite.AuthorizeRequest) {
   311  						token, _, err := strategy.GenerateAuthorizeCode(nil, nil)
   312  						require.NoError(t, err)
   313  						areq.Form = url.Values{"code": {token}}
   314  					},
   315  					expectErr: fosite.ErrInvalidGrant,
   316  				},
   317  				{
   318  					areq: &fosite.AccessRequest{
   319  						GrantTypes: fosite.Arguments{"authorization_code"},
   320  						Request: fosite.Request{
   321  							Form:        url.Values{"code": {"foo.bar"}},
   322  							Client:      &fosite.DefaultClient{GrantTypes: []string{"authorization_code"}},
   323  							Session:     &fosite.DefaultSession{},
   324  							RequestedAt: time.Now().UTC(),
   325  						},
   326  					},
   327  					description: "should fail because authcode validation failed",
   328  					expectErr:   fosite.ErrInvalidGrant,
   329  				},
   330  				{
   331  					areq: &fosite.AccessRequest{
   332  						GrantTypes: fosite.Arguments{"authorization_code"},
   333  						Request: fosite.Request{
   334  							Client:      &fosite.DefaultClient{ID: "foo", GrantTypes: []string{"authorization_code"}},
   335  							Session:     &fosite.DefaultSession{},
   336  							RequestedAt: time.Now().UTC(),
   337  						},
   338  					},
   339  					authreq: &fosite.AuthorizeRequest{
   340  						Request: fosite.Request{
   341  							Client:         &fosite.DefaultClient{ID: "bar"},
   342  							RequestedScope: fosite.Arguments{"a", "b"},
   343  						},
   344  					},
   345  					description: "should fail because client mismatch",
   346  					setup: func(t *testing.T, areq *fosite.AccessRequest, authreq *fosite.AuthorizeRequest) {
   347  						token, signature, err := strategy.GenerateAuthorizeCode(nil, nil)
   348  						require.NoError(t, err)
   349  						areq.Form = url.Values{"code": {token}}
   350  
   351  						require.NoError(t, store.CreateAuthorizeCodeSession(nil, signature, authreq))
   352  					},
   353  					expectErr: fosite.ErrInvalidGrant,
   354  				},
   355  				{
   356  					areq: &fosite.AccessRequest{
   357  						GrantTypes: fosite.Arguments{"authorization_code"},
   358  						Request: fosite.Request{
   359  							Client:      &fosite.DefaultClient{ID: "foo", GrantTypes: []string{"authorization_code"}},
   360  							Session:     &fosite.DefaultSession{},
   361  							RequestedAt: time.Now().UTC(),
   362  						},
   363  					},
   364  					authreq: &fosite.AuthorizeRequest{
   365  						Request: fosite.Request{
   366  							Client:  &fosite.DefaultClient{ID: "foo", GrantTypes: []string{"authorization_code"}},
   367  							Form:    url.Values{"redirect_uri": []string{"request-redir"}},
   368  							Session: &fosite.DefaultSession{},
   369  						},
   370  					},
   371  					description: "should fail because redirect uri was set during /authorize call, but not in /token call",
   372  					setup: func(t *testing.T, areq *fosite.AccessRequest, authreq *fosite.AuthorizeRequest) {
   373  						token, signature, err := strategy.GenerateAuthorizeCode(nil, nil)
   374  						require.NoError(t, err)
   375  						areq.Form = url.Values{"code": {token}}
   376  
   377  						require.NoError(t, store.CreateAuthorizeCodeSession(nil, signature, authreq))
   378  					},
   379  					expectErr: fosite.ErrInvalidGrant,
   380  				},
   381  				{
   382  					areq: &fosite.AccessRequest{
   383  						GrantTypes: fosite.Arguments{"authorization_code"},
   384  						Request: fosite.Request{
   385  							Client:      &fosite.DefaultClient{ID: "foo", GrantTypes: []string{"authorization_code"}},
   386  							Form:        url.Values{"redirect_uri": []string{"request-redir"}},
   387  							Session:     &fosite.DefaultSession{},
   388  							RequestedAt: time.Now().UTC(),
   389  						},
   390  					},
   391  					authreq: &fosite.AuthorizeRequest{
   392  						Request: fosite.Request{
   393  							Client:         &fosite.DefaultClient{ID: "foo", GrantTypes: []string{"authorization_code"}},
   394  							Session:        &fosite.DefaultSession{},
   395  							RequestedScope: fosite.Arguments{"a", "b"},
   396  							RequestedAt:    time.Now().UTC(),
   397  						},
   398  					},
   399  					description: "should pass",
   400  					setup: func(t *testing.T, areq *fosite.AccessRequest, authreq *fosite.AuthorizeRequest) {
   401  						token, signature, err := strategy.GenerateAuthorizeCode(nil, nil)
   402  						require.NoError(t, err)
   403  
   404  						areq.Form = url.Values{"code": {token}}
   405  						require.NoError(t, store.CreateAuthorizeCodeSession(nil, signature, authreq))
   406  					},
   407  				},
   408  				{
   409  					areq: &fosite.AccessRequest{
   410  						GrantTypes: fosite.Arguments{"authorization_code"},
   411  						Request: fosite.Request{
   412  							Form: url.Values{},
   413  							Client: &fosite.DefaultClient{
   414  								GrantTypes: fosite.Arguments{"authorization_code"},
   415  							},
   416  							GrantedScope: fosite.Arguments{"foo", "offline"},
   417  							Session:      &fosite.DefaultSession{},
   418  							RequestedAt:  time.Now().UTC(),
   419  						},
   420  					},
   421  					check: func(t *testing.T, areq *fosite.AccessRequest, authreq *fosite.AuthorizeRequest) {
   422  						assert.Equal(t, time.Now().Add(time.Minute).UTC().Round(time.Second), areq.GetSession().GetExpiresAt(fosite.AccessToken))
   423  						assert.Equal(t, time.Now().Add(time.Minute).UTC().Round(time.Second), areq.GetSession().GetExpiresAt(fosite.RefreshToken))
   424  					},
   425  					setup: func(t *testing.T, areq *fosite.AccessRequest, authreq *fosite.AuthorizeRequest) {
   426  						code, sig, err := strategy.GenerateAuthorizeCode(nil, nil)
   427  						require.NoError(t, err)
   428  						areq.Form.Add("code", code)
   429  
   430  						require.NoError(t, store.CreateAuthorizeCodeSession(nil, sig, areq))
   431  						require.NoError(t, store.InvalidateAuthorizeCodeSession(nil, sig))
   432  					},
   433  					description: "should fail because code has been used already",
   434  					expectErr:   fosite.ErrInvalidGrant,
   435  				},
   436  			} {
   437  				t.Run(fmt.Sprintf("case=%d/description=%s", i, c.description), func(t *testing.T) {
   438  					if c.setup != nil {
   439  						c.setup(t, c.areq, c.authreq)
   440  					}
   441  
   442  					t.Logf("Processing %+v", c.areq.Client)
   443  
   444  					err := h.HandleTokenEndpointRequest(context.Background(), c.areq)
   445  					if c.expectErr != nil {
   446  						require.EqualError(t, err, c.expectErr.Error(), "%+v", err)
   447  					} else {
   448  						require.NoError(t, err, "%+v", err)
   449  						if c.check != nil {
   450  							c.check(t, c.areq, c.authreq)
   451  						}
   452  					}
   453  				})
   454  			}
   455  		})
   456  	}
   457  }
   458  
   459  func TestAuthorizeCodeTransactional_HandleTokenEndpointRequest(t *testing.T) {
   460  	var mockTransactional *internal.MockTransactional
   461  	var mockCoreStore *internal.MockCoreStorage
   462  	strategy := hmacshaStrategy
   463  	request := &fosite.AccessRequest{
   464  		GrantTypes: fosite.Arguments{"authorization_code"},
   465  		Request: fosite.Request{
   466  			Client: &fosite.DefaultClient{
   467  				GrantTypes: fosite.Arguments{"authorization_code", "refresh_token"},
   468  			},
   469  			GrantedScope: fosite.Arguments{"offline"},
   470  			Session:      &fosite.DefaultSession{},
   471  			RequestedAt:  time.Now().UTC(),
   472  		},
   473  	}
   474  	token, _, err := strategy.GenerateAuthorizeCode(nil, nil)
   475  	require.NoError(t, err)
   476  	request.Form = url.Values{"code": {token}}
   477  	response := fosite.NewAccessResponse()
   478  	propagatedContext := context.Background()
   479  
   480  	// some storage implementation that has support for transactions, notice the embedded type `storage.Transactional`
   481  	type transactionalStore struct {
   482  		storage.Transactional
   483  		CoreStorage
   484  	}
   485  
   486  	for _, testCase := range []struct {
   487  		description string
   488  		setup       func()
   489  		expectError error
   490  	}{
   491  		{
   492  			description: "transaction should be committed successfully if no errors occur",
   493  			setup: func() {
   494  				mockCoreStore.
   495  					EXPECT().
   496  					GetAuthorizeCodeSession(gomock.Any(), gomock.Any(), gomock.Any()).
   497  					Return(request, nil).
   498  					Times(1)
   499  				mockTransactional.
   500  					EXPECT().
   501  					BeginTX(propagatedContext).
   502  					Return(propagatedContext, nil)
   503  				mockCoreStore.
   504  					EXPECT().
   505  					InvalidateAuthorizeCodeSession(gomock.Any(), gomock.Any()).
   506  					Return(nil).
   507  					Times(1)
   508  				mockCoreStore.
   509  					EXPECT().
   510  					CreateAccessTokenSession(propagatedContext, gomock.Any(), gomock.Any()).
   511  					Return(nil).
   512  					Times(1)
   513  				mockCoreStore.
   514  					EXPECT().
   515  					CreateRefreshTokenSession(propagatedContext, gomock.Any(), gomock.Any()).
   516  					Return(nil).
   517  					Times(1)
   518  				mockTransactional.
   519  					EXPECT().
   520  					Commit(propagatedContext).
   521  					Return(nil).
   522  					Times(1)
   523  			},
   524  		},
   525  		{
   526  			description: "transaction should be rolled back if `InvalidateAuthorizeCodeSession` returns an error",
   527  			setup: func() {
   528  				mockCoreStore.
   529  					EXPECT().
   530  					GetAuthorizeCodeSession(gomock.Any(), gomock.Any(), gomock.Any()).
   531  					Return(request, nil).
   532  					Times(1)
   533  				mockTransactional.
   534  					EXPECT().
   535  					BeginTX(propagatedContext).
   536  					Return(propagatedContext, nil)
   537  				mockCoreStore.
   538  					EXPECT().
   539  					InvalidateAuthorizeCodeSession(gomock.Any(), gomock.Any()).
   540  					Return(errors.New("Whoops, a nasty database error occurred!")).
   541  					Times(1)
   542  				mockTransactional.
   543  					EXPECT().
   544  					Rollback(propagatedContext).
   545  					Return(nil).
   546  					Times(1)
   547  			},
   548  			expectError: fosite.ErrServerError,
   549  		},
   550  		{
   551  			description: "transaction should be rolled back if `CreateAccessTokenSession` returns an error",
   552  			setup: func() {
   553  				mockCoreStore.
   554  					EXPECT().
   555  					GetAuthorizeCodeSession(gomock.Any(), gomock.Any(), gomock.Any()).
   556  					Return(request, nil).
   557  					Times(1)
   558  				mockTransactional.
   559  					EXPECT().
   560  					BeginTX(propagatedContext).
   561  					Return(propagatedContext, nil)
   562  				mockCoreStore.
   563  					EXPECT().
   564  					InvalidateAuthorizeCodeSession(gomock.Any(), gomock.Any()).
   565  					Return(nil).
   566  					Times(1)
   567  				mockCoreStore.
   568  					EXPECT().
   569  					CreateAccessTokenSession(propagatedContext, gomock.Any(), gomock.Any()).
   570  					Return(errors.New("Whoops, a nasty database error occurred!")).
   571  					Times(1)
   572  				mockTransactional.
   573  					EXPECT().
   574  					Rollback(propagatedContext).
   575  					Return(nil).
   576  					Times(1)
   577  			},
   578  			expectError: fosite.ErrServerError,
   579  		},
   580  		{
   581  			description: "should result in a server error if transaction cannot be created",
   582  			setup: func() {
   583  				mockCoreStore.
   584  					EXPECT().
   585  					GetAuthorizeCodeSession(gomock.Any(), gomock.Any(), gomock.Any()).
   586  					Return(request, nil).
   587  					Times(1)
   588  				mockTransactional.
   589  					EXPECT().
   590  					BeginTX(propagatedContext).
   591  					Return(nil, errors.New("Whoops, unable to create transaction!"))
   592  			},
   593  			expectError: fosite.ErrServerError,
   594  		},
   595  		{
   596  			description: "should result in a server error if transaction cannot be rolled back",
   597  			setup: func() {
   598  				mockCoreStore.
   599  					EXPECT().
   600  					GetAuthorizeCodeSession(gomock.Any(), gomock.Any(), gomock.Any()).
   601  					Return(request, nil).
   602  					Times(1)
   603  				mockTransactional.
   604  					EXPECT().
   605  					BeginTX(propagatedContext).
   606  					Return(propagatedContext, nil)
   607  				mockCoreStore.
   608  					EXPECT().
   609  					InvalidateAuthorizeCodeSession(gomock.Any(), gomock.Any()).
   610  					Return(errors.New("Whoops, a nasty database error occurred!")).
   611  					Times(1)
   612  				mockTransactional.
   613  					EXPECT().
   614  					Rollback(propagatedContext).
   615  					Return(errors.New("Whoops, unable to rollback transaction!")).
   616  					Times(1)
   617  			},
   618  			expectError: fosite.ErrServerError,
   619  		},
   620  		{
   621  			description: "should result in a server error if transaction cannot be committed",
   622  			setup: func() {
   623  				mockCoreStore.
   624  					EXPECT().
   625  					GetAuthorizeCodeSession(gomock.Any(), gomock.Any(), gomock.Any()).
   626  					Return(request, nil).
   627  					Times(1)
   628  				mockTransactional.
   629  					EXPECT().
   630  					BeginTX(propagatedContext).
   631  					Return(propagatedContext, nil)
   632  				mockCoreStore.
   633  					EXPECT().
   634  					InvalidateAuthorizeCodeSession(gomock.Any(), gomock.Any()).
   635  					Return(nil).
   636  					Times(1)
   637  				mockCoreStore.
   638  					EXPECT().
   639  					CreateAccessTokenSession(propagatedContext, gomock.Any(), gomock.Any()).
   640  					Return(nil).
   641  					Times(1)
   642  				mockCoreStore.
   643  					EXPECT().
   644  					CreateRefreshTokenSession(propagatedContext, gomock.Any(), gomock.Any()).
   645  					Return(nil).
   646  					Times(1)
   647  				mockTransactional.
   648  					EXPECT().
   649  					Commit(propagatedContext).
   650  					Return(errors.New("Whoops, unable to commit transaction!")).
   651  					Times(1)
   652  				mockTransactional.
   653  					EXPECT().
   654  					Rollback(propagatedContext).
   655  					Return(nil).
   656  					Times(1)
   657  			},
   658  			expectError: fosite.ErrServerError,
   659  		},
   660  	} {
   661  		t.Run(fmt.Sprintf("scenario=%s", testCase.description), func(t *testing.T) {
   662  			ctrl := gomock.NewController(t)
   663  			defer ctrl.Finish()
   664  
   665  			mockTransactional = internal.NewMockTransactional(ctrl)
   666  			mockCoreStore = internal.NewMockCoreStorage(ctrl)
   667  			testCase.setup()
   668  
   669  			handler := AuthorizeExplicitGrantHandler{
   670  				CoreStorage: transactionalStore{
   671  					mockTransactional,
   672  					mockCoreStore,
   673  				},
   674  				AccessTokenStrategy:      strategy,
   675  				RefreshTokenStrategy:     strategy,
   676  				AuthorizeCodeStrategy:    strategy,
   677  				ScopeStrategy:            fosite.HierarchicScopeStrategy,
   678  				AudienceMatchingStrategy: fosite.DefaultAudienceMatchingStrategy,
   679  				AuthCodeLifespan:         time.Minute,
   680  			}
   681  
   682  			if err := handler.PopulateTokenEndpointResponse(propagatedContext, request, response); testCase.expectError != nil {
   683  				assert.EqualError(t, err, testCase.expectError.Error())
   684  			}
   685  		})
   686  	}
   687  }
   688  

View as plain text