1 Star 0 Fork 0

一片会思考的猪肉/fosite

加入 Gitee
与超过 1200万 开发者一起发现、参与优秀开源项目,私有仓库也完全免费 :)
免费加入
文件
克隆/下载
client_authentication_test.go 23.23 KB
一键复制 编辑 原始数据 按行查看 历史
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561
/*
* Copyright © 2017-2018 Aeneas Rekkas <[email protected]>
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*
* @author Aeneas Rekkas <[email protected]>
* @Copyright 2017-2018 Aeneas Rekkas <[email protected]>
* @license Apache-2.0
*
*/
package fosite_test
import (
"context"
"crypto/ecdsa"
"crypto/rsa"
"encoding/base64"
"encoding/json"
"fmt"
"net/http"
"net/http/httptest"
"net/url"
"testing"
"time"
jwt "github.com/dgrijalva/jwt-go"
"github.com/pkg/errors"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
jose "gopkg.in/square/go-jose.v2"
. "github.com/ory/fosite"
"github.com/ory/fosite/internal"
"github.com/ory/fosite/storage"
)
func mustGenerateRSAAssertion(t *testing.T, claims jwt.MapClaims, key *rsa.PrivateKey, kid string) string {
token := jwt.NewWithClaims(jwt.SigningMethodRS256, claims)
token.Header["kid"] = kid
tokenString, err := token.SignedString(key)
require.NoError(t, err)
return tokenString
}
func mustGenerateECDSAAssertion(t *testing.T, claims jwt.MapClaims, key *ecdsa.PrivateKey, kid string) string {
token := jwt.NewWithClaims(jwt.SigningMethodES256, claims)
token.Header["kid"] = kid
tokenString, err := token.SignedString(key)
require.NoError(t, err)
return tokenString
}
func mustGenerateHSAssertion(t *testing.T, claims jwt.MapClaims, key *rsa.PrivateKey, kid string) string {
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
tokenString, err := token.SignedString([]byte("aaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccddddddddddddddddddddddd"))
require.NoError(t, err)
return tokenString
}
func mustGenerateNoneAssertion(t *testing.T, claims jwt.MapClaims, key *rsa.PrivateKey, kid string) string {
token := jwt.NewWithClaims(jwt.SigningMethodNone, claims)
tokenString, err := token.SignedString(jwt.UnsafeAllowNoneSignatureType)
require.NoError(t, err)
return tokenString
}
// returns an http basic authorization header, encoded using application/x-www-form-urlencoded
func clientBasicAuthHeader(clientID, clientSecret string) http.Header {
creds := url.QueryEscape(clientID) + ":" + url.QueryEscape(clientSecret)
return http.Header{
"Authorization": {
"Basic " + base64.StdEncoding.EncodeToString([]byte(creds)),
},
}
}
func TestAuthenticateClient(t *testing.T) {
const at = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
hasher := &BCrypt{WorkFactor: 6}
f := &Fosite{
JWKSFetcherStrategy: NewDefaultJWKSFetcherStrategy(),
Store: storage.NewMemoryStore(),
Hasher: hasher,
TokenURL: "token-url",
}
barSecret, err := hasher.Hash(context.TODO(), []byte("bar"))
require.NoError(t, err)
// a secret containing various special characters
complexSecretRaw := "foo %66%6F%6F@$<§!✓"
complexSecret, err := hasher.Hash(context.TODO(), []byte(complexSecretRaw))
require.NoError(t, err)
rsaKey := internal.MustRSAKey()
rsaJwks := &jose.JSONWebKeySet{
Keys: []jose.JSONWebKey{
{
KeyID: "kid-foo",
Use: "sig",
Key: &rsaKey.PublicKey,
},
},
}
ecdsaKey := internal.MustECDSAKey()
ecdsaJwks := &jose.JSONWebKeySet{
Keys: []jose.JSONWebKey{
{
KeyID: "kid-foo",
Use: "sig",
Key: &ecdsaKey.PublicKey,
},
},
}
var h http.HandlerFunc
h = func(w http.ResponseWriter, r *http.Request) {
require.NoError(t, json.NewEncoder(w).Encode(rsaJwks))
}
ts := httptest.NewServer(h)
defer ts.Close()
for k, tc := range []struct {
d string
client *DefaultOpenIDConnectClient
assertionType string
assertion string
r *http.Request
form url.Values
expectErr error
}{
{
d: "should fail because authentication can not be determined",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "foo"}, TokenEndpointAuthMethod: "client_secret_basic"},
form: url.Values{},
r: new(http.Request),
expectErr: ErrInvalidRequest,
},
{
d: "should fail because client does not exist",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "foo", Public: true}, TokenEndpointAuthMethod: "none"},
form: url.Values{"client_id": []string{"bar"}},
r: new(http.Request),
expectErr: ErrInvalidClient,
},
{
d: "should pass because client is public and authentication requirements are met",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "foo", Public: true}, TokenEndpointAuthMethod: "none"},
form: url.Values{"client_id": []string{"foo"}},
r: new(http.Request),
},
{
d: "should pass with client credentials containing special characters",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "!foo%20bar", Secret: complexSecret}, TokenEndpointAuthMethod: "client_secret_post"},
form: url.Values{"client_id": []string{"!foo%20bar"}, "client_secret": []string{complexSecretRaw}},
r: new(http.Request),
},
{
d: "should pass with client credentials containing special characters via basic auth",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "foo — bar! +<&>*", Secret: complexSecret}, TokenEndpointAuthMethod: "client_secret_basic"},
form: url.Values{},
r: &http.Request{Header: clientBasicAuthHeader("foo — bar! +<&>*", complexSecretRaw)},
},
{
d: "should fail because auth method is not none",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "foo", Public: true}, TokenEndpointAuthMethod: "client_secret_basic"},
form: url.Values{"client_id": []string{"foo"}},
r: new(http.Request),
expectErr: ErrInvalidClient,
},
{
d: "should pass because client is confidential and id and secret match in post body",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "foo", Secret: barSecret}, TokenEndpointAuthMethod: "client_secret_post"},
form: url.Values{"client_id": []string{"foo"}, "client_secret": []string{"bar"}},
r: new(http.Request),
},
{
d: "should fail because client is confidential and secret does not match in post body",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "foo", Secret: barSecret}, TokenEndpointAuthMethod: "client_secret_post"},
form: url.Values{"client_id": []string{"foo"}, "client_secret": []string{"baz"}},
r: new(http.Request),
expectErr: ErrInvalidClient,
},
{
d: "should fail because client is confidential and id does not exist in post body",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "bar", Secret: barSecret}, TokenEndpointAuthMethod: "client_secret_post"},
form: url.Values{"client_id": []string{"foo"}, "client_secret": []string{"bar"}},
r: new(http.Request),
expectErr: ErrInvalidClient,
},
{
d: "should pass because client is confidential and id and secret match in header",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "foo", Secret: barSecret}, TokenEndpointAuthMethod: "client_secret_basic"},
form: url.Values{},
r: &http.Request{Header: clientBasicAuthHeader("foo", "bar")},
},
{
d: "should fail because auth method is not client_secret_basic",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "foo", Secret: barSecret}, TokenEndpointAuthMethod: "client_secret_post"},
form: url.Values{},
r: &http.Request{Header: clientBasicAuthHeader("foo", "bar")},
expectErr: ErrInvalidClient,
},
{
d: "should fail because client is confidential and secret does not match in header",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "foo", Secret: barSecret}, TokenEndpointAuthMethod: "client_secret_basic"},
form: url.Values{},
r: &http.Request{Header: clientBasicAuthHeader("foo", "baz")},
expectErr: ErrInvalidClient,
},
{
d: "should fail because client id is not encoded using application/x-www-form-urlencoded",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "foo", Secret: barSecret}, TokenEndpointAuthMethod: "client_secret_basic"},
form: url.Values{},
r: &http.Request{Header: http.Header{"Authorization": {"Basic " + base64.StdEncoding.EncodeToString([]byte("%%%%%%:foo"))}}},
expectErr: ErrInvalidRequest,
},
{
d: "should fail because client secret is not encoded using application/x-www-form-urlencoded",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "foo", Secret: barSecret}, TokenEndpointAuthMethod: "client_secret_basic"},
form: url.Values{},
r: &http.Request{Header: http.Header{"Authorization": {"Basic " + base64.StdEncoding.EncodeToString([]byte("foo:%%%%%%%"))}}},
expectErr: ErrInvalidRequest,
},
{
d: "should fail because client is confidential and id does not exist in header",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "bar", Secret: barSecret}, TokenEndpointAuthMethod: "client_secret_basic"},
form: url.Values{},
r: &http.Request{Header: http.Header{"Authorization": {"Basic " + base64.StdEncoding.EncodeToString([]byte("foo:bar"))}}},
expectErr: ErrInvalidClient,
},
{
d: "should fail because client_assertion but client_assertion is missing",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "foo", Secret: barSecret}, TokenEndpointAuthMethod: "private_key_jwt"},
form: url.Values{"client_id": []string{"foo"}, "client_assertion_type": []string{at}},
r: new(http.Request),
expectErr: ErrInvalidRequest,
},
{
d: "should fail because client_assertion_type is unknown",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "foo", Secret: barSecret}, TokenEndpointAuthMethod: "private_key_jwt"},
form: url.Values{"client_id": []string{"foo"}, "client_assertion_type": []string{"foobar"}},
r: new(http.Request),
expectErr: ErrInvalidRequest,
},
{
d: "should pass with proper RSA assertion when JWKs are set within the client and client_id is not set in the request",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "bar", Secret: barSecret}, JSONWebKeys: rsaJwks, TokenEndpointAuthMethod: "private_key_jwt"},
form: url.Values{"client_assertion": {mustGenerateRSAAssertion(t, jwt.MapClaims{
"sub": "bar",
"exp": time.Now().Add(time.Hour).Unix(),
"iss": "bar",
"jti": "12345",
"aud": "token-url",
}, rsaKey, "kid-foo")}, "client_assertion_type": []string{at}},
r: new(http.Request),
},
{
d: "should pass with proper ECDSA assertion when JWKs are set within the client and client_id is not set in the request",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "bar", Secret: barSecret}, JSONWebKeys: ecdsaJwks, TokenEndpointAuthMethod: "private_key_jwt", TokenEndpointAuthSigningAlgorithm: "ES256"},
form: url.Values{"client_assertion": {mustGenerateECDSAAssertion(t, jwt.MapClaims{
"sub": "bar",
"exp": time.Now().Add(time.Hour).Unix(),
"iss": "bar",
"jti": "12345",
"aud": "token-url",
}, ecdsaKey, "kid-foo")}, "client_assertion_type": []string{at}},
r: new(http.Request),
},
{
d: "should fail because RSA assertion is used, but ECDSA assertion is required",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "bar", Secret: barSecret}, JSONWebKeys: ecdsaJwks, TokenEndpointAuthMethod: "private_key_jwt", TokenEndpointAuthSigningAlgorithm: "ES256"},
form: url.Values{"client_assertion": {mustGenerateRSAAssertion(t, jwt.MapClaims{
"sub": "bar",
"exp": time.Now().Add(time.Hour).Unix(),
"iss": "bar",
"jti": "12345",
"aud": "token-url",
}, rsaKey, "kid-foo")}, "client_assertion_type": []string{at}},
r: new(http.Request),
expectErr: ErrInvalidClient,
},
{
d: "should fail because token auth method is not private_key_jwt, but client_secret_jwt",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "bar", Secret: barSecret}, JSONWebKeys: rsaJwks, TokenEndpointAuthMethod: "client_secret_jwt"},
form: url.Values{"client_assertion": {mustGenerateRSAAssertion(t, jwt.MapClaims{
"sub": "bar",
"exp": time.Now().Add(time.Hour).Unix(),
"iss": "bar",
"jti": "12345",
"aud": "token-url",
}, rsaKey, "kid-foo")}, "client_assertion_type": []string{at}},
r: new(http.Request),
expectErr: ErrInvalidClient,
},
{
d: "should fail because token auth method is not private_key_jwt, but none",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "bar", Secret: barSecret}, JSONWebKeys: rsaJwks, TokenEndpointAuthMethod: "none"},
form: url.Values{"client_assertion": {mustGenerateRSAAssertion(t, jwt.MapClaims{
"sub": "bar",
"exp": time.Now().Add(time.Hour).Unix(),
"iss": "bar",
"jti": "12345",
"aud": "token-url",
}, rsaKey, "kid-foo")}, "client_assertion_type": []string{at}},
r: new(http.Request),
expectErr: ErrInvalidClient,
},
{
d: "should fail because token auth method is not private_key_jwt, but client_secret_post",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "bar", Secret: barSecret}, JSONWebKeys: rsaJwks, TokenEndpointAuthMethod: "client_secret_post"},
form: url.Values{"client_assertion": {mustGenerateRSAAssertion(t, jwt.MapClaims{
"sub": "bar",
"exp": time.Now().Add(time.Hour).Unix(),
"iss": "bar",
"jti": "12345",
"aud": "token-url",
}, rsaKey, "kid-foo")}, "client_assertion_type": []string{at}},
r: new(http.Request),
expectErr: ErrInvalidClient,
},
{
d: "should fail because token auth method is not private_key_jwt, but client_secret_basic",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "bar", Secret: barSecret}, JSONWebKeys: rsaJwks, TokenEndpointAuthMethod: "client_secret_basic"},
form: url.Values{"client_assertion": {mustGenerateRSAAssertion(t, jwt.MapClaims{
"sub": "bar",
"exp": time.Now().Add(time.Hour).Unix(),
"iss": "bar",
"jti": "12345",
"aud": "token-url",
}, rsaKey, "kid-foo")}, "client_assertion_type": []string{at}},
r: new(http.Request),
expectErr: ErrInvalidClient,
},
{
d: "should fail because token auth method is not private_key_jwt, but foobar",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "bar", Secret: barSecret}, JSONWebKeys: rsaJwks, TokenEndpointAuthMethod: "foobar"},
form: url.Values{"client_assertion": {mustGenerateRSAAssertion(t, jwt.MapClaims{
"sub": "bar",
"exp": time.Now().Add(time.Hour).Unix(),
"iss": "bar",
"jti": "12345",
"aud": "token-url",
}, rsaKey, "kid-foo")}, "client_assertion_type": []string{at}},
r: new(http.Request),
expectErr: ErrInvalidClient,
},
{
d: "should pass with proper assertion when JWKs are set within the client and client_id is not set in the request (aud is array)",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "bar", Secret: barSecret}, JSONWebKeys: rsaJwks, TokenEndpointAuthMethod: "private_key_jwt"},
form: url.Values{"client_assertion": {mustGenerateRSAAssertion(t, jwt.MapClaims{
"sub": "bar",
"exp": time.Now().Add(time.Hour).Unix(),
"iss": "bar",
"jti": "12345",
"aud": []string{"token-url-2", "token-url"},
}, rsaKey, "kid-foo")}, "client_assertion_type": []string{at}},
r: new(http.Request),
},
{
d: "should fail because audience (array) does not match token url",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "bar", Secret: barSecret}, JSONWebKeys: rsaJwks, TokenEndpointAuthMethod: "private_key_jwt"},
form: url.Values{"client_assertion": {mustGenerateRSAAssertion(t, jwt.MapClaims{
"sub": "bar",
"exp": time.Now().Add(time.Hour).Unix(),
"iss": "bar",
"jti": "12345",
"aud": []string{"token-url-1", "token-url-2"},
}, rsaKey, "kid-foo")}, "client_assertion_type": []string{at}},
r: new(http.Request),
expectErr: ErrInvalidClient,
},
{
d: "should pass with proper assertion when JWKs are set within the client",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "bar", Secret: barSecret}, JSONWebKeys: rsaJwks, TokenEndpointAuthMethod: "private_key_jwt"},
form: url.Values{"client_id": []string{"bar"}, "client_assertion": {mustGenerateRSAAssertion(t, jwt.MapClaims{
"sub": "bar",
"exp": time.Now().Add(time.Hour).Unix(),
"iss": "bar",
"jti": "12345",
"aud": "token-url",
}, rsaKey, "kid-foo")}, "client_assertion_type": []string{at}},
r: new(http.Request),
},
{
d: "should fail because JWT algorithm is HS256",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "bar", Secret: barSecret}, JSONWebKeys: rsaJwks, TokenEndpointAuthMethod: "private_key_jwt"},
form: url.Values{"client_id": []string{"bar"}, "client_assertion": {mustGenerateHSAssertion(t, jwt.MapClaims{
"sub": "bar",
"exp": time.Now().Add(time.Hour).Unix(),
"iss": "bar",
"jti": "12345",
"aud": "token-url",
}, rsaKey, "kid-foo")}, "client_assertion_type": []string{at}},
r: new(http.Request),
expectErr: ErrInvalidClient,
},
{
d: "should fail because JWT algorithm is none",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "bar", Secret: barSecret}, JSONWebKeys: rsaJwks, TokenEndpointAuthMethod: "private_key_jwt"},
form: url.Values{"client_id": []string{"bar"}, "client_assertion": {mustGenerateNoneAssertion(t, jwt.MapClaims{
"sub": "bar",
"exp": time.Now().Add(time.Hour).Unix(),
"iss": "bar",
"jti": "12345",
"aud": "token-url",
}, rsaKey, "kid-foo")}, "client_assertion_type": []string{at}},
r: new(http.Request),
expectErr: ErrInvalidClient,
},
{
d: "should pass with proper assertion when JWKs URI is set",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "bar", Secret: barSecret}, JSONWebKeysURI: ts.URL, TokenEndpointAuthMethod: "private_key_jwt"},
form: url.Values{"client_id": []string{"bar"}, "client_assertion": {mustGenerateRSAAssertion(t, jwt.MapClaims{
"sub": "bar",
"exp": time.Now().Add(time.Hour).Unix(),
"iss": "bar",
"jti": "12345",
"aud": "token-url",
}, rsaKey, "kid-foo")}, "client_assertion_type": []string{at}},
r: new(http.Request),
},
{
d: "should fail because client_assertion sub does not match client",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "bar", Secret: barSecret}, JSONWebKeys: rsaJwks, TokenEndpointAuthMethod: "private_key_jwt"},
form: url.Values{"client_id": []string{"bar"}, "client_assertion": {mustGenerateRSAAssertion(t, jwt.MapClaims{
"sub": "not-bar",
"exp": time.Now().Add(time.Hour).Unix(),
"iss": "bar",
"jti": "12345",
"aud": "token-url",
}, rsaKey, "kid-foo")}, "client_assertion_type": []string{at}},
r: new(http.Request),
expectErr: ErrInvalidClient,
},
{
d: "should fail because client_assertion iss does not match client",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "bar", Secret: barSecret}, JSONWebKeys: rsaJwks, TokenEndpointAuthMethod: "private_key_jwt"},
form: url.Values{"client_id": []string{"bar"}, "client_assertion": {mustGenerateRSAAssertion(t, jwt.MapClaims{
"sub": "bar",
"exp": time.Now().Add(time.Hour).Unix(),
"iss": "not-bar",
"jti": "12345",
"aud": "token-url",
}, rsaKey, "kid-foo")}, "client_assertion_type": []string{at}},
r: new(http.Request),
expectErr: ErrInvalidClient,
},
{
d: "should fail because client_assertion jti is not set",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "bar", Secret: barSecret}, JSONWebKeys: rsaJwks, TokenEndpointAuthMethod: "private_key_jwt"},
form: url.Values{"client_id": []string{"bar"}, "client_assertion": {mustGenerateRSAAssertion(t, jwt.MapClaims{
"sub": "bar",
"exp": time.Now().Add(time.Hour).Unix(),
"iss": "bar",
"aud": "token-url",
}, rsaKey, "kid-foo")}, "client_assertion_type": []string{at}},
r: new(http.Request),
expectErr: ErrInvalidClient,
},
{
d: "should fail because client_assertion aud is not set",
client: &DefaultOpenIDConnectClient{DefaultClient: &DefaultClient{ID: "bar", Secret: barSecret}, JSONWebKeys: rsaJwks, TokenEndpointAuthMethod: "private_key_jwt"},
form: url.Values{"client_id": []string{"bar"}, "client_assertion": {mustGenerateRSAAssertion(t, jwt.MapClaims{
"sub": "bar",
"exp": time.Now().Add(time.Hour).Unix(),
"iss": "bar",
"jti": "12345",
"aud": "not-token-url",
}, rsaKey, "kid-foo")}, "client_assertion_type": []string{at}},
r: new(http.Request),
expectErr: ErrInvalidClient,
},
} {
t.Run(fmt.Sprintf("case=%d/description=%s", k, tc.d), func(t *testing.T) {
store := storage.NewMemoryStore()
store.Clients[tc.client.ID] = tc.client
f.Store = store
c, err := f.AuthenticateClient(nil, tc.r, tc.form)
if tc.expectErr != nil {
require.EqualError(t, err, tc.expectErr.Error())
return
}
if err != nil {
switch e := errors.Cause(err).(type) {
case *jwt.ValidationError:
t.Logf("Error is: %s", e.Inner)
case *RFC6749Error:
t.Logf("Debug is: %s", e.Debug)
}
}
require.NoError(t, err)
assert.EqualValues(t, tc.client, c)
})
}
}
func TestAuthenticateClientTwice(t *testing.T) {
const at = "urn:ietf:params:oauth:client-assertion-type:jwt-bearer"
key := internal.MustRSAKey()
client := &DefaultOpenIDConnectClient{
DefaultClient: &DefaultClient{
ID: "bar",
Secret: []byte("secret"),
},
JSONWebKeys: &jose.JSONWebKeySet{
Keys: []jose.JSONWebKey{
{
KeyID: "kid-foo",
Use: "sig",
Key: &key.PublicKey,
},
},
},
TokenEndpointAuthMethod: "private_key_jwt",
}
store := storage.NewMemoryStore()
store.Clients[client.ID] = client
hasher := &BCrypt{WorkFactor: 6}
f := &Fosite{
JWKSFetcherStrategy: NewDefaultJWKSFetcherStrategy(),
Store: store,
Hasher: hasher,
TokenURL: "token-url",
}
formValues := url.Values{"client_id": []string{"bar"}, "client_assertion": {mustGenerateRSAAssertion(t, jwt.MapClaims{
"sub": "bar",
"exp": time.Now().Add(time.Hour).Unix(),
"iss": "bar",
"jti": "12345",
"aud": "token-url",
}, key, "kid-foo")}, "client_assertion_type": []string{at}}
c, err := f.AuthenticateClient(nil, new(http.Request), formValues)
require.NoError(t, err, "%#v", err)
assert.Equal(t, client, c)
// replay the request and expect it to fail
c, err = f.AuthenticateClient(nil, new(http.Request), formValues)
require.Error(t, err)
assert.EqualError(t, err, ErrJTIKnown.Error())
assert.Nil(t, c)
}
Loading...
马建仓 AI 助手
尝试更多
代码解读
代码找茬
代码优化
1
https://gitee.com/zhurou/fosite.git
[email protected]:zhurou/fosite.git
zhurou
fosite
fosite
master

搜索帮助