...

Source file src/github.com/ory/fosite/authorize_request_handler_test.go

Documentation: github.com/ory/fosite

     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 fosite_test
    23  
    24  import (
    25  	"context"
    26  	"fmt"
    27  	"net/http"
    28  	"net/url"
    29  	"testing"
    30  
    31  	"github.com/golang/mock/gomock"
    32  	"github.com/pkg/errors"
    33  	"github.com/stretchr/testify/assert"
    34  	"github.com/stretchr/testify/require"
    35  
    36  	. "github.com/ory/fosite"
    37  	. "github.com/ory/fosite/internal"
    38  )
    39  
    40  // Should pass
    41  //
    42  // * https://openid.net/specs/oauth-v2-multiple-response-types-1_0.html#Terminology
    43  //   The OAuth 2.0 specification allows for registration of space-separated response_type parameter values.
    44  //   If a Response Type contains one of more space characters (%20), it is compared as a space-delimited list of
    45  //   values in which the order of values does not matter.
    46  func TestNewAuthorizeRequest(t *testing.T) {
    47  	var store *MockStorage
    48  
    49  	redir, _ := url.Parse("https://foo.bar/cb")
    50  	specialCharRedir, _ := url.Parse("web+application://callback")
    51  	for k, c := range []struct {
    52  		desc          string
    53  		conf          *Fosite
    54  		r             *http.Request
    55  		query         url.Values
    56  		expectedError error
    57  		mock          func()
    58  		expect        *AuthorizeRequest
    59  	}{
    60  		/* empty request */
    61  		{
    62  			desc:          "empty request fails",
    63  			conf:          &Fosite{Store: store, ScopeStrategy: ExactScopeStrategy, AudienceMatchingStrategy: DefaultAudienceMatchingStrategy},
    64  			r:             &http.Request{},
    65  			expectedError: ErrInvalidClient,
    66  			mock: func() {
    67  				store.EXPECT().GetClient(gomock.Any(), gomock.Any()).Return(nil, errors.New("foo"))
    68  			},
    69  		},
    70  		/* invalid redirect uri */
    71  		{
    72  			desc:          "invalid redirect uri fails",
    73  			conf:          &Fosite{Store: store, ScopeStrategy: ExactScopeStrategy, AudienceMatchingStrategy: DefaultAudienceMatchingStrategy},
    74  			query:         url.Values{"redirect_uri": []string{"invalid"}},
    75  			expectedError: ErrInvalidClient,
    76  			mock: func() {
    77  				store.EXPECT().GetClient(gomock.Any(), gomock.Any()).Return(nil, errors.New("foo"))
    78  			},
    79  		},
    80  		/* invalid client */
    81  		{
    82  			desc:          "invalid client fails",
    83  			conf:          &Fosite{Store: store, ScopeStrategy: ExactScopeStrategy, AudienceMatchingStrategy: DefaultAudienceMatchingStrategy},
    84  			query:         url.Values{"redirect_uri": []string{"https://foo.bar/cb"}},
    85  			expectedError: ErrInvalidClient,
    86  			mock: func() {
    87  				store.EXPECT().GetClient(gomock.Any(), gomock.Any()).Return(nil, errors.New("foo"))
    88  			},
    89  		},
    90  		/* redirect client mismatch */
    91  		{
    92  			desc: "client and request redirects mismatch",
    93  			conf: &Fosite{Store: store, ScopeStrategy: ExactScopeStrategy, AudienceMatchingStrategy: DefaultAudienceMatchingStrategy},
    94  			query: url.Values{
    95  				"client_id": []string{"1234"},
    96  			},
    97  			expectedError: ErrInvalidRequest,
    98  			mock: func() {
    99  				store.EXPECT().GetClient(gomock.Any(), "1234").Return(&DefaultClient{RedirectURIs: []string{"invalid"}, Scopes: []string{}}, nil)
   100  			},
   101  		},
   102  		/* redirect client mismatch */
   103  		{
   104  			desc: "client and request redirects mismatch",
   105  			conf: &Fosite{Store: store, ScopeStrategy: ExactScopeStrategy, AudienceMatchingStrategy: DefaultAudienceMatchingStrategy},
   106  			query: url.Values{
   107  				"redirect_uri": []string{""},
   108  				"client_id":    []string{"1234"},
   109  			},
   110  			expectedError: ErrInvalidRequest,
   111  			mock: func() {
   112  				store.EXPECT().GetClient(gomock.Any(), "1234").Return(&DefaultClient{RedirectURIs: []string{"invalid"}, Scopes: []string{}}, nil)
   113  			},
   114  		},
   115  		/* redirect client mismatch */
   116  		{
   117  			desc: "client and request redirects mismatch",
   118  			conf: &Fosite{Store: store, ScopeStrategy: ExactScopeStrategy, AudienceMatchingStrategy: DefaultAudienceMatchingStrategy},
   119  			query: url.Values{
   120  				"redirect_uri": []string{"https://foo.bar/cb"},
   121  				"client_id":    []string{"1234"},
   122  			},
   123  			expectedError: ErrInvalidRequest,
   124  			mock: func() {
   125  				store.EXPECT().GetClient(gomock.Any(), "1234").Return(&DefaultClient{RedirectURIs: []string{"invalid"}, Scopes: []string{}}, nil)
   126  			},
   127  		},
   128  		/* no state */
   129  		{
   130  			desc: "no state",
   131  			conf: &Fosite{Store: store, ScopeStrategy: ExactScopeStrategy, AudienceMatchingStrategy: DefaultAudienceMatchingStrategy},
   132  			query: url.Values{
   133  				"redirect_uri":  []string{"https://foo.bar/cb"},
   134  				"client_id":     []string{"1234"},
   135  				"response_type": []string{"code"},
   136  			},
   137  			expectedError: ErrInvalidState,
   138  			mock: func() {
   139  				store.EXPECT().GetClient(gomock.Any(), "1234").Return(&DefaultClient{RedirectURIs: []string{"https://foo.bar/cb"}, Scopes: []string{}}, nil)
   140  			},
   141  		},
   142  		/* short state */
   143  		{
   144  			desc: "short state",
   145  			conf: &Fosite{Store: store, ScopeStrategy: ExactScopeStrategy, AudienceMatchingStrategy: DefaultAudienceMatchingStrategy},
   146  			query: url.Values{
   147  				"redirect_uri":  {"https://foo.bar/cb"},
   148  				"client_id":     {"1234"},
   149  				"response_type": {"code"},
   150  				"state":         {"short"},
   151  			},
   152  			expectedError: ErrInvalidState,
   153  			mock: func() {
   154  				store.EXPECT().GetClient(gomock.Any(), "1234").Return(&DefaultClient{RedirectURIs: []string{"https://foo.bar/cb"}, Scopes: []string{}}, nil)
   155  			},
   156  		},
   157  		/* fails because scope not given */
   158  		{
   159  			desc: "should fail because client does not have scope baz",
   160  			conf: &Fosite{Store: store, ScopeStrategy: ExactScopeStrategy, AudienceMatchingStrategy: DefaultAudienceMatchingStrategy},
   161  			query: url.Values{
   162  				"redirect_uri":  {"https://foo.bar/cb"},
   163  				"client_id":     {"1234"},
   164  				"response_type": {"code token"},
   165  				"state":         {"strong-state"},
   166  				"scope":         {"foo bar baz"},
   167  			},
   168  			mock: func() {
   169  				store.EXPECT().GetClient(gomock.Any(), "1234").Return(&DefaultClient{RedirectURIs: []string{"https://foo.bar/cb"}, Scopes: []string{"foo", "bar"}}, nil)
   170  			},
   171  			expectedError: ErrInvalidScope,
   172  		},
   173  		/* fails because scope not given */
   174  		{
   175  			desc: "should fail because client does not have scope baz",
   176  			conf: &Fosite{Store: store, ScopeStrategy: ExactScopeStrategy, AudienceMatchingStrategy: DefaultAudienceMatchingStrategy},
   177  			query: url.Values{
   178  				"redirect_uri":  {"https://foo.bar/cb"},
   179  				"client_id":     {"1234"},
   180  				"response_type": {"code token"},
   181  				"state":         {"strong-state"},
   182  				"scope":         {"foo bar"},
   183  				"audience":      {"https://cloud.ory.sh/api https://www.ory.sh/api"},
   184  			},
   185  			mock: func() {
   186  				store.EXPECT().GetClient(gomock.Any(), "1234").Return(&DefaultClient{
   187  					RedirectURIs: []string{"https://foo.bar/cb"}, Scopes: []string{"foo", "bar"},
   188  					Audience: []string{"https://cloud.ory.sh/api"},
   189  				}, nil)
   190  			},
   191  			expectedError: ErrInvalidRequest,
   192  		},
   193  		/* success case */
   194  		{
   195  			desc: "should pass",
   196  			conf: &Fosite{Store: store, ScopeStrategy: ExactScopeStrategy, AudienceMatchingStrategy: DefaultAudienceMatchingStrategy},
   197  			query: url.Values{
   198  				"redirect_uri":  {"https://foo.bar/cb"},
   199  				"client_id":     {"1234"},
   200  				"response_type": {"code token"},
   201  				"state":         {"strong-state"},
   202  				"scope":         {"foo bar"},
   203  				"audience":      {"https://cloud.ory.sh/api https://www.ory.sh/api"},
   204  			},
   205  			mock: func() {
   206  				store.EXPECT().GetClient(gomock.Any(), "1234").Return(&DefaultClient{
   207  					ResponseTypes: []string{"code token"},
   208  					RedirectURIs:  []string{"https://foo.bar/cb"},
   209  					Scopes:        []string{"foo", "bar"},
   210  					Audience:      []string{"https://cloud.ory.sh/api", "https://www.ory.sh/api"},
   211  				}, nil)
   212  			},
   213  			expect: &AuthorizeRequest{
   214  				RedirectURI:   redir,
   215  				ResponseTypes: []string{"code", "token"},
   216  				State:         "strong-state",
   217  				Request: Request{
   218  					Client: &DefaultClient{
   219  						ResponseTypes: []string{"code token"}, RedirectURIs: []string{"https://foo.bar/cb"},
   220  						Scopes:   []string{"foo", "bar"},
   221  						Audience: []string{"https://cloud.ory.sh/api", "https://www.ory.sh/api"},
   222  					},
   223  					RequestedScope:    []string{"foo", "bar"},
   224  					RequestedAudience: []string{"https://cloud.ory.sh/api", "https://www.ory.sh/api"},
   225  				},
   226  			},
   227  		},
   228  		/* repeated audience parameter */
   229  		{
   230  			desc: "repeated audience parameter",
   231  			conf: &Fosite{Store: store, ScopeStrategy: ExactScopeStrategy, AudienceMatchingStrategy: DefaultAudienceMatchingStrategy},
   232  			query: url.Values{
   233  				"redirect_uri":  {"https://foo.bar/cb"},
   234  				"client_id":     {"1234"},
   235  				"response_type": {"code token"},
   236  				"state":         {"strong-state"},
   237  				"scope":         {"foo bar"},
   238  				"audience":      {"https://cloud.ory.sh/api", "https://www.ory.sh/api"},
   239  			},
   240  			mock: func() {
   241  				store.EXPECT().GetClient(gomock.Any(), "1234").Return(&DefaultClient{
   242  					ResponseTypes: []string{"code token"},
   243  					RedirectURIs:  []string{"https://foo.bar/cb"},
   244  					Scopes:        []string{"foo", "bar"},
   245  					Audience:      []string{"https://cloud.ory.sh/api", "https://www.ory.sh/api"},
   246  				}, nil)
   247  			},
   248  			expect: &AuthorizeRequest{
   249  				RedirectURI:   redir,
   250  				ResponseTypes: []string{"code", "token"},
   251  				State:         "strong-state",
   252  				Request: Request{
   253  					Client: &DefaultClient{
   254  						ResponseTypes: []string{"code token"}, RedirectURIs: []string{"https://foo.bar/cb"},
   255  						Scopes:   []string{"foo", "bar"},
   256  						Audience: []string{"https://cloud.ory.sh/api", "https://www.ory.sh/api"},
   257  					},
   258  					RequestedScope:    []string{"foo", "bar"},
   259  					RequestedAudience: []string{"https://cloud.ory.sh/api", "https://www.ory.sh/api"},
   260  				},
   261  			},
   262  		},
   263  		/* repeated audience parameter with tricky values */
   264  		{
   265  			desc: "repeated audience parameter with tricky values",
   266  			conf: &Fosite{Store: store, ScopeStrategy: ExactScopeStrategy, AudienceMatchingStrategy: ExactAudienceMatchingStrategy},
   267  			query: url.Values{
   268  				"redirect_uri":  {"https://foo.bar/cb"},
   269  				"client_id":     {"1234"},
   270  				"response_type": {"code token"},
   271  				"state":         {"strong-state"},
   272  				"scope":         {"foo bar"},
   273  				"audience":      {"test value", ""},
   274  			},
   275  			mock: func() {
   276  				store.EXPECT().GetClient(gomock.Any(), "1234").Return(&DefaultClient{
   277  					ResponseTypes: []string{"code token"},
   278  					RedirectURIs:  []string{"https://foo.bar/cb"},
   279  					Scopes:        []string{"foo", "bar"},
   280  					Audience:      []string{"test value"},
   281  				}, nil)
   282  			},
   283  			expect: &AuthorizeRequest{
   284  				RedirectURI:   redir,
   285  				ResponseTypes: []string{"code", "token"},
   286  				State:         "strong-state",
   287  				Request: Request{
   288  					Client: &DefaultClient{
   289  						ResponseTypes: []string{"code token"}, RedirectURIs: []string{"https://foo.bar/cb"},
   290  						Scopes:   []string{"foo", "bar"},
   291  						Audience: []string{"test value"},
   292  					},
   293  					RequestedScope:    []string{"foo", "bar"},
   294  					RequestedAudience: []string{"test value"},
   295  				},
   296  			},
   297  		},
   298  		/* redirect_uri with special character in protocol*/
   299  		{
   300  			desc: "redirect_uri with special character",
   301  			conf: &Fosite{Store: store, ScopeStrategy: ExactScopeStrategy, AudienceMatchingStrategy: DefaultAudienceMatchingStrategy},
   302  			query: url.Values{
   303  				"redirect_uri":  {"web+application://callback"},
   304  				"client_id":     {"1234"},
   305  				"response_type": {"code token"},
   306  				"state":         {"strong-state"},
   307  				"scope":         {"foo bar"},
   308  				"audience":      {"https://cloud.ory.sh/api https://www.ory.sh/api"},
   309  			},
   310  			mock: func() {
   311  				store.EXPECT().GetClient(gomock.Any(), "1234").Return(&DefaultClient{
   312  					ResponseTypes: []string{"code token"},
   313  					RedirectURIs:  []string{"web+application://callback"},
   314  					Scopes:        []string{"foo", "bar"},
   315  					Audience:      []string{"https://cloud.ory.sh/api", "https://www.ory.sh/api"},
   316  				}, nil)
   317  			},
   318  			expect: &AuthorizeRequest{
   319  				RedirectURI:   specialCharRedir,
   320  				ResponseTypes: []string{"code", "token"},
   321  				State:         "strong-state",
   322  				Request: Request{
   323  					Client: &DefaultClient{
   324  						ResponseTypes: []string{"code token"}, RedirectURIs: []string{"web+application://callback"},
   325  						Scopes:   []string{"foo", "bar"},
   326  						Audience: []string{"https://cloud.ory.sh/api", "https://www.ory.sh/api"},
   327  					},
   328  					RequestedScope:    []string{"foo", "bar"},
   329  					RequestedAudience: []string{"https://cloud.ory.sh/api", "https://www.ory.sh/api"},
   330  				},
   331  			},
   332  		},
   333  		/* audience with double spaces between values */
   334  		{
   335  			desc: "audience with double spaces between values",
   336  			conf: &Fosite{Store: store, ScopeStrategy: ExactScopeStrategy, AudienceMatchingStrategy: DefaultAudienceMatchingStrategy},
   337  			query: url.Values{
   338  				"redirect_uri":  {"https://foo.bar/cb"},
   339  				"client_id":     {"1234"},
   340  				"response_type": {"code token"},
   341  				"state":         {"strong-state"},
   342  				"scope":         {"foo bar"},
   343  				"audience":      {"https://cloud.ory.sh/api  https://www.ory.sh/api"},
   344  			},
   345  			mock: func() {
   346  				store.EXPECT().GetClient(gomock.Any(), "1234").Return(&DefaultClient{
   347  					ResponseTypes: []string{"code token"},
   348  					RedirectURIs:  []string{"https://foo.bar/cb"},
   349  					Scopes:        []string{"foo", "bar"},
   350  					Audience:      []string{"https://cloud.ory.sh/api", "https://www.ory.sh/api"},
   351  				}, nil)
   352  			},
   353  			expect: &AuthorizeRequest{
   354  				RedirectURI:   redir,
   355  				ResponseTypes: []string{"code", "token"},
   356  				State:         "strong-state",
   357  				Request: Request{
   358  					Client: &DefaultClient{
   359  						ResponseTypes: []string{"code token"}, RedirectURIs: []string{"https://foo.bar/cb"},
   360  						Scopes:   []string{"foo", "bar"},
   361  						Audience: []string{"https://cloud.ory.sh/api", "https://www.ory.sh/api"},
   362  					},
   363  					RequestedScope:    []string{"foo", "bar"},
   364  					RequestedAudience: []string{"https://cloud.ory.sh/api", "https://www.ory.sh/api"},
   365  				},
   366  			},
   367  		},
   368  		/* fails because unknown response_mode*/
   369  		{
   370  			desc: "should fail because unknown response_mode",
   371  			conf: &Fosite{Store: store, ScopeStrategy: ExactScopeStrategy, AudienceMatchingStrategy: DefaultAudienceMatchingStrategy},
   372  			query: url.Values{
   373  				"redirect_uri":  {"https://foo.bar/cb"},
   374  				"client_id":     {"1234"},
   375  				"response_type": {"code token"},
   376  				"state":         {"strong-state"},
   377  				"scope":         {"foo bar"},
   378  				"response_mode": {"unknown"},
   379  			},
   380  			mock: func() {
   381  				store.EXPECT().GetClient(gomock.Any(), "1234").Return(&DefaultClient{RedirectURIs: []string{"https://foo.bar/cb"}, Scopes: []string{"foo", "bar"}, ResponseTypes: []string{"code token"}}, nil)
   382  			},
   383  			expectedError: ErrUnsupportedResponseMode,
   384  		},
   385  		/* fails because response_mode is requested but the OAuth 2.0 client doesn't support response mode */
   386  		{
   387  			desc: "should fail because response_mode is requested but the OAuth 2.0 client doesn't support response mode",
   388  			conf: &Fosite{Store: store, ScopeStrategy: ExactScopeStrategy, AudienceMatchingStrategy: DefaultAudienceMatchingStrategy},
   389  			query: url.Values{
   390  				"redirect_uri":  {"https://foo.bar/cb"},
   391  				"client_id":     {"1234"},
   392  				"response_type": {"code token"},
   393  				"state":         {"strong-state"},
   394  				"scope":         {"foo bar"},
   395  				"response_mode": {"form_post"},
   396  			},
   397  			mock: func() {
   398  				store.EXPECT().GetClient(gomock.Any(), "1234").Return(&DefaultClient{RedirectURIs: []string{"https://foo.bar/cb"}, Scopes: []string{"foo", "bar"}, ResponseTypes: []string{"code token"}}, nil)
   399  			},
   400  			expectedError: ErrUnsupportedResponseMode,
   401  		},
   402  		/* fails because requested response mode is not allowed */
   403  		{
   404  			desc: "should fail because requested response mode is not allowed",
   405  			conf: &Fosite{Store: store, ScopeStrategy: ExactScopeStrategy, AudienceMatchingStrategy: DefaultAudienceMatchingStrategy},
   406  			query: url.Values{
   407  				"redirect_uri":  {"https://foo.bar/cb"},
   408  				"client_id":     {"1234"},
   409  				"response_type": {"code token"},
   410  				"state":         {"strong-state"},
   411  				"scope":         {"foo bar"},
   412  				"response_mode": {"form_post"},
   413  			},
   414  			mock: func() {
   415  				store.EXPECT().GetClient(gomock.Any(), "1234").Return(&DefaultResponseModeClient{
   416  					DefaultClient: &DefaultClient{
   417  						RedirectURIs:  []string{"https://foo.bar/cb"},
   418  						Scopes:        []string{"foo", "bar"},
   419  						ResponseTypes: []string{"code token"},
   420  					},
   421  					ResponseModes: []ResponseModeType{ResponseModeQuery},
   422  				}, nil)
   423  			},
   424  			expectedError: ErrUnsupportedResponseMode,
   425  		},
   426  		/* success with response mode */
   427  		{
   428  			desc: "success with response mode",
   429  			conf: &Fosite{Store: store, ScopeStrategy: ExactScopeStrategy, AudienceMatchingStrategy: DefaultAudienceMatchingStrategy},
   430  			query: url.Values{
   431  				"redirect_uri":  {"https://foo.bar/cb"},
   432  				"client_id":     {"1234"},
   433  				"response_type": {"code token"},
   434  				"state":         {"strong-state"},
   435  				"scope":         {"foo bar"},
   436  				"response_mode": {"form_post"},
   437  				"audience":      {"https://cloud.ory.sh/api https://www.ory.sh/api"},
   438  			},
   439  			mock: func() {
   440  				store.EXPECT().GetClient(gomock.Any(), "1234").Return(&DefaultResponseModeClient{
   441  					DefaultClient: &DefaultClient{
   442  						RedirectURIs:  []string{"https://foo.bar/cb"},
   443  						Scopes:        []string{"foo", "bar"},
   444  						ResponseTypes: []string{"code token"},
   445  						Audience:      []string{"https://cloud.ory.sh/api", "https://www.ory.sh/api"},
   446  					},
   447  					ResponseModes: []ResponseModeType{ResponseModeFormPost},
   448  				}, nil)
   449  			},
   450  			expect: &AuthorizeRequest{
   451  				RedirectURI:   redir,
   452  				ResponseTypes: []string{"code", "token"},
   453  				State:         "strong-state",
   454  				Request: Request{
   455  					Client: &DefaultResponseModeClient{
   456  						DefaultClient: &DefaultClient{
   457  							RedirectURIs:  []string{"https://foo.bar/cb"},
   458  							Scopes:        []string{"foo", "bar"},
   459  							ResponseTypes: []string{"code token"},
   460  							Audience:      []string{"https://cloud.ory.sh/api", "https://www.ory.sh/api"},
   461  						},
   462  						ResponseModes: []ResponseModeType{ResponseModeFormPost},
   463  					},
   464  					RequestedScope:    []string{"foo", "bar"},
   465  					RequestedAudience: []string{"https://cloud.ory.sh/api", "https://www.ory.sh/api"},
   466  				},
   467  			},
   468  		},
   469  		/* determine correct response mode if default */
   470  		{
   471  			desc: "success with response mode",
   472  			conf: &Fosite{Store: store, ScopeStrategy: ExactScopeStrategy, AudienceMatchingStrategy: DefaultAudienceMatchingStrategy},
   473  			query: url.Values{
   474  				"redirect_uri":  {"https://foo.bar/cb"},
   475  				"client_id":     {"1234"},
   476  				"response_type": {"code"},
   477  				"state":         {"strong-state"},
   478  				"scope":         {"foo bar"},
   479  				"audience":      {"https://cloud.ory.sh/api https://www.ory.sh/api"},
   480  			},
   481  			mock: func() {
   482  				store.EXPECT().GetClient(gomock.Any(), "1234").Return(&DefaultResponseModeClient{
   483  					DefaultClient: &DefaultClient{
   484  						RedirectURIs:  []string{"https://foo.bar/cb"},
   485  						Scopes:        []string{"foo", "bar"},
   486  						ResponseTypes: []string{"code"},
   487  						Audience:      []string{"https://cloud.ory.sh/api", "https://www.ory.sh/api"},
   488  					},
   489  					ResponseModes: []ResponseModeType{ResponseModeQuery},
   490  				}, nil)
   491  			},
   492  			expect: &AuthorizeRequest{
   493  				RedirectURI:   redir,
   494  				ResponseTypes: []string{"code"},
   495  				State:         "strong-state",
   496  				Request: Request{
   497  					Client: &DefaultResponseModeClient{
   498  						DefaultClient: &DefaultClient{
   499  							RedirectURIs:  []string{"https://foo.bar/cb"},
   500  							Scopes:        []string{"foo", "bar"},
   501  							ResponseTypes: []string{"code"},
   502  							Audience:      []string{"https://cloud.ory.sh/api", "https://www.ory.sh/api"},
   503  						},
   504  						ResponseModes: []ResponseModeType{ResponseModeQuery},
   505  					},
   506  					RequestedScope:    []string{"foo", "bar"},
   507  					RequestedAudience: []string{"https://cloud.ory.sh/api", "https://www.ory.sh/api"},
   508  				},
   509  			},
   510  		},
   511  		/* determine correct response mode if default */
   512  		{
   513  			desc: "success with response mode",
   514  			conf: &Fosite{Store: store, ScopeStrategy: ExactScopeStrategy, AudienceMatchingStrategy: DefaultAudienceMatchingStrategy},
   515  			query: url.Values{
   516  				"redirect_uri":  {"https://foo.bar/cb"},
   517  				"client_id":     {"1234"},
   518  				"response_type": {"code token"},
   519  				"state":         {"strong-state"},
   520  				"scope":         {"foo bar"},
   521  				"audience":      {"https://cloud.ory.sh/api https://www.ory.sh/api"},
   522  			},
   523  			mock: func() {
   524  				store.EXPECT().GetClient(gomock.Any(), "1234").Return(&DefaultResponseModeClient{
   525  					DefaultClient: &DefaultClient{
   526  						RedirectURIs:  []string{"https://foo.bar/cb"},
   527  						Scopes:        []string{"foo", "bar"},
   528  						ResponseTypes: []string{"code token"},
   529  						Audience:      []string{"https://cloud.ory.sh/api", "https://www.ory.sh/api"},
   530  					},
   531  					ResponseModes: []ResponseModeType{ResponseModeFragment},
   532  				}, nil)
   533  			},
   534  			expect: &AuthorizeRequest{
   535  				RedirectURI:   redir,
   536  				ResponseTypes: []string{"code", "token"},
   537  				State:         "strong-state",
   538  				Request: Request{
   539  					Client: &DefaultResponseModeClient{
   540  						DefaultClient: &DefaultClient{
   541  							RedirectURIs:  []string{"https://foo.bar/cb"},
   542  							Scopes:        []string{"foo", "bar"},
   543  							ResponseTypes: []string{"code token"},
   544  							Audience:      []string{"https://cloud.ory.sh/api", "https://www.ory.sh/api"},
   545  						},
   546  						ResponseModes: []ResponseModeType{ResponseModeFragment},
   547  					},
   548  					RequestedScope:    []string{"foo", "bar"},
   549  					RequestedAudience: []string{"https://cloud.ory.sh/api", "https://www.ory.sh/api"},
   550  				},
   551  			},
   552  		},
   553  	} {
   554  		t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) {
   555  			ctrl := gomock.NewController(t)
   556  			store = NewMockStorage(ctrl)
   557  			defer ctrl.Finish()
   558  
   559  			c.mock()
   560  			if c.r == nil {
   561  				c.r = &http.Request{Header: http.Header{}}
   562  				if c.query != nil {
   563  					c.r.URL = &url.URL{RawQuery: c.query.Encode()}
   564  				}
   565  			}
   566  
   567  			c.conf.Store = store
   568  			ar, err := c.conf.NewAuthorizeRequest(context.Background(), c.r)
   569  			if c.expectedError != nil {
   570  				assert.EqualError(t, err, c.expectedError.Error())
   571  				// https://github.com/ory/hydra/issues/1642
   572  				AssertObjectKeysEqual(t, &AuthorizeRequest{State: c.query.Get("state")}, ar, "State")
   573  			} else {
   574  				require.NoError(t, err)
   575  				AssertObjectKeysEqual(t, c.expect, ar, "ResponseTypes", "RequestedAudience", "RequestedScope", "Client", "RedirectURI", "State")
   576  				assert.NotNil(t, ar.GetRequestedAt())
   577  			}
   578  		})
   579  	}
   580  }
   581  

View as plain text