...

Source file src/github.com/ory/fosite/handler/openid/validator_test.go

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

     1  /*
     2   * Copyright © 2017-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 	2017-2018 Aeneas Rekkas <aeneas+oss@aeneas.io>
    18   * @license 	Apache-2.0
    19   *
    20   */
    21  
    22  package openid
    23  
    24  import (
    25  	"context"
    26  	"fmt"
    27  	"net/url"
    28  	"testing"
    29  	"time"
    30  
    31  	"github.com/stretchr/testify/assert"
    32  	"github.com/stretchr/testify/require"
    33  
    34  	"github.com/ory/fosite"
    35  	"github.com/ory/fosite/token/jwt"
    36  )
    37  
    38  func TestValidatePrompt(t *testing.T) {
    39  	var j = &DefaultStrategy{
    40  		JWTStrategy: &jwt.RS256JWTStrategy{
    41  			PrivateKey: key,
    42  		},
    43  		MinParameterEntropy: fosite.MinParameterEntropy,
    44  	}
    45  
    46  	v := NewOpenIDConnectRequestValidator(nil, j)
    47  
    48  	var genIDToken = func(c jwt.IDTokenClaims) string {
    49  		s, _, err := j.Generate(context.TODO(), c.ToMapClaims(), jwt.NewHeaders())
    50  		require.NoError(t, err)
    51  		return s
    52  	}
    53  
    54  	for k, tc := range []struct {
    55  		d           string
    56  		prompt      string
    57  		redirectURL string
    58  		isPublic    bool
    59  		expectErr   bool
    60  		idTokenHint string
    61  		s           *DefaultSession
    62  	}{
    63  		{
    64  			d:           "should fail because prompt=none should not work together with public clients and http non-localhost",
    65  			prompt:      "none",
    66  			isPublic:    true,
    67  			expectErr:   true,
    68  			redirectURL: "http://foo-bar/",
    69  			s: &DefaultSession{
    70  				Subject: "foo",
    71  				Claims: &jwt.IDTokenClaims{
    72  					Subject:     "foo",
    73  					RequestedAt: time.Now().UTC(),
    74  					AuthTime:    time.Now().UTC().Add(-time.Minute),
    75  				},
    76  			},
    77  		},
    78  		{
    79  			d:           "should pass because prompt=none works for public clients and http localhost",
    80  			prompt:      "none",
    81  			isPublic:    true,
    82  			expectErr:   false,
    83  			redirectURL: "http://localhost/",
    84  			s: &DefaultSession{
    85  				Subject: "foo",
    86  				Claims: &jwt.IDTokenClaims{
    87  					Subject:     "foo",
    88  					RequestedAt: time.Now().UTC(),
    89  					AuthTime:    time.Now().UTC().Add(-time.Minute),
    90  				},
    91  			},
    92  		},
    93  		{
    94  			d:           "should pass",
    95  			prompt:      "none",
    96  			isPublic:    true,
    97  			expectErr:   false,
    98  			redirectURL: "https://foo-bar/",
    99  			s: &DefaultSession{
   100  				Subject: "foo",
   101  				Claims: &jwt.IDTokenClaims{
   102  					Subject:     "foo",
   103  					RequestedAt: time.Now().UTC(),
   104  					AuthTime:    time.Now().UTC().Add(-time.Minute),
   105  				},
   106  			},
   107  		},
   108  		{
   109  			d:         "should fail because prompt=none requires an auth time being set",
   110  			prompt:    "none",
   111  			isPublic:  false,
   112  			expectErr: true,
   113  			s: &DefaultSession{
   114  				Subject: "foo",
   115  				Claims: &jwt.IDTokenClaims{
   116  					Subject:     "foo",
   117  					RequestedAt: time.Now().UTC(),
   118  				},
   119  			},
   120  		},
   121  		{
   122  			d:         "should fail because prompt=none and auth time is recent (after requested at)",
   123  			prompt:    "none",
   124  			isPublic:  false,
   125  			expectErr: true,
   126  			s: &DefaultSession{
   127  				Subject: "foo",
   128  				Claims: &jwt.IDTokenClaims{
   129  					Subject:     "foo",
   130  					RequestedAt: time.Now().UTC().Add(-time.Minute),
   131  					AuthTime:    time.Now().UTC(),
   132  				},
   133  			},
   134  		},
   135  		{
   136  			d:         "should pass because prompt=none and auth time is in the past (before requested at)",
   137  			prompt:    "none",
   138  			isPublic:  false,
   139  			expectErr: false,
   140  			s: &DefaultSession{
   141  				Subject: "foo",
   142  				Claims: &jwt.IDTokenClaims{
   143  					Subject:     "foo",
   144  					RequestedAt: time.Now().UTC(),
   145  					AuthTime:    time.Now().UTC().Add(-time.Minute),
   146  				},
   147  			},
   148  		},
   149  		{
   150  			d:         "should fail because prompt=none can not be used together with other prompts",
   151  			prompt:    "none login",
   152  			isPublic:  false,
   153  			expectErr: true,
   154  			s: &DefaultSession{
   155  				Subject: "foo",
   156  				Claims: &jwt.IDTokenClaims{
   157  					Subject:     "foo",
   158  					RequestedAt: time.Now().UTC(),
   159  					AuthTime:    time.Now().UTC(),
   160  				},
   161  			},
   162  		},
   163  		{
   164  			d:         "should fail because prompt=foo is an unknown value",
   165  			prompt:    "foo",
   166  			isPublic:  false,
   167  			expectErr: true,
   168  			s: &DefaultSession{
   169  				Subject: "foo",
   170  				Claims: &jwt.IDTokenClaims{
   171  					Subject:     "foo",
   172  					RequestedAt: time.Now().UTC(),
   173  					AuthTime:    time.Now().UTC(),
   174  				},
   175  			},
   176  		},
   177  		{
   178  			d:         "should pass because requesting consent and login works with public clients",
   179  			prompt:    "login consent",
   180  			isPublic:  true,
   181  			expectErr: false,
   182  			s: &DefaultSession{
   183  				Subject: "foo",
   184  				Claims: &jwt.IDTokenClaims{
   185  					Subject:     "foo",
   186  					RequestedAt: time.Now().UTC().Add(-time.Second * 5),
   187  					AuthTime:    time.Now().UTC().Add(-time.Second),
   188  				},
   189  			},
   190  		},
   191  		{
   192  			d:         "should pass because requesting consent and login works with confidential clients",
   193  			prompt:    "login consent",
   194  			isPublic:  false,
   195  			expectErr: false,
   196  			s: &DefaultSession{
   197  				Subject: "foo",
   198  				Claims: &jwt.IDTokenClaims{
   199  					Subject:     "foo",
   200  					RequestedAt: time.Now().UTC().Add(-time.Second * 5),
   201  					AuthTime:    time.Now().UTC().Add(-time.Second),
   202  				},
   203  			},
   204  		},
   205  		{
   206  			d:         "should fail subject from ID token does not match subject from session",
   207  			prompt:    "login",
   208  			isPublic:  false,
   209  			expectErr: true,
   210  			s: &DefaultSession{
   211  				Subject: "foo",
   212  				Claims: &jwt.IDTokenClaims{
   213  					Subject:     "foo",
   214  					RequestedAt: time.Now().UTC(),
   215  					AuthTime:    time.Now().UTC().Add(-time.Second),
   216  				},
   217  			},
   218  			idTokenHint: genIDToken(jwt.IDTokenClaims{
   219  				Subject:     "bar",
   220  				RequestedAt: time.Now(),
   221  				ExpiresAt:   time.Now().Add(time.Hour),
   222  			}),
   223  		},
   224  		{
   225  			d:         "should pass subject from ID token matches subject from session",
   226  			prompt:    "",
   227  			isPublic:  false,
   228  			expectErr: false,
   229  			s: &DefaultSession{
   230  				Subject: "foo",
   231  				Claims: &jwt.IDTokenClaims{
   232  					Subject:     "foo",
   233  					RequestedAt: time.Now().UTC(),
   234  					AuthTime:    time.Now().UTC().Add(-time.Second),
   235  				},
   236  			},
   237  			idTokenHint: genIDToken(jwt.IDTokenClaims{
   238  				Subject:     "foo",
   239  				RequestedAt: time.Now(),
   240  				ExpiresAt:   time.Now().Add(time.Hour),
   241  			}),
   242  		},
   243  		{
   244  			d:         "should pass subject from ID token matches subject from session even though id token is expired",
   245  			prompt:    "",
   246  			isPublic:  false,
   247  			expectErr: false,
   248  			s: &DefaultSession{
   249  				Subject: "foo",
   250  				Claims: &jwt.IDTokenClaims{
   251  					Subject:     "foo",
   252  					RequestedAt: time.Now().UTC(),
   253  					AuthTime:    time.Now().UTC().Add(-time.Second),
   254  					ExpiresAt:   time.Now().UTC().Add(-time.Second),
   255  				},
   256  			},
   257  			idTokenHint: genIDToken(jwt.IDTokenClaims{
   258  				Subject:     "foo",
   259  				RequestedAt: time.Now(),
   260  				ExpiresAt:   time.Now().Add(time.Hour),
   261  			}),
   262  		},
   263  	} {
   264  		t.Run(fmt.Sprintf("case=%d/description=%s", k, tc.d), func(t *testing.T) {
   265  			t.Logf("%s", tc.idTokenHint)
   266  			err := v.ValidatePrompt(context.TODO(), &fosite.AuthorizeRequest{
   267  				Request: fosite.Request{
   268  					Form:    url.Values{"prompt": {tc.prompt}, "id_token_hint": {tc.idTokenHint}},
   269  					Client:  &fosite.DefaultClient{Public: tc.isPublic},
   270  					Session: tc.s,
   271  				},
   272  				RedirectURI: parse(tc.redirectURL),
   273  			})
   274  			if tc.expectErr {
   275  				assert.Error(t, err)
   276  			} else {
   277  				assert.NoError(t, err)
   278  			}
   279  		})
   280  	}
   281  }
   282  
   283  func parse(u string) *url.URL {
   284  	o, _ := url.Parse(u)
   285  	return o
   286  }
   287  

View as plain text