...

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

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

     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 openid
    23  
    24  import (
    25  	"context"
    26  	"fmt"
    27  	"testing"
    28  	"time"
    29  
    30  	"github.com/stretchr/testify/assert"
    31  
    32  	"github.com/ory/fosite"
    33  	"github.com/ory/fosite/token/jwt"
    34  )
    35  
    36  func TestJWTStrategy_GenerateIDToken(t *testing.T) {
    37  	var j = &DefaultStrategy{
    38  		JWTStrategy: &jwt.RS256JWTStrategy{
    39  			PrivateKey: key,
    40  		},
    41  		MinParameterEntropy: fosite.MinParameterEntropy,
    42  	}
    43  
    44  	var req *fosite.AccessRequest
    45  	for k, c := range []struct {
    46  		description string
    47  		setup       func()
    48  		expectErr   bool
    49  	}{
    50  		{
    51  			setup: func() {
    52  				req = fosite.NewAccessRequest(&DefaultSession{
    53  					Claims: &jwt.IDTokenClaims{
    54  						Subject: "peter",
    55  					},
    56  					Headers: &jwt.Headers{},
    57  				})
    58  				req.Form.Set("nonce", "some-secure-nonce-state")
    59  			},
    60  			expectErr: false,
    61  		},
    62  		{
    63  			setup: func() {
    64  				req = fosite.NewAccessRequest(&DefaultSession{
    65  					Claims: &jwt.IDTokenClaims{
    66  						Subject:     "peter",
    67  						AuthTime:    time.Now().UTC(),
    68  						RequestedAt: time.Now().UTC(),
    69  					},
    70  					Headers: &jwt.Headers{},
    71  				})
    72  				req.Form.Set("nonce", "some-secure-nonce-state")
    73  				req.Form.Set("max_age", "1234")
    74  			},
    75  			expectErr: false,
    76  		},
    77  		{
    78  			setup: func() {
    79  				req = fosite.NewAccessRequest(&DefaultSession{
    80  					Claims: &jwt.IDTokenClaims{
    81  						Subject:   "peter",
    82  						ExpiresAt: time.Now().UTC().Add(-time.Hour),
    83  					},
    84  					Headers: &jwt.Headers{},
    85  				})
    86  				req.Form.Set("nonce", "some-secure-nonce-state")
    87  			},
    88  			expectErr: true,
    89  		},
    90  		{
    91  			setup: func() {
    92  				req = fosite.NewAccessRequest(&DefaultSession{
    93  					Claims: &jwt.IDTokenClaims{
    94  						Subject: "peter",
    95  					},
    96  					Headers: &jwt.Headers{},
    97  				})
    98  				req.Form.Set("nonce", "some-secure-nonce-state")
    99  				req.Form.Set("max_age", "1234")
   100  			},
   101  			expectErr: true,
   102  		},
   103  		{
   104  			setup: func() {
   105  				req = fosite.NewAccessRequest(&DefaultSession{
   106  					Claims:  &jwt.IDTokenClaims{},
   107  					Headers: &jwt.Headers{},
   108  				})
   109  				req.Form.Set("nonce", "some-secure-nonce-state")
   110  			},
   111  			expectErr: true,
   112  		},
   113  		{
   114  			setup: func() {
   115  				req = fosite.NewAccessRequest(&DefaultSession{
   116  					Claims: &jwt.IDTokenClaims{
   117  						Subject: "peter",
   118  					},
   119  					Headers: &jwt.Headers{},
   120  				})
   121  			},
   122  			expectErr: false,
   123  		},
   124  		{
   125  			description: "should pass because max_age was requested and auth_time happened after initial request time",
   126  			setup: func() {
   127  				req = fosite.NewAccessRequest(&DefaultSession{
   128  					Claims: &jwt.IDTokenClaims{
   129  						Subject:     "peter",
   130  						AuthTime:    time.Now().UTC(),
   131  						RequestedAt: time.Now().UTC(),
   132  					},
   133  					Headers: &jwt.Headers{},
   134  				})
   135  				req.Form.Set("max_age", "60")
   136  			},
   137  			expectErr: false,
   138  		},
   139  		{
   140  			description: "should fail because max_age was requested and auth_time has expired",
   141  			setup: func() {
   142  				req = fosite.NewAccessRequest(&DefaultSession{
   143  					Claims: &jwt.IDTokenClaims{
   144  						Subject:  "peter",
   145  						AuthTime: time.Now().Add(-time.Hour).UTC(),
   146  					},
   147  					Headers: &jwt.Headers{},
   148  				})
   149  				req.Form.Set("max_age", "60")
   150  			},
   151  			expectErr: true,
   152  		},
   153  		{
   154  			description: "should fail because prompt=none was requested and auth_time indicates fresh login",
   155  			setup: func() {
   156  				req = fosite.NewAccessRequest(&DefaultSession{
   157  					Claims: &jwt.IDTokenClaims{
   158  						Subject:     "peter",
   159  						AuthTime:    time.Now().UTC(),
   160  						RequestedAt: time.Now().Add(-time.Minute),
   161  					},
   162  					Headers: &jwt.Headers{},
   163  				})
   164  				req.Form.Set("prompt", "none")
   165  			},
   166  			expectErr: true,
   167  		},
   168  		{
   169  			description: "should pass because prompt=none was requested and auth_time indicates fresh login but grant type is refresh_token",
   170  			setup: func() {
   171  				req = fosite.NewAccessRequest(&DefaultSession{
   172  					Claims: &jwt.IDTokenClaims{
   173  						Subject:     "peter",
   174  						AuthTime:    time.Now().UTC(),
   175  						RequestedAt: time.Now().Add(-time.Minute),
   176  					},
   177  					Headers: &jwt.Headers{},
   178  				})
   179  				req.Form.Set("prompt", "none")
   180  				req.Form.Set("grant_type", "refresh_token")
   181  			},
   182  			expectErr: false,
   183  		},
   184  		{
   185  			description: "should pass because prompt=none was requested and auth_time indicates old login",
   186  			setup: func() {
   187  				req = fosite.NewAccessRequest(&DefaultSession{
   188  					Claims: &jwt.IDTokenClaims{
   189  						Subject:     "peter",
   190  						AuthTime:    time.Now().Add(-time.Hour).UTC(),
   191  						RequestedAt: time.Now().Add(-time.Minute),
   192  					},
   193  					Headers: &jwt.Headers{},
   194  				})
   195  				req.Form.Set("prompt", "none")
   196  			},
   197  			expectErr: false,
   198  		},
   199  		{
   200  			description: "should pass because prompt=login was requested and auth_time indicates fresh login",
   201  			setup: func() {
   202  				req = fosite.NewAccessRequest(&DefaultSession{
   203  					Claims: &jwt.IDTokenClaims{
   204  						Subject:     "peter",
   205  						AuthTime:    time.Now().UTC(),
   206  						RequestedAt: time.Now().Add(-time.Minute),
   207  					},
   208  					Headers: &jwt.Headers{},
   209  				})
   210  				req.Form.Set("prompt", "login")
   211  			},
   212  			expectErr: false,
   213  		},
   214  		{
   215  			description: "should fail because prompt=login was requested and auth_time indicates old login",
   216  			setup: func() {
   217  				req = fosite.NewAccessRequest(&DefaultSession{
   218  					Claims: &jwt.IDTokenClaims{
   219  						Subject:     "peter",
   220  						AuthTime:    time.Now().Add(-time.Hour).UTC(),
   221  						RequestedAt: time.Now().Add(-time.Minute),
   222  					},
   223  					Headers: &jwt.Headers{},
   224  				})
   225  				req.Form.Set("prompt", "login")
   226  			},
   227  			expectErr: true,
   228  		},
   229  		{
   230  			description: "should pass because id_token_hint subject matches subject from claims",
   231  			setup: func() {
   232  				req = fosite.NewAccessRequest(&DefaultSession{
   233  					Claims: &jwt.IDTokenClaims{
   234  						Subject:     "peter",
   235  						AuthTime:    time.Now().Add(-time.Hour).UTC(),
   236  						RequestedAt: time.Now().Add(-time.Minute),
   237  					},
   238  					Headers: &jwt.Headers{},
   239  				})
   240  				token, _ := j.GenerateIDToken(context.TODO(), fosite.NewAccessRequest(&DefaultSession{
   241  					Claims: &jwt.IDTokenClaims{
   242  						Subject: "peter",
   243  					},
   244  					Headers: &jwt.Headers{},
   245  				}))
   246  				req.Form.Set("id_token_hint", token)
   247  			},
   248  			expectErr: false,
   249  		},
   250  		{
   251  			description: "should pass even though token is expired",
   252  			setup: func() {
   253  				req = fosite.NewAccessRequest(&DefaultSession{
   254  					Claims: &jwt.IDTokenClaims{
   255  						Subject:     "peter",
   256  						AuthTime:    time.Now().Add(-time.Hour).UTC(),
   257  						RequestedAt: time.Now().Add(-time.Minute),
   258  					},
   259  					Headers: &jwt.Headers{},
   260  				})
   261  				token, _ := j.GenerateIDToken(context.TODO(), fosite.NewAccessRequest(&DefaultSession{
   262  					Claims: &jwt.IDTokenClaims{
   263  						Subject:   "peter",
   264  						ExpiresAt: time.Now().Add(-time.Hour).UTC(),
   265  					},
   266  					Headers: &jwt.Headers{},
   267  				}))
   268  				req.Form.Set("id_token_hint", token)
   269  			},
   270  			expectErr: false,
   271  		},
   272  		{
   273  			description: "should fail because id_token_hint subject does not match subject from claims",
   274  			setup: func() {
   275  				req = fosite.NewAccessRequest(&DefaultSession{
   276  					Claims: &jwt.IDTokenClaims{
   277  						Subject:     "peter",
   278  						AuthTime:    time.Now().Add(-time.Hour).UTC(),
   279  						RequestedAt: time.Now().Add(-time.Minute),
   280  					},
   281  					Headers: &jwt.Headers{},
   282  				})
   283  				token, _ := j.GenerateIDToken(context.TODO(), fosite.NewAccessRequest(&DefaultSession{
   284  					Claims: &jwt.IDTokenClaims{Subject: "alice"}, Headers: &jwt.Headers{},
   285  				}))
   286  				req.Form.Set("id_token_hint", token)
   287  			},
   288  			expectErr: true,
   289  		},
   290  	} {
   291  		t.Run(fmt.Sprintf("case=%d/description=%s", k, c.description), func(t *testing.T) {
   292  			c.setup()
   293  			token, err := j.GenerateIDToken(context.TODO(), req)
   294  			assert.Equal(t, c.expectErr, err != nil, "%d: %+v", k, err)
   295  			if !c.expectErr {
   296  				assert.NotEmpty(t, token)
   297  			}
   298  		})
   299  	}
   300  }
   301  

View as plain text