From 0911eb0d643d77105e0126bf2303bdfd7190ccd3 Mon Sep 17 00:00:00 2001 From: Nikita Vorobey Date: Tue, 10 Oct 2017 14:30:19 +0300 Subject: [PATCH 01/35] handler/oauth2: set expiration time before the access token is generated (#216) Signed-off-by: Nikita Vorobey --- handler/oauth2/flow_authorize_implicit.go | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/handler/oauth2/flow_authorize_implicit.go b/handler/oauth2/flow_authorize_implicit.go index 336ce763..30da033f 100644 --- a/handler/oauth2/flow_authorize_implicit.go +++ b/handler/oauth2/flow_authorize_implicit.go @@ -55,13 +55,14 @@ func (c *AuthorizeImplicitGrantTypeHandler) HandleAuthorizeEndpointRequest(ctx c } func (c *AuthorizeImplicitGrantTypeHandler) IssueImplicitAccessToken(ctx context.Context, ar fosite.AuthorizeRequester, resp fosite.AuthorizeResponder) error { + ar.GetSession().SetExpiresAt(fosite.AccessToken, time.Now().Add(c.AccessTokenLifespan)) + // Generate the code token, signature, err := c.AccessTokenStrategy.GenerateAccessToken(ctx, ar) if err != nil { return errors.Wrap(fosite.ErrServerError, err.Error()) } - ar.GetSession().SetExpiresAt(fosite.AccessToken, time.Now().Add(c.AccessTokenLifespan)) if err := c.AccessTokenStorage.CreateAccessTokenSession(ctx, signature, ar); err != nil { return errors.Wrap(fosite.ErrServerError, err.Error()) } From b4b9be5640c9d814b35f54b2c8621137364209ca Mon Sep 17 00:00:00 2001 From: arekkas Date: Wed, 25 Oct 2017 10:44:57 +0200 Subject: [PATCH 02/35] token/hmac: replace custom logic with copypasta --- HISTORY.md | 9 ++ glide.lock | 47 +++++----- glide.yaml | 21 +++-- handler/oauth2/strategy_hmacsha_test.go | 2 +- handler/openid/flow_hybrid_test.go | 2 +- integration/helper_setup_test.go | 2 +- integration/oidc_implicit_hybrid_test.go | 114 ++++++++++++----------- token/hmac/hmacsha.go | 58 ++++++------ token/hmac/hmacsha_test.go | 4 +- 9 files changed, 132 insertions(+), 127 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index dcc8174e..0cda53c1 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -32,6 +32,15 @@ bumps (`0.1.0` -> `0.2.0`). +## 0.12.0 + +### Breaking changes + +#### Improved cryptographic methods + +* The minimum required secret length used to generate signatures of access tokens has increased from 16 to 32 byte. +* The algorithm used to generate access tokens using the HMAC-SHA strategy has changed from HMAC-SHA256 to HMAC-SHA512. + ## 0.11.0 ### Non-breaking changes diff --git a/glide.lock b/glide.lock index 7a8864aa..3eb3cb48 100644 --- a/glide.lock +++ b/glide.lock @@ -1,55 +1,44 @@ -hash: d92ad78a0e95699af758182303644f7316bb846aa8efbd29301f27cf690b59f3 -updated: 2017-07-08T21:49:06.7880537+02:00 +hash: e095f7a7794a22ca84172c4f0d7f2d150fa8d260f9852537828441910ad73e84 +updated: 2017-10-25T11:28:31.641679+02:00 imports: - name: github.com/asaskevich/govalidator - version: 4918b99a7cb949bb295f3c7bbaf24b577d806e35 + version: 73945b6115bfbbcc57d89b7316e28109364124e1 - name: github.com/dgrijalva/jwt-go - version: d2709f9f1f31ebcda9651b03077758c1f3a0018c + version: dbeaa9332f19a944acb5736b4456cfcc02140e29 - name: github.com/golang/mock - version: 93f6609a15b7de76bd49259f1f9a6b58df358936 + version: 13f360950a79f5864a972c786a10a50e44b69541 subpackages: - gomock +- name: github.com/gtank/cryptopasta + version: 1f550f6f2f69009f6ae57347c188e0a67cd4e500 - name: github.com/mohae/deepcopy version: 491d3605edfb866af34a48075bd4355ac1bf46ca -- name: github.com/oleiade/reflections - version: 2b6ec3da648e3e834dc41bad8d9ed7f2dc6a9496 - name: github.com/pborman/uuid - version: a97ce2ca70fa5a848076093f05e639a89ca34d06 + version: e790cca94e6cc75c7064b1332e63811d4aae1a53 - name: github.com/pkg/errors version: 645ef00459ed84a119197bfb8d8205042c6df63d -- name: github.com/rakyll/hey - version: 886125b9f23d5bdb23dbb1000f2bff4b757ccfb1 - subpackages: - - requester - name: golang.org/x/crypto - version: 453249f01cfeb54c3d549ddb75ff152ca243f9d8 + version: faadfbdc035307d901e69eea569f5dda451a3ee3 subpackages: - bcrypt - blowfish -- name: golang.org/x/net - version: dd2d9a67c97da0afa00d5726e28086007a0acce5 - subpackages: - - context - - http2 - - http2/hpack - - idna - - lex/httplex - - publicsuffix testImports: - name: github.com/davecgh/go-spew version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 subpackages: - spew - name: github.com/golang/protobuf - version: 69b215d01a5606c843240eab4937eab3acee6530 + version: 11b8df160996e00fd4b55cbaafb3d84ec6d50fa8 subpackages: - proto - name: github.com/gorilla/context version: 1ea25387ff6f684839d82767c1733ff4d4d15d0a - name: github.com/gorilla/mux - version: bcd8bc72b08df0f70df986b97f95590779502d31 + version: 24fca303ac6da784b9e8269f724ddeb0b2eea5e7 - name: github.com/moul/http2curl version: 4e24498b31dba4683efb9d35c1c8a91e2eda28c8 +- name: github.com/oleiade/reflections + version: 2b6ec3da648e3e834dc41bad8d9ed7f2dc6a9496 - name: github.com/parnurzeal/gorequest version: a578a48e8d6ca8b01a3b18314c43c6716bb5f5a3 - name: github.com/pmezard/go-difflib @@ -61,13 +50,19 @@ testImports: subpackages: - assert - require +- name: golang.org/x/net + version: 859d1a86bb617c0c20d154590c3c5d3fcb670b07 + subpackages: + - context + - context/ctxhttp + - publicsuffix - name: golang.org/x/oauth2 - version: b9780ec78894ab900c062d58ee3076cd9b2a4501 + version: 13449ad91cb26cb47661c1b080790392170385fd subpackages: - clientcredentials - internal - name: google.golang.org/appengine - version: 3a452f9e00122ead39586d68ffdb9c6e1326af3c + version: d9a072cfa7b9736e44311ef77b3e09d804bfa599 subpackages: - internal - internal/base diff --git a/glide.yaml b/glide.yaml index 4b92a8d3..341a5543 100644 --- a/glide.yaml +++ b/glide.yaml @@ -1,16 +1,17 @@ package: github.com/ory/fosite import: - package: github.com/asaskevich/govalidator - version: ~6.0.0 + version: ~7.0.0 - package: github.com/dgrijalva/jwt-go - version: ~3.0.0 + version: ~3.1.0 - package: github.com/golang/mock + version: ~1.0.0 subpackages: - gomock -- package: github.com/oleiade/reflections - version: ~1.0.0 +- package: github.com/gtank/cryptopasta +- package: github.com/mohae/deepcopy - package: github.com/pborman/uuid - version: ~1.0.0 + version: ~1.1.0 - package: github.com/pkg/errors version: ~0.8.0 - package: golang.org/x/crypto @@ -18,14 +19,16 @@ import: - bcrypt testImport: - package: github.com/gorilla/mux - version: ~1.4.0 + version: ~1.5.0 +- package: github.com/oleiade/reflections + version: ~1.0.0 - package: github.com/parnurzeal/gorequest version: ~0.2.15 -- package: golang.org/x/oauth2 - subpackages: - - clientcredentials - package: github.com/stretchr/testify version: ~1.1.4 subpackages: - assert - require +- package: golang.org/x/oauth2 + subpackages: + - clientcredentials diff --git a/handler/oauth2/strategy_hmacsha_test.go b/handler/oauth2/strategy_hmacsha_test.go index a4773348..c7507519 100644 --- a/handler/oauth2/strategy_hmacsha_test.go +++ b/handler/oauth2/strategy_hmacsha_test.go @@ -11,7 +11,7 @@ import ( ) var hmacshaStrategy = HMACSHAStrategy{ - Enigma: &hmac.HMACStrategy{GlobalSecret: []byte("foobarfoobarfoobarfoobar")}, + Enigma: &hmac.HMACStrategy{GlobalSecret: []byte("foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobar")}, AccessTokenLifespan: time.Hour * 24, AuthorizeCodeLifespan: time.Hour * 24, } diff --git a/handler/openid/flow_hybrid_test.go b/handler/openid/flow_hybrid_test.go index a78c9e7d..f4405c19 100644 --- a/handler/openid/flow_hybrid_test.go +++ b/handler/openid/flow_hybrid_test.go @@ -23,7 +23,7 @@ var idStrategy = &DefaultStrategy{ var hmacStrategy = &oauth2.HMACSHAStrategy{ Enigma: &hmac.HMACStrategy{ - GlobalSecret: []byte("some-super-cool-secret-that-nobody-knows"), + GlobalSecret: []byte("some-super-cool-secret-that-nobody-knows-nobody-knows"), }, } diff --git a/integration/helper_setup_test.go b/integration/helper_setup_test.go index 741b1f09..7944e51c 100644 --- a/integration/helper_setup_test.go +++ b/integration/helper_setup_test.go @@ -75,7 +75,7 @@ func newOAuth2AppClient(ts *httptest.Server) *clientcredentials.Config { var hmacStrategy = &oauth2.HMACSHAStrategy{ Enigma: &hmac.HMACStrategy{ - GlobalSecret: []byte("some-super-cool-secret-that-nobody-knows"), + GlobalSecret: []byte("some-super-cool-secret-that-nobody-knows-nobody-knows"), }, AccessTokenLifespan: accessTokenLifespan, AuthorizeCodeLifespan: authCodeLifespan, diff --git a/integration/oidc_implicit_hybrid_test.go b/integration/oidc_implicit_hybrid_test.go index f51c8ae6..b00e669f 100644 --- a/integration/oidc_implicit_hybrid_test.go +++ b/integration/oidc_implicit_hybrid_test.go @@ -17,6 +17,7 @@ import ( "github.com/ory/fosite/handler/openid" "github.com/ory/fosite/internal" "github.com/ory/fosite/token/jwt" + "fmt" ) func TestOIDCImplicitFlow(t *testing.T) { @@ -28,7 +29,7 @@ func TestOIDCImplicitFlow(t *testing.T) { Headers: &jwt.Headers{}, }, } - f := compose.ComposeAllEnabled(new(compose.Config), fositeStore, []byte("some-secret-thats-random"), internal.MustRSAKey()) + f := compose.ComposeAllEnabled(new(compose.Config), fositeStore, []byte("some-secret-thats-random-some-secret-thats-random-"), internal.MustRSAKey()) ts := mockServer(t, f, session) defer ts.Close() @@ -94,60 +95,61 @@ func TestOIDCImplicitFlow(t *testing.T) { hasIdToken: true, }, } { - c.setup() - - var callbackURL *url.URL - authURL := strings.Replace(oauthClient.AuthCodeURL(state), "response_type=code", "response_type="+c.responseType, -1) + "&nonce=" + c.nonce - client := &http.Client{ - CheckRedirect: func(req *http.Request, via []*http.Request) error { - callbackURL = req.URL - return errors.New("Dont follow redirects") - }, - } - resp, err := client.Get(authURL) - require.NotNil(t, err, "(%d) %s", k, c.description) - - t.Logf("Response (%d): %s", k, callbackURL.String()) - fragment, err := url.ParseQuery(callbackURL.Fragment) - require.Nil(t, err, "(%d) %s", k, c.description) - - if c.hasToken { - assert.NotEmpty(t, fragment.Get("access_token"), "(%d) %s", k, c.description) - } else { - assert.Empty(t, fragment.Get("access_token"), "(%d) %s", k, c.description) - } - - if c.hasCode { - assert.NotEmpty(t, fragment.Get("code"), "(%d) %s", k, c.description) - } else { - assert.Empty(t, fragment.Get("code"), "(%d) %s", k, c.description) - } - - if c.hasIdToken { - assert.NotEmpty(t, fragment.Get("id_token"), "(%d) %s", k, c.description) - } else { - assert.Empty(t, fragment.Get("id_token"), "(%d) %s", k, c.description) - } - - if !c.hasToken { - continue - } - - expires, err := strconv.Atoi(fragment.Get("expires_in")) - require.Nil(t, err, "(%d) %s", k, c.description) - - token := &oauth2.Token{ - AccessToken: fragment.Get("access_token"), - TokenType: fragment.Get("token_type"), - RefreshToken: fragment.Get("refresh_token"), - Expiry: time.Now().Add(time.Duration(expires) * time.Second), - } - - httpClient := oauthClient.Client(oauth2.NoContext, token) - resp, err = httpClient.Get(ts.URL + "/info") - require.Nil(t, err, "(%d) %s", k, c.description) - assert.Equal(t, http.StatusNoContent, resp.StatusCode, "(%d) %s", k, c.description) - t.Logf("Passed test case (%d) %s", k, c.description) - + t.Run(fmt.Sprintf("case=%d/description=%s", k, c.description), func(t *testing.T) { + c.setup() + + var callbackURL *url.URL + authURL := strings.Replace(oauthClient.AuthCodeURL(state), "response_type=code", "response_type="+c.responseType, -1) + "&nonce=" + c.nonce + client := &http.Client{ + CheckRedirect: func(req *http.Request, via []*http.Request) error { + callbackURL = req.URL + return errors.New("Dont follow redirects") + }, + } + resp, err := client.Get(authURL) + require.Error(t, err) + + t.Logf("Response (%d): %s", k, callbackURL.String()) + fragment, err := url.ParseQuery(callbackURL.Fragment) + require.NoError(t, err) + + if c.hasToken { + assert.NotEmpty(t, fragment.Get("access_token")) + } else { + assert.Empty(t, fragment.Get("access_token")) + } + + if c.hasCode { + assert.NotEmpty(t, fragment.Get("code")) + } else { + assert.Empty(t, fragment.Get("code")) + } + + if c.hasIdToken { + assert.NotEmpty(t, fragment.Get("id_token")) + } else { + assert.Empty(t, fragment.Get("id_token")) + } + + if !c.hasToken { + return + } + + expires, err := strconv.Atoi(fragment.Get("expires_in")) + require.NoError(t, err) + + token := &oauth2.Token{ + AccessToken: fragment.Get("access_token"), + TokenType: fragment.Get("token_type"), + RefreshToken: fragment.Get("refresh_token"), + Expiry: time.Now().Add(time.Duration(expires) * time.Second), + } + + httpClient := oauthClient.Client(oauth2.NoContext, token) + resp, err = httpClient.Get(ts.URL + "/info") + require.NoError(t, err) + assert.Equal(t, http.StatusNoContent, resp.StatusCode) + t.Logf("Passed test case (%d) %s", k, c.description) + }) } } diff --git a/token/hmac/hmacsha.go b/token/hmac/hmacsha.go index 7f44565e..aabadee5 100644 --- a/token/hmac/hmacsha.go +++ b/token/hmac/hmacsha.go @@ -3,20 +3,20 @@ package hmac import ( - "crypto/hmac" - "crypto/sha256" "encoding/base64" "fmt" "strings" - "github.com/ory/fosite" "github.com/pkg/errors" + "sync" + "github.com/gtank/cryptopasta" ) // HMACStrategy is responsible for generating and validating challenges. type HMACStrategy struct { AuthCodeEntropy int GlobalSecret []byte + sync.Mutex } const ( @@ -32,10 +32,16 @@ var b64 = base64.URLEncoding.WithPadding(base64.NoPadding) // Generate generates a token and a matching signature or returns an error. // This method implements rfc6819 Section 5.1.4.2.2: Use High Entropy for Secrets. func (c *HMACStrategy) Generate() (string, string, error) { - if len(c.GlobalSecret) < minimumSecretLength/2 { - return "", "", errors.New("Secret is not strong enough") + c.Lock() + defer c.Unlock() + + if len(c.GlobalSecret) < minimumSecretLength { + return "", "", errors.Errorf("Secret for signing HMAC-SHA256 is expected to be 32 byte long, got %d byte", len(c.GlobalSecret)) } + var signingKey [32]byte + copy(signingKey[:], c.GlobalSecret) + if c.AuthCodeEntropy < minimumEntropy { c.AuthCodeEntropy = minimumEntropy } @@ -47,59 +53,49 @@ func (c *HMACStrategy) Generate() (string, string, error) { // constructed from a cryptographically strong random or pseudo-random // number sequence (see [RFC4086] for best current practice) generated // by the authorization server. - key, err := RandomBytes(c.AuthCodeEntropy) + tokenKey, err := RandomBytes(c.AuthCodeEntropy) if err != nil { return "", "", errors.WithStack(err) } - if len(key) < c.AuthCodeEntropy { - return "", "", errors.New("Could not read enough random data for key generation") - } - - useSecret := append([]byte{}, c.GlobalSecret...) - mac := hmac.New(sha256.New, useSecret) - _, err = mac.Write(key) - if err != nil { - return "", "", errors.WithStack(err) - } + signature := cryptopasta.GenerateHMAC(tokenKey, &signingKey) - signature := mac.Sum([]byte{}) encodedSignature := b64.EncodeToString(signature) - encodedToken := fmt.Sprintf("%s.%s", b64.EncodeToString(key), encodedSignature) + encodedToken := fmt.Sprintf("%s.%s", b64.EncodeToString(tokenKey), encodedSignature) return encodedToken, encodedSignature, nil } // Validate validates a token and returns its signature or an error if the token is not valid. func (c *HMACStrategy) Validate(token string) error { + if len(c.GlobalSecret) < minimumSecretLength { + return errors.Errorf("Secret for signing HMAC-SHA256 is expected to be 32 byte long, got %d byte", len(c.GlobalSecret)) + } + + var signingKey [32]byte + copy(signingKey[:], c.GlobalSecret) + split := strings.Split(token, ".") if len(split) != 2 { return errors.WithStack(fosite.ErrInvalidTokenFormat) } - key := split[0] - signature := split[1] - if key == "" || signature == "" { + tokenKey := split[0] + tokenSignature := split[1] + if tokenKey == "" || tokenSignature == "" { return errors.WithStack(fosite.ErrInvalidTokenFormat) } - decodedSignature, err := b64.DecodeString(signature) - if err != nil { - return errors.WithStack(err) - } - - decodedKey, err := b64.DecodeString(key) + decodedTokenSignature, err := b64.DecodeString(tokenSignature) if err != nil { return errors.WithStack(err) } - useSecret := append([]byte{}, c.GlobalSecret...) - mac := hmac.New(sha256.New, useSecret) - _, err = mac.Write(decodedKey) + decodedTokenKey, err := b64.DecodeString(tokenKey) if err != nil { return errors.WithStack(err) } - if !hmac.Equal(decodedSignature, mac.Sum([]byte{})) { + if !cryptopasta.CheckHMAC(decodedTokenKey, decodedTokenSignature, &signingKey) { // Hash is invalid return errors.WithStack(fosite.ErrTokenSignatureMismatch) } diff --git a/token/hmac/hmacsha_test.go b/token/hmac/hmacsha_test.go index 12e88ca1..aef6cf01 100644 --- a/token/hmac/hmacsha_test.go +++ b/token/hmac/hmacsha_test.go @@ -17,7 +17,7 @@ func TestGenerateFailsWithShortCredentials(t *testing.T) { func TestGenerate(t *testing.T) { cg := HMACStrategy{ - GlobalSecret: []byte("12345678901234567890"), + GlobalSecret: []byte("1234567890123456789012345678901234567890"), } token, signature, err := cg.Generate() @@ -40,7 +40,7 @@ func TestGenerate(t *testing.T) { func TestValidateSignatureRejects(t *testing.T) { var err error cg := HMACStrategy{ - GlobalSecret: []byte("12345678901234567890"), + GlobalSecret: []byte("1234567890123456789012345678901234567890"), } for k, c := range []string{ "", From 7fe1f946af7b4921da008f245da84b85ea3f26d0 Mon Sep 17 00:00:00 2001 From: arekkas Date: Wed, 25 Oct 2017 11:56:45 +0200 Subject: [PATCH 03/35] tests: replace nil checks with Error/NoError --- authorize_helper_test.go | 2 +- equalKeys_test.go | 16 +++--- handler/oauth2/strategy_hmacsha_test.go | 55 ++++++++++--------- handler/oauth2/strategy_jwt_test.go | 27 +++++---- handler/openid/helper_test.go | 4 +- hash_bcrypt_test.go | 10 ++-- integration/authorize_code_grant_test.go | 30 +++++----- integration/authorize_implicit_grant_test.go | 58 ++++++++++---------- integration/helper_setup_test.go | 2 +- integration/introspect_token_test.go | 54 +++++++++--------- integration/oidc_explicit_test.go | 31 ++++++----- integration/refresh_token_grant_test.go | 4 +- integration/revoke_token_test.go | 2 +- token/hmac/bytes_test.go | 4 +- token/hmac/hmacsha_test.go | 10 ++-- token/jwt/jwt_test.go | 20 +++---- 16 files changed, 173 insertions(+), 156 deletions(-) diff --git a/authorize_helper_test.go b/authorize_helper_test.go index 7d48216d..c2e26035 100644 --- a/authorize_helper_test.go +++ b/authorize_helper_test.go @@ -156,7 +156,7 @@ func TestIsRedirectURISecure(t *testing.T) { {u: "wta://auth", err: false}, } { uu, err := url.Parse(c.u) - require.Nil(t, err) + require.NoError(t, err) assert.Equal(t, !c.err, IsRedirectURISecure(uu), "case %d", d) } } diff --git a/equalKeys_test.go b/equalKeys_test.go index 112a93fb..dbdb8878 100644 --- a/equalKeys_test.go +++ b/equalKeys_test.go @@ -26,9 +26,9 @@ func AssertObjectKeysEqual(t *testing.T, a, b interface{}, keys ...string) { assert.True(t, len(keys) > 0, "No keys provided.") for _, k := range keys { c, err := reflections.GetField(a, k) - assert.Nil(t, err) + assert.NoError(t, err) d, err := reflections.GetField(b, k) - assert.Nil(t, err) + assert.NoError(t, err) assert.Equal(t, c, d, "%s", k) } } @@ -37,9 +37,9 @@ func AssertObjectKeysNotEqual(t *testing.T, a, b interface{}, keys ...string) { assert.True(t, len(keys) > 0, "No keys provided.") for _, k := range keys { c, err := reflections.GetField(a, k) - assert.Nil(t, err) + assert.NoError(t, err) d, err := reflections.GetField(b, k) - assert.Nil(t, err) + assert.NoError(t, err) assert.NotEqual(t, c, d, "%s", k) } } @@ -48,9 +48,9 @@ func RequireObjectKeysEqual(t *testing.T, a, b interface{}, keys ...string) { assert.True(t, len(keys) > 0, "No keys provided.") for _, k := range keys { c, err := reflections.GetField(a, k) - assert.Nil(t, err) + assert.NoError(t, err) d, err := reflections.GetField(b, k) - assert.Nil(t, err) + assert.NoError(t, err) require.Equal(t, c, d, "%s", k) } } @@ -58,9 +58,9 @@ func RequireObjectKeysNotEqual(t *testing.T, a, b interface{}, keys ...string) { assert.True(t, len(keys) > 0, "No keys provided.") for _, k := range keys { c, err := reflections.GetField(a, k) - assert.Nil(t, err) + assert.NoError(t, err) d, err := reflections.GetField(b, k) - assert.Nil(t, err) + assert.NoError(t, err) require.NotEqual(t, c, d, "%s", k) } } diff --git a/handler/oauth2/strategy_hmacsha_test.go b/handler/oauth2/strategy_hmacsha_test.go index c7507519..3f22864d 100644 --- a/handler/oauth2/strategy_hmacsha_test.go +++ b/handler/oauth2/strategy_hmacsha_test.go @@ -8,6 +8,7 @@ import ( "github.com/ory/fosite" "github.com/ory/fosite/token/hmac" "github.com/stretchr/testify/assert" + "fmt" ) var hmacshaStrategy = HMACSHAStrategy{ @@ -41,7 +42,7 @@ var hmacValidCase = fosite.Request{ } func TestHMACAccessToken(t *testing.T) { - for _, c := range []struct { + for k, c := range []struct { r fosite.Request pass bool }{ @@ -54,29 +55,31 @@ func TestHMACAccessToken(t *testing.T) { pass: false, }, } { - token, signature, err := hmacshaStrategy.GenerateAccessToken(nil, &c.r) - assert.Nil(t, err, "%s", err) - assert.Equal(t, strings.Split(token, ".")[1], signature) + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + token, signature, err := hmacshaStrategy.GenerateAccessToken(nil, &c.r) + assert.NoError(t, err) + assert.Equal(t, strings.Split(token, ".")[1], signature) - err = hmacshaStrategy.ValidateAccessToken(nil, &c.r, token) - if c.pass { - assert.Nil(t, err, "%s", err) - validate := hmacshaStrategy.Enigma.Signature(token) - assert.Equal(t, signature, validate) - } else { - assert.NotNil(t, err, "%s", err) - } + err = hmacshaStrategy.ValidateAccessToken(nil, &c.r, token) + if c.pass { + assert.NoError(t, err) + validate := hmacshaStrategy.Enigma.Signature(token) + assert.Equal(t, signature, validate) + } else { + assert.Error(t, err) + } + }) } } func TestHMACRefreshToken(t *testing.T) { token, signature, err := hmacshaStrategy.GenerateRefreshToken(nil, &hmacValidCase) - assert.Nil(t, err, "%s", err) + assert.NoError(t, err) assert.Equal(t, strings.Split(token, ".")[1], signature) validate := hmacshaStrategy.Enigma.Signature(token) err = hmacshaStrategy.ValidateRefreshToken(nil, &hmacValidCase, token) - assert.Nil(t, err, "%s", err) + assert.NoError(t, err) assert.Equal(t, signature, validate) } @@ -94,17 +97,19 @@ func TestHMACAuthorizeCode(t *testing.T) { pass: false, }, } { - token, signature, err := hmacshaStrategy.GenerateAuthorizeCode(nil, &c.r) - assert.Nil(t, err, "%s", err) - assert.Equal(t, strings.Split(token, ".")[1], signature) + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + token, signature, err := hmacshaStrategy.GenerateAuthorizeCode(nil, &c.r) + assert.NoError(t, err) + assert.Equal(t, strings.Split(token, ".")[1], signature) - err = hmacshaStrategy.ValidateAuthorizeCode(nil, &c.r, token) - if c.pass { - assert.Nil(t, err, "%d: %s", k, err) - validate := hmacshaStrategy.Enigma.Signature(token) - assert.Equal(t, signature, validate) - } else { - assert.NotNil(t, err, "%d: %s", k, err) - } + err = hmacshaStrategy.ValidateAuthorizeCode(nil, &c.r, token) + if c.pass { + assert.NoError(t, err) + validate := hmacshaStrategy.Enigma.Signature(token) + assert.Equal(t, signature, validate) + } else { + assert.Error(t, err) + } + }) } } diff --git a/handler/oauth2/strategy_jwt_test.go b/handler/oauth2/strategy_jwt_test.go index 7755219b..9108b014 100644 --- a/handler/oauth2/strategy_jwt_test.go +++ b/handler/oauth2/strategy_jwt_test.go @@ -9,6 +9,7 @@ import ( "github.com/ory/fosite/internal" "github.com/ory/fosite/token/jwt" "github.com/stretchr/testify/assert" + "fmt" ) var j = &RS256JWTStrategy{ @@ -72,7 +73,7 @@ var jwtExpiredCase = func(tokenType fosite.TokenType) *fosite.Request { } func TestAccessToken(t *testing.T) { - for _, c := range []struct { + for k, c := range []struct { r *fosite.Request pass bool }{ @@ -85,17 +86,19 @@ func TestAccessToken(t *testing.T) { pass: false, }, } { - token, signature, err := j.GenerateAccessToken(nil, c.r) - assert.Nil(t, err, "%s", err) - assert.Equal(t, strings.Split(token, ".")[2], signature) + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + token, signature, err := j.GenerateAccessToken(nil, c.r) + assert.NoError(t, err) + assert.Equal(t, strings.Split(token, ".")[2], signature) - validate := j.signature(token) - err = j.ValidateAccessToken(nil, c.r, token) - if c.pass { - assert.Nil(t, err, "%s", err) - assert.Equal(t, signature, validate) - } else { - assert.NotNil(t, err, "%s", err) - } + validate := j.signature(token) + err = j.ValidateAccessToken(nil, c.r, token) + if c.pass { + assert.NoError(t, err) + assert.Equal(t, signature, validate) + } else { + assert.Error(t, err) + } + }) } } diff --git a/handler/openid/helper_test.go b/handler/openid/helper_test.go index a14e49d7..fdc36d57 100644 --- a/handler/openid/helper_test.go +++ b/handler/openid/helper_test.go @@ -80,7 +80,7 @@ func TestIssueExplicitToken(t *testing.T) { resp.EXPECT().SetExtra("id_token", gomock.Any()) h := &IDTokenHandleHelper{IDTokenStrategy: strat} err := h.IssueExplicitIDToken(nil, ar, resp) - assert.Nil(t, err, "%s", err) + assert.NoError(t, err) } func TestIssueImplicitToken(t *testing.T) { @@ -97,5 +97,5 @@ func TestIssueImplicitToken(t *testing.T) { resp.EXPECT().AddFragment("id_token", gomock.Any()) h := &IDTokenHandleHelper{IDTokenStrategy: strat} err := h.IssueImplicitIDToken(nil, ar, resp) - assert.Nil(t, err, "%s", err) + assert.NoError(t, err) } diff --git a/hash_bcrypt_test.go b/hash_bcrypt_test.go index 49faecef..c931ad5b 100644 --- a/hash_bcrypt_test.go +++ b/hash_bcrypt_test.go @@ -13,7 +13,7 @@ func TestHash(t *testing.T) { } password := []byte("foo") hash, err := h.Hash(password) - assert.Nil(t, err) + assert.NoError(t, err) assert.NotNil(t, hash) assert.NotEqual(t, hash, password) } @@ -24,10 +24,10 @@ func TestCompareEquals(t *testing.T) { } password := []byte("foo") hash, err := h.Hash(password) - assert.Nil(t, err) + assert.NoError(t, err) assert.NotNil(t, hash) err = h.Compare(hash, password) - assert.Nil(t, err) + assert.NoError(t, err) } func TestCompareDifferent(t *testing.T) { @@ -36,8 +36,8 @@ func TestCompareDifferent(t *testing.T) { } password := []byte("foo") hash, err := h.Hash(password) - assert.Nil(t, err) + assert.NoError(t, err) assert.NotNil(t, hash) err = h.Compare(hash, []byte(uuid.NewRandom())) - assert.NotNil(t, err) + assert.Error(t, err) } diff --git a/integration/authorize_code_grant_test.go b/integration/authorize_code_grant_test.go index 14d6ac9a..4c68daa8 100644 --- a/integration/authorize_code_grant_test.go +++ b/integration/authorize_code_grant_test.go @@ -11,6 +11,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" goauth "golang.org/x/oauth2" + "fmt" ) func TestAuthorizeCodeFlow(t *testing.T) { @@ -44,22 +45,23 @@ func runAuthorizeCodeGrantTest(t *testing.T, strategy interface{}) { authStatusCode: http.StatusOK, }, } { - c.setup() + t.Run(fmt.Sprintf("case=%d/description=%s", k, c.description), func(t *testing.T) { + c.setup() - resp, err := http.Get(oauthClient.AuthCodeURL(state)) - require.Nil(t, err) - require.Equal(t, c.authStatusCode, resp.StatusCode, "(%d) %s", k, c.description) + resp, err := http.Get(oauthClient.AuthCodeURL(state)) + require.NoError(t, err) + require.Equal(t, c.authStatusCode, resp.StatusCode) - if resp.StatusCode == http.StatusOK { - token, err := oauthClient.Exchange(goauth.NoContext, resp.Request.URL.Query().Get("code")) - require.Nil(t, err, "(%d) %s", k, c.description) - require.NotEmpty(t, token.AccessToken, "(%d) %s", k, c.description) + if resp.StatusCode == http.StatusOK { + token, err := oauthClient.Exchange(goauth.NoContext, resp.Request.URL.Query().Get("code")) + require.NoError(t, err) + require.NotEmpty(t, token.AccessToken) - httpClient := oauthClient.Client(goauth.NoContext, token) - resp, err := httpClient.Get(ts.URL + "/info") - require.Nil(t, err, "(%d) %s", k, c.description) - assert.Equal(t, http.StatusNoContent, resp.StatusCode, "(%d) %s", k, c.description) - } - t.Logf("Passed test case (%d) %s", k, c.description) + httpClient := oauthClient.Client(goauth.NoContext, token) + resp, err := httpClient.Get(ts.URL + "/info") + require.NoError(t, err) + assert.Equal(t, http.StatusNoContent, resp.StatusCode) + } + }) } } diff --git a/integration/authorize_implicit_grant_test.go b/integration/authorize_implicit_grant_test.go index fb6adf08..38583131 100644 --- a/integration/authorize_implicit_grant_test.go +++ b/integration/authorize_implicit_grant_test.go @@ -15,6 +15,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" goauth "golang.org/x/oauth2" + "fmt" ) func TestAuthorizeImplicitFlow(t *testing.T) { @@ -47,36 +48,37 @@ func runTestAuthorizeImplicitGrant(t *testing.T, strategy interface{}) { authStatusCode: http.StatusOK, }, } { - c.setup() + t.Run(fmt.Sprintf("case=%d/description=%s", k, c.description), func(t *testing.T) { + c.setup() - var callbackURL *url.URL - authURL := strings.Replace(oauthClient.AuthCodeURL(state), "response_type=code", "response_type=token", -1) - client := &http.Client{ - CheckRedirect: func(req *http.Request, via []*http.Request) error { - callbackURL = req.URL - return errors.New("Dont follow redirects") - }, - } - resp, err := client.Get(authURL) - require.NotNil(t, err) - - if resp.StatusCode == http.StatusOK { - fragment, err := url.ParseQuery(callbackURL.Fragment) - require.Nil(t, err) - expires, err := strconv.Atoi(fragment.Get("expires_in")) - require.Nil(t, err) - token := &goauth.Token{ - AccessToken: fragment.Get("access_token"), - TokenType: fragment.Get("token_type"), - RefreshToken: fragment.Get("refresh_token"), - Expiry: time.Now().Add(time.Duration(expires) * time.Second), + var callbackURL *url.URL + authURL := strings.Replace(oauthClient.AuthCodeURL(state), "response_type=code", "response_type=token", -1) + client := &http.Client{ + CheckRedirect: func(req *http.Request, via []*http.Request) error { + callbackURL = req.URL + return errors.New("Dont follow redirects") + }, } + resp, err := client.Get(authURL) + require.Error(t, err) - httpClient := oauthClient.Client(goauth.NoContext, token) - resp, err := httpClient.Get(ts.URL + "/info") - require.Nil(t, err, "(%d) %s", k, c.description) - assert.Equal(t, http.StatusNoContent, resp.StatusCode, "(%d) %s", k, c.description) - } - t.Logf("Passed test case (%d) %s", k, c.description) + if resp.StatusCode == http.StatusOK { + fragment, err := url.ParseQuery(callbackURL.Fragment) + require.NoError(t, err) + expires, err := strconv.Atoi(fragment.Get("expires_in")) + require.NoError(t, err) + token := &goauth.Token{ + AccessToken: fragment.Get("access_token"), + TokenType: fragment.Get("token_type"), + RefreshToken: fragment.Get("refresh_token"), + Expiry: time.Now().Add(time.Duration(expires) * time.Second), + } + + httpClient := oauthClient.Client(goauth.NoContext, token) + resp, err := httpClient.Get(ts.URL + "/info") + require.NoError(t, err) + assert.Equal(t, http.StatusNoContent, resp.StatusCode) + } + }) } } diff --git a/integration/helper_setup_test.go b/integration/helper_setup_test.go index 7944e51c..741b1f09 100644 --- a/integration/helper_setup_test.go +++ b/integration/helper_setup_test.go @@ -75,7 +75,7 @@ func newOAuth2AppClient(ts *httptest.Server) *clientcredentials.Config { var hmacStrategy = &oauth2.HMACSHAStrategy{ Enigma: &hmac.HMACStrategy{ - GlobalSecret: []byte("some-super-cool-secret-that-nobody-knows-nobody-knows"), + GlobalSecret: []byte("some-super-cool-secret-that-nobody-knows"), }, AccessTokenLifespan: accessTokenLifespan, AuthorizeCodeLifespan: authCodeLifespan, diff --git a/integration/introspect_token_test.go b/integration/introspect_token_test.go index 266f106d..b2c1301e 100644 --- a/integration/introspect_token_test.go +++ b/integration/introspect_token_test.go @@ -12,6 +12,7 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" goauth "golang.org/x/oauth2" + "fmt" ) func TestIntrospectToken(t *testing.T) { @@ -48,11 +49,11 @@ func runIntrospectTokenTest(t *testing.T, strategy oauth2.AccessTokenStrategy, i oauthClient := newOAuth2AppClient(ts) a, err := oauthClient.Token(goauth.NoContext) - require.Nil(t, err) + require.NoError(t, err) b, err := oauthClient.Token(goauth.NoContext) - require.Nil(t, err) + require.NoError(t, err) - for _, c := range []struct { + for k, c := range []struct { prepare func(*gorequest.SuperAgent) *gorequest.SuperAgent isActive bool scopes string @@ -93,28 +94,31 @@ func runIntrospectTokenTest(t *testing.T, strategy oauth2.AccessTokenStrategy, i scopes: "", }, } { - res := struct { - Active bool `json:"active"` - ClientId string `json:"client_id"` - Scope string `json:"scope"` - ExpiresAt float64 `json:"exp"` - IssuedAt float64 `json:"iat"` - }{} - s := gorequest.New() - s = s.Post(ts.URL + "/introspect"). - Type("form"). - SendStruct(map[string]string{"token": b.AccessToken, "scope": c.scopes}) - _, bytes, errs := c.prepare(s).End() + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + res := struct { + Active bool `json:"active"` + ClientId string `json:"client_id"` + Scope string `json:"scope"` + ExpiresAt float64 `json:"exp"` + IssuedAt float64 `json:"iat"` + }{} + s := gorequest.New() + s = s.Post(ts.URL + "/introspect"). + Type("form"). + SendStruct(map[string]string{"token": b.AccessToken, "scope": c.scopes}) + _, bytes, errs := c.prepare(s).End() + + assert.Nil(t, json.Unmarshal([]byte(bytes), &res)) + t.Logf("Got answer: %s", bytes) - assert.Nil(t, json.Unmarshal([]byte(bytes), &res)) - t.Logf("Got answer: %s", bytes) - assert.Len(t, errs, 0) - assert.Equal(t, c.isActive, res.Active) - if c.isActive { - assert.Equal(t, "fosite", res.Scope) - assert.True(t, res.ExpiresAt > 0) - assert.True(t, res.IssuedAt > 0) - assert.True(t, res.IssuedAt < res.ExpiresAt) - } + assert.Len(t, errs, 0) + assert.Equal(t, c.isActive, res.Active) + if c.isActive { + assert.Equal(t, "fosite", res.Scope) + assert.True(t, res.ExpiresAt > 0) + assert.True(t, res.IssuedAt > 0) + assert.True(t, res.IssuedAt < res.ExpiresAt) + } + }) } } diff --git a/integration/oidc_explicit_test.go b/integration/oidc_explicit_test.go index 1baaf7b1..d62bcb00 100644 --- a/integration/oidc_explicit_test.go +++ b/integration/oidc_explicit_test.go @@ -23,7 +23,7 @@ func TestOpenIDConnectExplicitFlow(t *testing.T) { Headers: &jwt.Headers{}, }, } - f := compose.ComposeAllEnabled(new(compose.Config), fositeStore, []byte("some-secret-thats-random"), internal.MustRSAKey()) + f := compose.ComposeAllEnabled(new(compose.Config), fositeStore, []byte("some-secret-thats-random-some-secret-thats-random-"), internal.MustRSAKey()) ts := mockServer(t, f, session) defer ts.Close() @@ -45,19 +45,20 @@ func TestOpenIDConnectExplicitFlow(t *testing.T) { authStatusCode: http.StatusOK, }, } { - c.setup() - - resp, err := http.Get(oauthClient.AuthCodeURL(state) + "&nonce=1234567890") - require.Nil(t, err) - require.Equal(t, c.authStatusCode, resp.StatusCode, "(%d) %s", k, c.description) - - if resp.StatusCode == http.StatusOK { - token, err := oauthClient.Exchange(oauth2.NoContext, resp.Request.URL.Query().Get("code")) - fmt.Printf("after exchange: %s\n\n", fositeStore.AuthorizeCodes) - require.Nil(t, err, "(%d) %s", k, c.description) - require.NotEmpty(t, token.AccessToken, "(%d) %s", k, c.description) - require.NotEmpty(t, token.Extra("id_token"), "(%d) %s", k, c.description) - } - t.Logf("Passed test case (%d) %s", k, c.description) + t.Run(fmt.Sprintf("case=%d/description=%s", k, c.description), func(t *testing.T) { + c.setup() + + resp, err := http.Get(oauthClient.AuthCodeURL(state) + "&nonce=1234567890") + require.NoError(t, err) + require.Equal(t, c.authStatusCode, resp.StatusCode) + + if resp.StatusCode == http.StatusOK { + token, err := oauthClient.Exchange(oauth2.NoContext, resp.Request.URL.Query().Get("code")) + fmt.Printf("after exchange: %s\n\n", fositeStore.AuthorizeCodes) + require.NoError(t, err) + require.NotEmpty(t, token.AccessToken) + require.NotEmpty(t, token.Extra("id_token")) + } + }) } } diff --git a/integration/refresh_token_grant_test.go b/integration/refresh_token_grant_test.go index 06a9e458..55ae85f2 100644 --- a/integration/refresh_token_grant_test.go +++ b/integration/refresh_token_grant_test.go @@ -23,7 +23,7 @@ func TestRefreshTokenFlow(t *testing.T) { Headers: &jwt.Headers{}, }, } - f := compose.ComposeAllEnabled(new(compose.Config), fositeStore, []byte("some-secret-thats-random"), internal.MustRSAKey()) + f := compose.ComposeAllEnabled(new(compose.Config), fositeStore, []byte("some-secret-thats-random-some-secret-thats-random-"), internal.MustRSAKey()) ts := mockServer(t, f, session) defer ts.Close() @@ -92,7 +92,7 @@ func TestRefreshTokenFlow(t *testing.T) { require.NoError(t, err) c.check(token, refreshed) } else { - require.NotNil(t, err) + require.Error(t, err) } }) } diff --git a/integration/revoke_token_test.go b/integration/revoke_token_test.go index 03980892..c026f0b8 100644 --- a/integration/revoke_token_test.go +++ b/integration/revoke_token_test.go @@ -29,7 +29,7 @@ func runRevokeTokenTest(t *testing.T, strategy oauth2.AccessTokenStrategy) { oauthClient := newOAuth2AppClient(ts) token, err := oauthClient.Token(goauth.NoContext) - assert.Nil(t, err) + assert.NoError(t, err) resp, _, errs := gorequest.New().Post(ts.URL+"/revoke"). SetBasicAuth(oauthClient.ClientID, oauthClient.ClientSecret). diff --git a/token/hmac/bytes_test.go b/token/hmac/bytes_test.go index e19e59b7..6d440e22 100644 --- a/token/hmac/bytes_test.go +++ b/token/hmac/bytes_test.go @@ -8,7 +8,7 @@ import ( func TestRandomBytes(t *testing.T) { bytes, err := RandomBytes(128) - assert.Nil(t, err, "%s", err) + assert.NoError(t, err) assert.Len(t, bytes, 128) } @@ -17,7 +17,7 @@ func TestPseudoRandomness(t *testing.T) { results := map[string]bool{} for i := 0; i < runs; i++ { bytes, err := RandomBytes(128) - assert.Nil(t, err, "%s", err) + assert.NoError(t, err) _, ok := results[string(bytes)] assert.False(t, ok) diff --git a/token/hmac/hmacsha_test.go b/token/hmac/hmacsha_test.go index aef6cf01..154aa71c 100644 --- a/token/hmac/hmacsha_test.go +++ b/token/hmac/hmacsha_test.go @@ -10,7 +10,7 @@ import ( func TestGenerateFailsWithShortCredentials(t *testing.T) { cg := HMACStrategy{GlobalSecret: []byte("foo")} challenge, signature, err := cg.Generate() - require.NotNil(t, err, "%s", err) + require.Error(t, err) require.Empty(t, challenge) require.Empty(t, signature) } @@ -21,20 +21,20 @@ func TestGenerate(t *testing.T) { } token, signature, err := cg.Generate() - require.Nil(t, err, "%s", err) + require.NoError(t, err) require.NotEmpty(t, token) require.NotEmpty(t, signature) t.Logf("Token: %s\n Signature: %s", token, signature) err = cg.Validate(token) - require.Nil(t, err, "%s", err) + require.NoError(t, err) validateSignature := cg.Signature(token) assert.Equal(t, signature, validateSignature) cg.GlobalSecret = []byte("baz") err = cg.Validate(token) - require.NotNil(t, err, "%s", err) + require.Error(t, err) } func TestValidateSignatureRejects(t *testing.T) { @@ -50,7 +50,7 @@ func TestValidateSignatureRejects(t *testing.T) { ".foo", } { err = cg.Validate(c) - assert.NotNil(t, err, "%s", err) + assert.Error(t, err) t.Logf("Passed test case %d", k) } } diff --git a/token/jwt/jwt_test.go b/token/jwt/jwt_test.go index f3feda08..97414e5a 100644 --- a/token/jwt/jwt_test.go +++ b/token/jwt/jwt_test.go @@ -23,7 +23,7 @@ func TestHash(t *testing.T) { } in := []byte("foo") out, err := j.Hash(in) - assert.Nil(t, err) + assert.NoError(t, err) assert.NotEqual(t, in, out) } @@ -64,19 +64,19 @@ func TestGenerateJWT(t *testing.T) { } token, sig, err := j.Generate(claims.ToMapClaims(), header) - require.Nil(t, err, "%s", err) + require.NoError(t, err) require.NotNil(t, token) sig, err = j.Validate(token) - require.Nil(t, err, "%s", err) + require.NoError(t, err) sig, err = j.Validate(token + "." + "0123456789") - require.NotNil(t, err, "%s", err) + require.Error(t, err) partToken := strings.Split(token, ".")[2] sig, err = j.Validate(partToken) - require.NotNil(t, err, "%s", err) + require.Error(t, err) // Reset private key j.PrivateKey = internal.MustRSAKey() @@ -86,23 +86,23 @@ func TestGenerateJWT(t *testing.T) { ExpiresAt: time.Now().Add(-time.Hour), } token, sig, err = j.Generate(claims.ToMapClaims(), header) - require.Nil(t, err, "%s", err) + require.NoError(t, err) require.NotNil(t, token) //t.Logf("%s.%s", token, sig) sig, err = j.Validate(token) - require.NotNil(t, err, "%s", err) + require.Error(t, err) // Lets validate the nbf claim claims = &JWTClaims{ NotBefore: time.Now().Add(time.Hour), } token, sig, err = j.Generate(claims.ToMapClaims(), header) - require.Nil(t, err, "%s", err) + require.NoError(t, err) require.NotNil(t, token) //t.Logf("%s.%s", token, sig) sig, err = j.Validate(token) - require.NotNil(t, err, "%s", err) + require.Error(t, err) require.Empty(t, sig, "%s", err) } @@ -120,7 +120,7 @@ func TestValidateSignatureRejectsJWT(t *testing.T) { ".foo", } { _, err = j.Validate(c) - assert.NotNil(t, err, "%s", err) + assert.Error(t, err) t.Logf("Passed test case %d", k) } } From 92c73aee93b5d1fe2acf3395b495caf912453368 Mon Sep 17 00:00:00 2001 From: arekkas Date: Wed, 25 Oct 2017 11:58:02 +0200 Subject: [PATCH 04/35] scripts: add format helper scripts --- scripts/.gitattributes | 1 + scripts/run-format.sh | 8 ++++++++ scripts/test-format.sh | 11 +++++++++++ 3 files changed, 20 insertions(+) create mode 100644 scripts/.gitattributes create mode 100755 scripts/run-format.sh create mode 100755 scripts/test-format.sh diff --git a/scripts/.gitattributes b/scripts/.gitattributes new file mode 100644 index 00000000..dfdb8b77 --- /dev/null +++ b/scripts/.gitattributes @@ -0,0 +1 @@ +*.sh text eol=lf diff --git a/scripts/run-format.sh b/scripts/run-format.sh new file mode 100755 index 00000000..97138104 --- /dev/null +++ b/scripts/run-format.sh @@ -0,0 +1,8 @@ +#!/bin/bash + +set -euo pipefail + +cd "$( dirname "${BASH_SOURCE[0]}" )/.." + +goimports -w $(go list -f {{.Dir}} ./... | grep -v vendor | grep -v oathkeeper$) +goimports -w *.go diff --git a/scripts/test-format.sh b/scripts/test-format.sh new file mode 100755 index 00000000..17799995 --- /dev/null +++ b/scripts/test-format.sh @@ -0,0 +1,11 @@ +#!/bin/bash + +set -euo pipefail + +cd "$( dirname "${BASH_SOURCE[0]}" )/.." + +toformat=$(goimports -l $(go list -f {{.Dir}} ./... | grep -v vendor | grep -v 'oathkeeper$')) +[ -z "$toformat" ] && echo "All files are formatted correctly" +[ -n "$toformat" ] && echo "Please use \`goimports\` to format the following files:" && echo $toformat && exit 1 + +exit 0 From c87defe18676b36d880fa834c10e2cbd5464e061 Mon Sep 17 00:00:00 2001 From: arekkas Date: Wed, 25 Oct 2017 12:01:25 +0200 Subject: [PATCH 05/35] all: format files with goimports --- handler/oauth2/strategy_hmacsha_test.go | 5 +++-- handler/oauth2/strategy_jwt_test.go | 3 ++- integration/authorize_code_grant_test.go | 3 ++- integration/authorize_implicit_grant_test.go | 3 ++- integration/introspect_token_test.go | 3 ++- integration/oidc_implicit_hybrid_test.go | 3 ++- scope_strategy_test.go | 3 ++- token/hmac/hmacsha.go | 5 +++-- 8 files changed, 18 insertions(+), 10 deletions(-) diff --git a/handler/oauth2/strategy_hmacsha_test.go b/handler/oauth2/strategy_hmacsha_test.go index 3f22864d..d287a5d9 100644 --- a/handler/oauth2/strategy_hmacsha_test.go +++ b/handler/oauth2/strategy_hmacsha_test.go @@ -5,10 +5,11 @@ import ( "testing" "time" + "fmt" + "github.com/ory/fosite" "github.com/ory/fosite/token/hmac" "github.com/stretchr/testify/assert" - "fmt" ) var hmacshaStrategy = HMACSHAStrategy{ @@ -67,7 +68,7 @@ func TestHMACAccessToken(t *testing.T) { assert.Equal(t, signature, validate) } else { assert.Error(t, err) - } + } }) } } diff --git a/handler/oauth2/strategy_jwt_test.go b/handler/oauth2/strategy_jwt_test.go index 9108b014..dad43dc1 100644 --- a/handler/oauth2/strategy_jwt_test.go +++ b/handler/oauth2/strategy_jwt_test.go @@ -5,11 +5,12 @@ import ( "testing" "time" + "fmt" + "github.com/ory/fosite" "github.com/ory/fosite/internal" "github.com/ory/fosite/token/jwt" "github.com/stretchr/testify/assert" - "fmt" ) var j = &RS256JWTStrategy{ diff --git a/integration/authorize_code_grant_test.go b/integration/authorize_code_grant_test.go index 4c68daa8..76950adc 100644 --- a/integration/authorize_code_grant_test.go +++ b/integration/authorize_code_grant_test.go @@ -5,13 +5,14 @@ import ( "net/http" + "fmt" + "github.com/ory/fosite" "github.com/ory/fosite/compose" "github.com/ory/fosite/handler/oauth2" "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" goauth "golang.org/x/oauth2" - "fmt" ) func TestAuthorizeCodeFlow(t *testing.T) { diff --git a/integration/authorize_implicit_grant_test.go b/integration/authorize_implicit_grant_test.go index 38583131..ed0a2a73 100644 --- a/integration/authorize_implicit_grant_test.go +++ b/integration/authorize_implicit_grant_test.go @@ -8,6 +8,8 @@ import ( "testing" "time" + "fmt" + "github.com/ory/fosite" "github.com/ory/fosite/compose" "github.com/ory/fosite/handler/oauth2" @@ -15,7 +17,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" goauth "golang.org/x/oauth2" - "fmt" ) func TestAuthorizeImplicitFlow(t *testing.T) { diff --git a/integration/introspect_token_test.go b/integration/introspect_token_test.go index b2c1301e..59ef67a2 100644 --- a/integration/introspect_token_test.go +++ b/integration/introspect_token_test.go @@ -5,6 +5,8 @@ import ( "encoding/json" + "fmt" + "github.com/ory/fosite" "github.com/ory/fosite/compose" "github.com/ory/fosite/handler/oauth2" @@ -12,7 +14,6 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" goauth "golang.org/x/oauth2" - "fmt" ) func TestIntrospectToken(t *testing.T) { diff --git a/integration/oidc_implicit_hybrid_test.go b/integration/oidc_implicit_hybrid_test.go index b00e669f..ee8c9329 100644 --- a/integration/oidc_implicit_hybrid_test.go +++ b/integration/oidc_implicit_hybrid_test.go @@ -13,11 +13,12 @@ import ( "github.com/stretchr/testify/require" "golang.org/x/oauth2" + "fmt" + "github.com/ory/fosite/compose" "github.com/ory/fosite/handler/openid" "github.com/ory/fosite/internal" "github.com/ory/fosite/token/jwt" - "fmt" ) func TestOIDCImplicitFlow(t *testing.T) { diff --git a/scope_strategy_test.go b/scope_strategy_test.go index 21949578..32ec6f95 100644 --- a/scope_strategy_test.go +++ b/scope_strategy_test.go @@ -3,8 +3,9 @@ package fosite import ( "testing" - "github.com/stretchr/testify/assert" "strings" + + "github.com/stretchr/testify/assert" ) func TestHierarchicScopeStrategy(t *testing.T) { diff --git a/token/hmac/hmacsha.go b/token/hmac/hmacsha.go index aabadee5..aeae0782 100644 --- a/token/hmac/hmacsha.go +++ b/token/hmac/hmacsha.go @@ -6,10 +6,11 @@ import ( "encoding/base64" "fmt" "strings" - "github.com/ory/fosite" - "github.com/pkg/errors" "sync" + "github.com/gtank/cryptopasta" + "github.com/ory/fosite" + "github.com/pkg/errors" ) // HMACStrategy is responsible for generating and validating challenges. From 47fd477814c7826a9e9e89a02c248cfbad6b5a7a Mon Sep 17 00:00:00 2001 From: arekkas Date: Wed, 25 Oct 2017 12:01:39 +0200 Subject: [PATCH 06/35] travis: use go-acc and test format --- .travis.yml | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/.travis.yml b/.travis.yml index 47e045fb..fa18945d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -10,13 +10,10 @@ env: - GO15VENDOREXPERIMENT=1 install: - - go get github.com/mattn/goveralls golang.org/x/tools/cmd/cover github.com/pierrre/gotestcover github.com/Masterminds/glide + - go get github.com/mattn/goveralls golang.org/x/tools/cmd/cover github.com/pierrre/gotestcover github.com/Masterminds/glide github.com/ory/go-acc - glide install script: - - touch ./coverage.tmp - - | - echo 'mode: atomic' > coverage.txt - - | - go list ./... | grep -v /vendor | grep -v /internal | xargs -n1 -I{} sh -c 'go test -race -covermode=atomic -coverprofile=coverage.tmp -coverpkg $(go list ./... | grep -v /vendor | grep -v /internal | tr "\n" ",") {} && tail -n +2 coverage.tmp >> coverage.txt || exit 255' && rm coverage.tmp + - ./scripts/test-format.sh + - go-acc -o coverage.txt $(glide novendor) - goveralls -coverprofile="coverage.txt" From a2e3a474b2439e4ad68a641152639f7921e610a6 Mon Sep 17 00:00:00 2001 From: arekkas Date: Wed, 25 Oct 2017 12:03:32 +0200 Subject: [PATCH 07/35] history: add 0.12.0 to TOC --- HISTORY.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/HISTORY.md b/HISTORY.md index 0cda53c1..0797d58e 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -5,6 +5,9 @@ bumps (`0.1.0` -> `0.2.0`). +- [0.12.0](#0120) + - [Breaking changes](#breaking-changes) + - [Improved cryptographic methods](#improved-cryptographic-methods) - [0.11.0](#0110) - [Non-breaking changes](#non-breaking-changes) - [Storage adapter](#storage-adapter) @@ -19,7 +22,7 @@ bumps (`0.1.0` -> `0.2.0`). - [0.10.0](#0100) - [0.9.0](#090) - [0.8.0](#080) - - [Breaking changes](#breaking-changes) + - [Breaking changes](#breaking-changes-1) - [`ClientManager`](#clientmanager) - [`OAuth2Provider`](#oauth2provider) - [0.7.0](#070) From c17222c854198a7a388a2656a710bf13a5c3c3b9 Mon Sep 17 00:00:00 2001 From: arekkas Date: Wed, 25 Oct 2017 12:05:42 +0200 Subject: [PATCH 08/35] travis: update to go 1.9 --- .travis.yml | 6 +----- 1 file changed, 1 insertion(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index fa18945d..b39419f4 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,11 +3,7 @@ language: go go_import_path: github.com/ory/fosite go: - - 1.7 - - 1.8 - -env: - - GO15VENDOREXPERIMENT=1 + - 1.9 install: - go get github.com/mattn/goveralls golang.org/x/tools/cmd/cover github.com/pierrre/gotestcover github.com/Masterminds/glide github.com/ory/go-acc From 4f5df700e3c220f3aa5f7eb79a4b4f19d2f4576e Mon Sep 17 00:00:00 2001 From: arekkas Date: Wed, 25 Oct 2017 12:06:40 +0200 Subject: [PATCH 09/35] travis: add goimports to install section --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index b39419f4..54252b42 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ go: - 1.9 install: - - go get github.com/mattn/goveralls golang.org/x/tools/cmd/cover github.com/pierrre/gotestcover github.com/Masterminds/glide github.com/ory/go-acc + - go get github.com/mattn/goveralls golang.org/x/tools/cmd/cover github.com/pierrre/gotestcover github.com/Masterminds/glide github.com/ory/go-acc github.com/bradfitz/goimports - glide install script: From 65743b40c69ccc76f07fd3eb4c45837d3b4a1505 Mon Sep 17 00:00:00 2001 From: arekkas Date: Wed, 25 Oct 2017 12:09:14 +0200 Subject: [PATCH 10/35] scripts: fix goimports import path --- scripts/run-format.sh | 2 +- scripts/test-format.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/scripts/run-format.sh b/scripts/run-format.sh index 97138104..28c8a65a 100755 --- a/scripts/run-format.sh +++ b/scripts/run-format.sh @@ -4,5 +4,5 @@ set -euo pipefail cd "$( dirname "${BASH_SOURCE[0]}" )/.." -goimports -w $(go list -f {{.Dir}} ./... | grep -v vendor | grep -v oathkeeper$) +goimports -w $(go list -f {{.Dir}} ./... | grep -v vendor | grep -v fosite$) goimports -w *.go diff --git a/scripts/test-format.sh b/scripts/test-format.sh index 17799995..0cc64896 100755 --- a/scripts/test-format.sh +++ b/scripts/test-format.sh @@ -4,7 +4,7 @@ set -euo pipefail cd "$( dirname "${BASH_SOURCE[0]}" )/.." -toformat=$(goimports -l $(go list -f {{.Dir}} ./... | grep -v vendor | grep -v 'oathkeeper$')) +toformat=$(goimports -l $(go list -f {{.Dir}} ./... | grep -v vendor | grep -v 'fosite$')) [ -z "$toformat" ] && echo "All files are formatted correctly" [ -n "$toformat" ] && echo "Please use \`goimports\` to format the following files:" && echo $toformat && exit 1 From ec43e3a05da49d45ebe8a98b28b14f8817c507f4 Mon Sep 17 00:00:00 2001 From: aeneasr Date: Wed, 25 Oct 2017 12:34:34 +0200 Subject: [PATCH 11/35] vendor: replace glide with dep --- .travis.yml | 13 +++-- CONTRIBUTING.md | 2 +- Gopkg.lock | 135 ++++++++++++++++++++++++++++++++++++++++++++++++ Gopkg.toml | 74 ++++++++++++++++++++++++++ HISTORY.md | 6 +++ README.md | 11 ++-- glide.lock | 73 -------------------------- glide.yaml | 34 ------------ 8 files changed, 231 insertions(+), 117 deletions(-) create mode 100644 Gopkg.lock create mode 100644 Gopkg.toml delete mode 100644 glide.lock delete mode 100644 glide.yaml diff --git a/.travis.yml b/.travis.yml index 54252b42..14f42cd9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -5,11 +5,18 @@ go_import_path: github.com/ory/fosite go: - 1.9 +env: + - DEP_VERSION="0.3.2" + +before_install: + - curl -L -s https://github.com/golang/dep/releases/download/v${DEP_VERSION}/dep-linux-amd64 -o $GOPATH/bin/dep + - chmod +x $GOPATH/bin/dep + install: - - go get github.com/mattn/goveralls golang.org/x/tools/cmd/cover github.com/pierrre/gotestcover github.com/Masterminds/glide github.com/ory/go-acc github.com/bradfitz/goimports - - glide install + - dep ensure + - go get github.com/mattn/goveralls golang.org/x/tools/cmd/cover github.com/pierrre/gotestcover github.com/ory/go-acc github.com/bradfitz/goimports script: - ./scripts/test-format.sh - - go-acc -o coverage.txt $(glide novendor) + - go-acc -o coverage.txt ./... - goveralls -coverprofile="coverage.txt" diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ffd0dee3..e869527c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -96,7 +96,7 @@ To make a pull request, you will need a GitHub account; if you are unclear on th 1. Create a feature branch off of `master` so that changes do not get mixed up. 1. [Rebase](https://git-scm.com/book/en/Git-Branching-Rebasing) your local changes against the `master` branch. -1. Run the full project test suite with the `go test $(glide novendor)` (or equivalent) command and confirm that it passes. +1. Run the full project test suite with the `go test ./...` (or equivalent) command and confirm that it passes. 1. Run `gofmt -s` (if the project is written in Go). 1. Accept the Developer's Certificate of Origin on all commits (see above). 1. Ensure that each commit has a subsystem prefix (ex: `controller: `). diff --git a/Gopkg.lock b/Gopkg.lock new file mode 100644 index 00000000..cc221cad --- /dev/null +++ b/Gopkg.lock @@ -0,0 +1,135 @@ +# This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. + + +[[projects]] + name = "github.com/asaskevich/govalidator" + packages = ["."] + revision = "73945b6115bfbbcc57d89b7316e28109364124e1" + version = "v7" + +[[projects]] + name = "github.com/davecgh/go-spew" + packages = ["spew"] + revision = "346938d642f2ec3594ed81d874461961cd0faa76" + version = "v1.1.0" + +[[projects]] + name = "github.com/dgrijalva/jwt-go" + packages = ["."] + revision = "dbeaa9332f19a944acb5736b4456cfcc02140e29" + version = "v3.1.0" + +[[projects]] + name = "github.com/golang/mock" + packages = ["gomock"] + revision = "13f360950a79f5864a972c786a10a50e44b69541" + version = "v1.0.0" + +[[projects]] + branch = "master" + name = "github.com/golang/protobuf" + packages = ["proto"] + revision = "1643683e1b54a9e88ad26d98f81400c8c9d9f4f9" + +[[projects]] + name = "github.com/gorilla/context" + packages = ["."] + revision = "1ea25387ff6f684839d82767c1733ff4d4d15d0a" + version = "v1.1" + +[[projects]] + name = "github.com/gorilla/mux" + packages = ["."] + revision = "24fca303ac6da784b9e8269f724ddeb0b2eea5e7" + version = "v1.5.0" + +[[projects]] + branch = "master" + name = "github.com/gtank/cryptopasta" + packages = ["."] + revision = "1f550f6f2f69009f6ae57347c188e0a67cd4e500" + +[[projects]] + branch = "master" + name = "github.com/mohae/deepcopy" + packages = ["."] + revision = "c48cc78d482608239f6c4c92a4abd87eb8761c90" + +[[projects]] + branch = "master" + name = "github.com/moul/http2curl" + packages = ["."] + revision = "9ac6cf4d929b2fa8fd2d2e6dec5bb0feb4f4911d" + +[[projects]] + name = "github.com/oleiade/reflections" + packages = ["."] + revision = "2b6ec3da648e3e834dc41bad8d9ed7f2dc6a9496" + version = "v1.0.0" + +[[projects]] + name = "github.com/parnurzeal/gorequest" + packages = ["."] + revision = "a578a48e8d6ca8b01a3b18314c43c6716bb5f5a3" + version = "v0.2.15" + +[[projects]] + name = "github.com/pborman/uuid" + packages = ["."] + revision = "e790cca94e6cc75c7064b1332e63811d4aae1a53" + version = "v1.1" + +[[projects]] + name = "github.com/pkg/errors" + packages = ["."] + revision = "645ef00459ed84a119197bfb8d8205042c6df63d" + version = "v0.8.0" + +[[projects]] + name = "github.com/pmezard/go-difflib" + packages = ["difflib"] + revision = "792786c7400a136282c1664665ae0a8db921c6c2" + version = "v1.0.0" + +[[projects]] + name = "github.com/stretchr/testify" + packages = ["assert","require"] + revision = "69483b4bd14f5845b5a1e55bca19e954e827f1d0" + version = "v1.1.4" + +[[projects]] + branch = "master" + name = "golang.org/x/crypto" + packages = ["bcrypt","blowfish"] + revision = "2509b142fb2b797aa7587dad548f113b2c0f20ce" + +[[projects]] + branch = "master" + name = "golang.org/x/net" + packages = ["context","context/ctxhttp","idna","publicsuffix"] + revision = "4b14673ba32bee7f5ac0f990a48f033919fd418b" + +[[projects]] + branch = "master" + name = "golang.org/x/oauth2" + packages = [".","clientcredentials","internal"] + revision = "bb50c06baba3d0c76f9d125c0719093e315b5b44" + +[[projects]] + branch = "master" + name = "golang.org/x/text" + packages = ["collate","collate/build","internal/colltab","internal/gen","internal/tag","internal/triegen","internal/ucd","language","secure/bidirule","transform","unicode/bidi","unicode/cldr","unicode/norm","unicode/rangetable"] + revision = "6eab0e8f74e86c598ec3b6fad4888e0c11482d48" + +[[projects]] + name = "google.golang.org/appengine" + packages = ["internal","internal/base","internal/datastore","internal/log","internal/remote_api","internal/urlfetch","urlfetch"] + revision = "150dc57a1b433e64154302bdc40b6bb8aefa313a" + version = "v1.0.0" + +[solve-meta] + analyzer-name = "dep" + analyzer-version = 1 + inputs-digest = "1ec88100ce674d2223851185b8712fcf94ba459b7b891314b79849ad95916938" + solver-name = "gps-cdcl" + solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml new file mode 100644 index 00000000..02215b1d --- /dev/null +++ b/Gopkg.toml @@ -0,0 +1,74 @@ + +# Gopkg.toml example +# +# Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md +# for detailed Gopkg.toml documentation. +# +# required = ["github.com/user/thing/cmd/thing"] +# ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"] +# +# [[constraint]] +# name = "github.com/user/project" +# version = "1.0.0" +# +# [[constraint]] +# name = "github.com/user/project2" +# branch = "dev" +# source = "github.com/myfork/project2" +# +# [[override]] +# name = "github.com/x/y" +# version = "2.4.0" + + +[[constraint]] + name = "github.com/asaskevich/govalidator" + version = "7.0.0" + +[[constraint]] + name = "github.com/dgrijalva/jwt-go" + version = "3.1.0" + +[[constraint]] + name = "github.com/golang/mock" + version = "1.0.0" + +[[constraint]] + name = "github.com/gorilla/mux" + version = "1.5.0" + +[[constraint]] + branch = "master" + name = "github.com/gtank/cryptopasta" + +[[constraint]] + branch = "master" + name = "github.com/mohae/deepcopy" + +[[constraint]] + name = "github.com/oleiade/reflections" + version = "1.0.0" + +[[constraint]] + name = "github.com/parnurzeal/gorequest" + version = "0.2.15" + +[[constraint]] + name = "github.com/pborman/uuid" + version = "1.1.0" + +[[constraint]] + name = "github.com/pkg/errors" + version = "0.8.0" + +[[constraint]] + name = "github.com/stretchr/testify" + version = "1.1.4" + +[[constraint]] + branch = "master" + name = "golang.org/x/crypto" + +[[constraint]] + branch = "master" + name = "golang.org/x/oauth2" diff --git a/HISTORY.md b/HISTORY.md index 0797d58e..8400a420 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -35,6 +35,12 @@ bumps (`0.1.0` -> `0.2.0`). +## 0.13.0 + +### Breaking changes + +`glide` was replaced with `dep`. + ## 0.12.0 ### Breaking changes diff --git a/README.md b/README.md index b4cfdc38..736990ad 100644 --- a/README.md +++ b/README.md @@ -57,7 +57,7 @@ was out there, so we decided to build it ourselves. The core public API is almost stable as most changes will only touch the inner workings. -We strongly encourage vendoring fosite using [glide](https://glide.sh) or comparable tools. +We strongly encourage vendoring fosite using [dep](https://github.com/golang/dep) or comparable tools. ## Example @@ -69,10 +69,9 @@ of code. You can run this minimalistic example by doing ``` -go get github.com/Masterminds/glide go get github.com/ory/fosite-example cd $GOPATH/src/github.com/ory/fosite-example -glide install +dep ensure go install github.com/ory/fosite-example fosite-example ``` @@ -148,7 +147,7 @@ GOPATH environment variable. go get -d github.com/ory/fosite ``` -We recommend to use [Glide](https://github.com/Masterminds/glide) or [Godep](https://github.com/tools/godep) to +We recommend to use [dep](https://github.com/golang/dep) to mitigate compatibility breaks that come with new api versions. ## Documentation @@ -385,10 +384,10 @@ go get -d github.com/ory/fosite cd $GOPATH/src/github.com/ory/fosite git status git remote add myfork -go test $(glide novendor) +go test ./.. ``` -Simple, right? Now you are ready to go! Make sure to run `go test $(glide novendor)` often, detecting problems with your code +Simple, right? Now you are ready to go! Make sure to run `go test ./...` often, detecting problems with your code rather sooner than later. Please read [CONTRIBUTE.md] before creating pull requests and issues. ### Refresh mock objects diff --git a/glide.lock b/glide.lock deleted file mode 100644 index 3eb3cb48..00000000 --- a/glide.lock +++ /dev/null @@ -1,73 +0,0 @@ -hash: e095f7a7794a22ca84172c4f0d7f2d150fa8d260f9852537828441910ad73e84 -updated: 2017-10-25T11:28:31.641679+02:00 -imports: -- name: github.com/asaskevich/govalidator - version: 73945b6115bfbbcc57d89b7316e28109364124e1 -- name: github.com/dgrijalva/jwt-go - version: dbeaa9332f19a944acb5736b4456cfcc02140e29 -- name: github.com/golang/mock - version: 13f360950a79f5864a972c786a10a50e44b69541 - subpackages: - - gomock -- name: github.com/gtank/cryptopasta - version: 1f550f6f2f69009f6ae57347c188e0a67cd4e500 -- name: github.com/mohae/deepcopy - version: 491d3605edfb866af34a48075bd4355ac1bf46ca -- name: github.com/pborman/uuid - version: e790cca94e6cc75c7064b1332e63811d4aae1a53 -- name: github.com/pkg/errors - version: 645ef00459ed84a119197bfb8d8205042c6df63d -- name: golang.org/x/crypto - version: faadfbdc035307d901e69eea569f5dda451a3ee3 - subpackages: - - bcrypt - - blowfish -testImports: -- name: github.com/davecgh/go-spew - version: 6d212800a42e8ab5c146b8ace3490ee17e5225f9 - subpackages: - - spew -- name: github.com/golang/protobuf - version: 11b8df160996e00fd4b55cbaafb3d84ec6d50fa8 - subpackages: - - proto -- name: github.com/gorilla/context - version: 1ea25387ff6f684839d82767c1733ff4d4d15d0a -- name: github.com/gorilla/mux - version: 24fca303ac6da784b9e8269f724ddeb0b2eea5e7 -- name: github.com/moul/http2curl - version: 4e24498b31dba4683efb9d35c1c8a91e2eda28c8 -- name: github.com/oleiade/reflections - version: 2b6ec3da648e3e834dc41bad8d9ed7f2dc6a9496 -- name: github.com/parnurzeal/gorequest - version: a578a48e8d6ca8b01a3b18314c43c6716bb5f5a3 -- name: github.com/pmezard/go-difflib - version: d8ed2627bdf02c080bf22230dbb337003b7aba2d - subpackages: - - difflib -- name: github.com/stretchr/testify - version: 69483b4bd14f5845b5a1e55bca19e954e827f1d0 - subpackages: - - assert - - require -- name: golang.org/x/net - version: 859d1a86bb617c0c20d154590c3c5d3fcb670b07 - subpackages: - - context - - context/ctxhttp - - publicsuffix -- name: golang.org/x/oauth2 - version: 13449ad91cb26cb47661c1b080790392170385fd - subpackages: - - clientcredentials - - internal -- name: google.golang.org/appengine - version: d9a072cfa7b9736e44311ef77b3e09d804bfa599 - subpackages: - - internal - - internal/base - - internal/datastore - - internal/log - - internal/remote_api - - internal/urlfetch - - urlfetch diff --git a/glide.yaml b/glide.yaml deleted file mode 100644 index 341a5543..00000000 --- a/glide.yaml +++ /dev/null @@ -1,34 +0,0 @@ -package: github.com/ory/fosite -import: -- package: github.com/asaskevich/govalidator - version: ~7.0.0 -- package: github.com/dgrijalva/jwt-go - version: ~3.1.0 -- package: github.com/golang/mock - version: ~1.0.0 - subpackages: - - gomock -- package: github.com/gtank/cryptopasta -- package: github.com/mohae/deepcopy -- package: github.com/pborman/uuid - version: ~1.1.0 -- package: github.com/pkg/errors - version: ~0.8.0 -- package: golang.org/x/crypto - subpackages: - - bcrypt -testImport: -- package: github.com/gorilla/mux - version: ~1.5.0 -- package: github.com/oleiade/reflections - version: ~1.0.0 -- package: github.com/parnurzeal/gorequest - version: ~0.2.15 -- package: github.com/stretchr/testify - version: ~1.1.4 - subpackages: - - assert - - require -- package: golang.org/x/oauth2 - subpackages: - - clientcredentials From dd9398ea0553b07d63022af50ee2090d1616c5a9 Mon Sep 17 00:00:00 2001 From: Aeneas Date: Mon, 6 Nov 2017 12:34:08 +0100 Subject: [PATCH 12/35] Add license header to all source files (#222) Closes #221 Signed-off-by: aeneasr --- access_error.go | 14 ++++++++++++++ access_error_test.go | 14 ++++++++++++++ access_request.go | 14 ++++++++++++++ access_request_handler.go | 14 ++++++++++++++ access_request_handler_test.go | 14 ++++++++++++++ access_request_test.go | 14 ++++++++++++++ access_response.go | 14 ++++++++++++++ access_response_test.go | 14 ++++++++++++++ access_response_writer.go | 14 ++++++++++++++ access_response_writer_test.go | 14 ++++++++++++++ access_write.go | 14 ++++++++++++++ access_write_test.go | 14 ++++++++++++++ arguments.go | 14 ++++++++++++++ arguments_test.go | 14 ++++++++++++++ authorize_error.go | 14 ++++++++++++++ authorize_error_test.go | 14 ++++++++++++++ authorize_helper.go | 14 ++++++++++++++ authorize_helper_test.go | 14 ++++++++++++++ authorize_request.go | 14 ++++++++++++++ authorize_request_handler.go | 14 ++++++++++++++ authorize_request_handler_test.go | 14 ++++++++++++++ authorize_request_test.go | 14 ++++++++++++++ authorize_response.go | 14 ++++++++++++++ authorize_response_test.go | 14 ++++++++++++++ authorize_response_writer.go | 14 ++++++++++++++ authorize_response_writer_test.go | 14 ++++++++++++++ authorize_write.go | 14 ++++++++++++++ authorize_write_test.go | 14 ++++++++++++++ client.go | 14 ++++++++++++++ client_manager.go | 14 ++++++++++++++ client_test.go | 14 ++++++++++++++ compose/compose.go | 14 ++++++++++++++ compose/compose_oauth2.go | 14 ++++++++++++++ compose/compose_openid.go | 14 ++++++++++++++ compose/compose_strategy.go | 14 ++++++++++++++ compose/config.go | 14 ++++++++++++++ context.go | 14 ++++++++++++++ equalKeys_test.go | 14 ++++++++++++++ errors.go | 14 ++++++++++++++ errors_test.go | 14 ++++++++++++++ fosite.go | 14 ++++++++++++++ fosite_test.go | 14 ++++++++++++++ handler.go | 14 ++++++++++++++ handler/oauth2/flow_authorize_code_auth.go | 14 ++++++++++++++ handler/oauth2/flow_authorize_code_auth_test.go | 14 ++++++++++++++ handler/oauth2/flow_authorize_code_token.go | 14 ++++++++++++++ handler/oauth2/flow_authorize_code_token_test.go | 14 ++++++++++++++ handler/oauth2/flow_authorize_implicit.go | 14 ++++++++++++++ handler/oauth2/flow_authorize_implicit_test.go | 14 ++++++++++++++ handler/oauth2/flow_client_credentials.go | 14 ++++++++++++++ handler/oauth2/flow_client_credentials_storage.go | 14 ++++++++++++++ handler/oauth2/flow_client_credentials_test.go | 14 ++++++++++++++ handler/oauth2/flow_refresh.go | 14 ++++++++++++++ handler/oauth2/flow_refresh_test.go | 14 ++++++++++++++ handler/oauth2/flow_resource_owner.go | 14 ++++++++++++++ handler/oauth2/flow_resource_owner_storage.go | 14 ++++++++++++++ handler/oauth2/flow_resource_owner_test.go | 14 ++++++++++++++ handler/oauth2/helper.go | 14 ++++++++++++++ handler/oauth2/helper_test.go | 14 ++++++++++++++ handler/oauth2/introspector.go | 14 ++++++++++++++ handler/oauth2/introspector_jwt.go | 14 ++++++++++++++ handler/oauth2/introspector_jwt_test.go | 14 ++++++++++++++ handler/oauth2/introspector_test.go | 14 ++++++++++++++ handler/oauth2/revocation.go | 14 ++++++++++++++ handler/oauth2/revocation_storage.go | 14 ++++++++++++++ handler/oauth2/revocation_test.go | 14 ++++++++++++++ handler/oauth2/storage.go | 14 ++++++++++++++ handler/oauth2/strategy.go | 14 ++++++++++++++ handler/oauth2/strategy_hmacsha.go | 14 ++++++++++++++ handler/oauth2/strategy_hmacsha_test.go | 14 ++++++++++++++ handler/oauth2/strategy_jwt.go | 14 ++++++++++++++ handler/oauth2/strategy_jwt_session.go | 14 ++++++++++++++ handler/oauth2/strategy_jwt_test.go | 14 ++++++++++++++ handler/openid/errors.go | 14 ++++++++++++++ handler/openid/flow_explicit_auth.go | 14 ++++++++++++++ handler/openid/flow_explicit_auth_test.go | 14 ++++++++++++++ handler/openid/flow_explicit_token.go | 14 ++++++++++++++ handler/openid/flow_explicit_token_test.go | 14 ++++++++++++++ handler/openid/flow_hybrid.go | 14 ++++++++++++++ handler/openid/flow_hybrid_test.go | 14 ++++++++++++++ handler/openid/flow_implicit.go | 14 ++++++++++++++ handler/openid/flow_implicit_test.go | 14 ++++++++++++++ handler/openid/flow_refresh_token.go | 14 ++++++++++++++ handler/openid/flow_refresh_token_test.go | 14 ++++++++++++++ handler/openid/helper.go | 14 ++++++++++++++ handler/openid/helper_test.go | 14 ++++++++++++++ handler/openid/storage.go | 14 ++++++++++++++ handler/openid/strategy.go | 14 ++++++++++++++ handler/openid/strategy_jwt.go | 14 ++++++++++++++ handler/openid/strategy_jwt_test.go | 14 ++++++++++++++ hash.go | 14 ++++++++++++++ hash_bcrypt.go | 14 ++++++++++++++ hash_bcrypt_test.go | 14 ++++++++++++++ helper.go | 14 ++++++++++++++ helper_test.go | 14 ++++++++++++++ integration/authorize_code_grant_test.go | 14 ++++++++++++++ integration/authorize_implicit_grant_test.go | 14 ++++++++++++++ integration/client_credentials_grant_test.go | 14 ++++++++++++++ integration/helper_endpoints_test.go | 14 ++++++++++++++ integration/helper_setup_test.go | 14 ++++++++++++++ integration/introspect_token_test.go | 14 ++++++++++++++ integration/oidc_explicit_test.go | 14 ++++++++++++++ integration/oidc_implicit_hybrid_test.go | 14 ++++++++++++++ integration/placeholder.go | 14 ++++++++++++++ integration/refresh_token_grant_test.go | 14 ++++++++++++++ ...source_owner_password_credentials_grant_test.go | 14 ++++++++++++++ integration/revoke_token_test.go | 14 ++++++++++++++ internal/access_request.go | 14 ++++++++++++++ internal/access_response.go | 14 ++++++++++++++ internal/access_token_storage.go | 14 ++++++++++++++ internal/access_token_strategy.go | 14 ++++++++++++++ internal/authorize_code_storage.go | 14 ++++++++++++++ internal/authorize_code_strategy.go | 14 ++++++++++++++ internal/authorize_handler.go | 14 ++++++++++++++ internal/authorize_request.go | 14 ++++++++++++++ internal/authorize_response.go | 14 ++++++++++++++ internal/client.go | 14 ++++++++++++++ internal/hash.go | 14 ++++++++++++++ internal/id_token_strategy.go | 14 ++++++++++++++ internal/introspector.go | 14 ++++++++++++++ internal/key.go | 14 ++++++++++++++ internal/oauth2_client_storage.go | 14 ++++++++++++++ internal/oauth2_explicit_storage.go | 14 ++++++++++++++ internal/oauth2_owner_storage.go | 14 ++++++++++++++ internal/oauth2_refresh_storage.go | 14 ++++++++++++++ internal/oauth2_revoke_storage.go | 14 ++++++++++++++ internal/oauth2_storage.go | 14 ++++++++++++++ internal/oauth2_strategy.go | 14 ++++++++++++++ internal/openid_id_token_storage.go | 14 ++++++++++++++ internal/refresh_token_strategy.go | 14 ++++++++++++++ internal/request.go | 14 ++++++++++++++ internal/revoke_handler.go | 14 ++++++++++++++ internal/rw.go | 14 ++++++++++++++ internal/storage.go | 14 ++++++++++++++ internal/token_handler.go | 14 ++++++++++++++ introspect.go | 14 ++++++++++++++ introspect_test.go | 14 ++++++++++++++ introspection_request_handler.go | 14 ++++++++++++++ introspection_request_handler_test.go | 14 ++++++++++++++ introspection_response_writer.go | 14 ++++++++++++++ introspection_response_writer_test.go | 14 ++++++++++++++ oauth2.go | 14 ++++++++++++++ request.go | 14 ++++++++++++++ request_test.go | 14 ++++++++++++++ revoke_handler.go | 14 ++++++++++++++ revoke_handler_test.go | 14 ++++++++++++++ scope_strategy.go | 14 ++++++++++++++ scope_strategy_test.go | 14 ++++++++++++++ session.go | 14 ++++++++++++++ session_test.go | 14 ++++++++++++++ storage.go | 14 ++++++++++++++ storage/memory.go | 14 ++++++++++++++ token/hmac/bytes.go | 14 ++++++++++++++ token/hmac/bytes_test.go | 14 ++++++++++++++ token/hmac/hmacsha.go | 14 ++++++++++++++ token/hmac/hmacsha_test.go | 14 ++++++++++++++ token/jwt/claims.go | 14 ++++++++++++++ token/jwt/claims_id_token.go | 14 ++++++++++++++ token/jwt/claims_id_token_test.go | 14 ++++++++++++++ token/jwt/claims_jwt.go | 14 ++++++++++++++ token/jwt/claims_jwt_test.go | 14 ++++++++++++++ token/jwt/claims_test.go | 14 ++++++++++++++ token/jwt/header.go | 14 ++++++++++++++ token/jwt/header_test.go | 14 ++++++++++++++ token/jwt/jwt.go | 14 ++++++++++++++ token/jwt/jwt_test.go | 14 ++++++++++++++ 166 files changed, 2324 insertions(+) diff --git a/access_error.go b/access_error.go index e5b7b8bd..09ce8c4b 100644 --- a/access_error.go +++ b/access_error.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/access_error_test.go b/access_error_test.go index f4ecc745..e917950f 100644 --- a/access_error_test.go +++ b/access_error_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite_test import ( diff --git a/access_request.go b/access_request.go index 810b7de3..984b9839 100644 --- a/access_request.go +++ b/access_request.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite type AccessRequest struct { diff --git a/access_request_handler.go b/access_request_handler.go index 4155d4c2..3c7a6144 100644 --- a/access_request_handler.go +++ b/access_request_handler.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/access_request_handler_test.go b/access_request_handler_test.go index c4dbbc90..d4e03553 100644 --- a/access_request_handler_test.go +++ b/access_request_handler_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite_test import ( diff --git a/access_request_test.go b/access_request_test.go index 8494ff45..cbd782f0 100644 --- a/access_request_test.go +++ b/access_request_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/access_response.go b/access_response.go index 1a9b16f1..11d121ea 100644 --- a/access_response.go +++ b/access_response.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/access_response_test.go b/access_response_test.go index 46a5a172..963fec71 100644 --- a/access_response_test.go +++ b/access_response_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite_test import ( diff --git a/access_response_writer.go b/access_response_writer.go index ef07bac1..8c1b8c04 100644 --- a/access_response_writer.go +++ b/access_response_writer.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/access_response_writer_test.go b/access_response_writer_test.go index 6d3f8ceb..38e89200 100644 --- a/access_response_writer_test.go +++ b/access_response_writer_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite_test import ( diff --git a/access_write.go b/access_write.go index a016c8be..a86433d9 100644 --- a/access_write.go +++ b/access_write.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/access_write_test.go b/access_write_test.go index df077f41..84eb2d7d 100644 --- a/access_write_test.go +++ b/access_write_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite_test import ( diff --git a/arguments.go b/arguments.go index 776389da..64a2893b 100644 --- a/arguments.go +++ b/arguments.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import "strings" diff --git a/arguments_test.go b/arguments_test.go index ded18d8e..2956d00c 100644 --- a/arguments_test.go +++ b/arguments_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/authorize_error.go b/authorize_error.go index bd971e1b..eaa41d48 100644 --- a/authorize_error.go +++ b/authorize_error.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/authorize_error_test.go b/authorize_error_test.go index 0d059088..1eb51fda 100644 --- a/authorize_error_test.go +++ b/authorize_error_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite_test import ( diff --git a/authorize_helper.go b/authorize_helper.go index 256b4763..f1bf7d45 100644 --- a/authorize_helper.go +++ b/authorize_helper.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/authorize_helper_test.go b/authorize_helper_test.go index c2e26035..041ff123 100644 --- a/authorize_helper_test.go +++ b/authorize_helper_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/authorize_request.go b/authorize_request.go index 3a192cb2..9228f6fb 100644 --- a/authorize_request.go +++ b/authorize_request.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/authorize_request_handler.go b/authorize_request_handler.go index 31ac2564..faf6ba52 100644 --- a/authorize_request_handler.go +++ b/authorize_request_handler.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/authorize_request_handler_test.go b/authorize_request_handler_test.go index 50a2c328..3a6b61ac 100644 --- a/authorize_request_handler_test.go +++ b/authorize_request_handler_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite_test import ( diff --git a/authorize_request_test.go b/authorize_request_test.go index b6704bcb..95ce4895 100644 --- a/authorize_request_test.go +++ b/authorize_request_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/authorize_response.go b/authorize_response.go index f72636f2..fc6158ef 100644 --- a/authorize_response.go +++ b/authorize_response.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/authorize_response_test.go b/authorize_response_test.go index 46f30086..1288bee6 100644 --- a/authorize_response_test.go +++ b/authorize_response_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/authorize_response_writer.go b/authorize_response_writer.go index a04c7907..3b0bd3b6 100644 --- a/authorize_response_writer.go +++ b/authorize_response_writer.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/authorize_response_writer_test.go b/authorize_response_writer_test.go index 19e34752..47be6625 100644 --- a/authorize_response_writer_test.go +++ b/authorize_response_writer_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite_test import ( diff --git a/authorize_write.go b/authorize_write.go index 55800099..b192168c 100644 --- a/authorize_write.go +++ b/authorize_write.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/authorize_write_test.go b/authorize_write_test.go index be1e9efb..a9045ef6 100644 --- a/authorize_write_test.go +++ b/authorize_write_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite_test import ( diff --git a/client.go b/client.go index c4f910c1..f31ab975 100644 --- a/client.go +++ b/client.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite // Client represents a client or an app. diff --git a/client_manager.go b/client_manager.go index 9ccd56f2..5d2081ec 100644 --- a/client_manager.go +++ b/client_manager.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import "context" diff --git a/client_test.go b/client_test.go index 671b2924..32cfe7dd 100644 --- a/client_test.go +++ b/client_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/compose/compose.go b/compose/compose.go index dd9de608..75d233df 100644 --- a/compose/compose.go +++ b/compose/compose.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package compose import ( diff --git a/compose/compose_oauth2.go b/compose/compose_oauth2.go index a665d8e0..775a9577 100644 --- a/compose/compose_oauth2.go +++ b/compose/compose_oauth2.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package compose import ( diff --git a/compose/compose_openid.go b/compose/compose_openid.go index 60955a8d..56bb59e2 100644 --- a/compose/compose_openid.go +++ b/compose/compose_openid.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package compose import ( diff --git a/compose/compose_strategy.go b/compose/compose_strategy.go index 460bb4ac..f4ec088a 100644 --- a/compose/compose_strategy.go +++ b/compose/compose_strategy.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package compose import ( diff --git a/compose/config.go b/compose/config.go index f0bac50b..1d7c6399 100644 --- a/compose/config.go +++ b/compose/config.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package compose import ( diff --git a/context.go b/context.go index 66cb4947..5abeaad7 100644 --- a/context.go +++ b/context.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import "context" diff --git a/equalKeys_test.go b/equalKeys_test.go index dbdb8878..51ef9821 100644 --- a/equalKeys_test.go +++ b/equalKeys_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite_test import ( diff --git a/errors.go b/errors.go index 971a5fd0..f35735fa 100644 --- a/errors.go +++ b/errors.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/errors_test.go b/errors_test.go index 62e9129f..65d86ba4 100644 --- a/errors_test.go +++ b/errors_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/fosite.go b/fosite.go index f01f8e5f..ccc91381 100644 --- a/fosite.go +++ b/fosite.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/fosite_test.go b/fosite_test.go index 09d0a3e6..315bfa45 100644 --- a/fosite_test.go +++ b/fosite_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite_test import ( diff --git a/handler.go b/handler.go index c504befe..984e3024 100644 --- a/handler.go +++ b/handler.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/handler/oauth2/flow_authorize_code_auth.go b/handler/oauth2/flow_authorize_code_auth.go index 32c50b00..3061cb82 100644 --- a/handler/oauth2/flow_authorize_code_auth.go +++ b/handler/oauth2/flow_authorize_code_auth.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/flow_authorize_code_auth_test.go b/handler/oauth2/flow_authorize_code_auth_test.go index f321a060..fea442a0 100644 --- a/handler/oauth2/flow_authorize_code_auth_test.go +++ b/handler/oauth2/flow_authorize_code_auth_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/flow_authorize_code_token.go b/handler/oauth2/flow_authorize_code_token.go index 274cb693..1cf449b4 100644 --- a/handler/oauth2/flow_authorize_code_token.go +++ b/handler/oauth2/flow_authorize_code_token.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/flow_authorize_code_token_test.go b/handler/oauth2/flow_authorize_code_token_test.go index b8e70c53..06fa1c6d 100644 --- a/handler/oauth2/flow_authorize_code_token_test.go +++ b/handler/oauth2/flow_authorize_code_token_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/flow_authorize_implicit.go b/handler/oauth2/flow_authorize_implicit.go index 30da033f..ed608540 100644 --- a/handler/oauth2/flow_authorize_implicit.go +++ b/handler/oauth2/flow_authorize_implicit.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/flow_authorize_implicit_test.go b/handler/oauth2/flow_authorize_implicit_test.go index 7e543fb8..42c6f7ba 100644 --- a/handler/oauth2/flow_authorize_implicit_test.go +++ b/handler/oauth2/flow_authorize_implicit_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/flow_client_credentials.go b/handler/oauth2/flow_client_credentials.go index 37876ef2..2da37d08 100644 --- a/handler/oauth2/flow_client_credentials.go +++ b/handler/oauth2/flow_client_credentials.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/flow_client_credentials_storage.go b/handler/oauth2/flow_client_credentials_storage.go index 0ef5da74..8ccf1f0a 100644 --- a/handler/oauth2/flow_client_credentials_storage.go +++ b/handler/oauth2/flow_client_credentials_storage.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 type ClientCredentialsGrantStorage interface { diff --git a/handler/oauth2/flow_client_credentials_test.go b/handler/oauth2/flow_client_credentials_test.go index 03d2c29c..cf5d4c1a 100644 --- a/handler/oauth2/flow_client_credentials_test.go +++ b/handler/oauth2/flow_client_credentials_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/flow_refresh.go b/handler/oauth2/flow_refresh.go index 1d7bb387..531a4039 100644 --- a/handler/oauth2/flow_refresh.go +++ b/handler/oauth2/flow_refresh.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/flow_refresh_test.go b/handler/oauth2/flow_refresh_test.go index 608d5844..eca6d3a8 100644 --- a/handler/oauth2/flow_refresh_test.go +++ b/handler/oauth2/flow_refresh_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/flow_resource_owner.go b/handler/oauth2/flow_resource_owner.go index 749ea222..d54bb2b2 100644 --- a/handler/oauth2/flow_resource_owner.go +++ b/handler/oauth2/flow_resource_owner.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/flow_resource_owner_storage.go b/handler/oauth2/flow_resource_owner_storage.go index e9f45779..87dce06e 100644 --- a/handler/oauth2/flow_resource_owner_storage.go +++ b/handler/oauth2/flow_resource_owner_storage.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/flow_resource_owner_test.go b/handler/oauth2/flow_resource_owner_test.go index 38aabed7..614f4056 100644 --- a/handler/oauth2/flow_resource_owner_test.go +++ b/handler/oauth2/flow_resource_owner_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/helper.go b/handler/oauth2/helper.go index e0c6b12d..73cc8a26 100644 --- a/handler/oauth2/helper.go +++ b/handler/oauth2/helper.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/helper_test.go b/handler/oauth2/helper_test.go index 11e18ece..d59ae375 100644 --- a/handler/oauth2/helper_test.go +++ b/handler/oauth2/helper_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/introspector.go b/handler/oauth2/introspector.go index db7b513e..d5485772 100644 --- a/handler/oauth2/introspector.go +++ b/handler/oauth2/introspector.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/introspector_jwt.go b/handler/oauth2/introspector_jwt.go index 16999176..2f1f2fe7 100644 --- a/handler/oauth2/introspector_jwt.go +++ b/handler/oauth2/introspector_jwt.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/introspector_jwt_test.go b/handler/oauth2/introspector_jwt_test.go index 21f5c902..2bd544e6 100644 --- a/handler/oauth2/introspector_jwt_test.go +++ b/handler/oauth2/introspector_jwt_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/introspector_test.go b/handler/oauth2/introspector_test.go index c582c67f..c3fdd3f6 100644 --- a/handler/oauth2/introspector_test.go +++ b/handler/oauth2/introspector_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/revocation.go b/handler/oauth2/revocation.go index 23dcfe12..79d8cab1 100644 --- a/handler/oauth2/revocation.go +++ b/handler/oauth2/revocation.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/revocation_storage.go b/handler/oauth2/revocation_storage.go index 5137d902..194610f7 100644 --- a/handler/oauth2/revocation_storage.go +++ b/handler/oauth2/revocation_storage.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/revocation_test.go b/handler/oauth2/revocation_test.go index 935eaa4b..57be6632 100644 --- a/handler/oauth2/revocation_test.go +++ b/handler/oauth2/revocation_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/storage.go b/handler/oauth2/storage.go index bf276103..40510dfc 100644 --- a/handler/oauth2/storage.go +++ b/handler/oauth2/storage.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/strategy.go b/handler/oauth2/strategy.go index 9df84ba2..ec178937 100644 --- a/handler/oauth2/strategy.go +++ b/handler/oauth2/strategy.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/strategy_hmacsha.go b/handler/oauth2/strategy_hmacsha.go index 1ce2e216..72584947 100644 --- a/handler/oauth2/strategy_hmacsha.go +++ b/handler/oauth2/strategy_hmacsha.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/strategy_hmacsha_test.go b/handler/oauth2/strategy_hmacsha_test.go index d287a5d9..3119f63a 100644 --- a/handler/oauth2/strategy_hmacsha_test.go +++ b/handler/oauth2/strategy_hmacsha_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/strategy_jwt.go b/handler/oauth2/strategy_jwt.go index b1dff88f..f008eb04 100644 --- a/handler/oauth2/strategy_jwt.go +++ b/handler/oauth2/strategy_jwt.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/strategy_jwt_session.go b/handler/oauth2/strategy_jwt_session.go index 0fa73829..d1983e79 100644 --- a/handler/oauth2/strategy_jwt_session.go +++ b/handler/oauth2/strategy_jwt_session.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/oauth2/strategy_jwt_test.go b/handler/oauth2/strategy_jwt_test.go index dad43dc1..4c94b9da 100644 --- a/handler/oauth2/strategy_jwt_test.go +++ b/handler/oauth2/strategy_jwt_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package oauth2 import ( diff --git a/handler/openid/errors.go b/handler/openid/errors.go index 1245f2b5..cce51683 100644 --- a/handler/openid/errors.go +++ b/handler/openid/errors.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package openid import "github.com/pkg/errors" diff --git a/handler/openid/flow_explicit_auth.go b/handler/openid/flow_explicit_auth.go index c94208ce..d31b99df 100644 --- a/handler/openid/flow_explicit_auth.go +++ b/handler/openid/flow_explicit_auth.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package openid import ( diff --git a/handler/openid/flow_explicit_auth_test.go b/handler/openid/flow_explicit_auth_test.go index 9f082588..3d3616f2 100644 --- a/handler/openid/flow_explicit_auth_test.go +++ b/handler/openid/flow_explicit_auth_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package openid import ( diff --git a/handler/openid/flow_explicit_token.go b/handler/openid/flow_explicit_token.go index fad5c270..35b34450 100644 --- a/handler/openid/flow_explicit_token.go +++ b/handler/openid/flow_explicit_token.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package openid import ( diff --git a/handler/openid/flow_explicit_token_test.go b/handler/openid/flow_explicit_token_test.go index 6950716e..966e86a2 100644 --- a/handler/openid/flow_explicit_token_test.go +++ b/handler/openid/flow_explicit_token_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package openid import ( diff --git a/handler/openid/flow_hybrid.go b/handler/openid/flow_hybrid.go index c8ca817f..128bd3c8 100644 --- a/handler/openid/flow_hybrid.go +++ b/handler/openid/flow_hybrid.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package openid import ( diff --git a/handler/openid/flow_hybrid_test.go b/handler/openid/flow_hybrid_test.go index f4405c19..645b955b 100644 --- a/handler/openid/flow_hybrid_test.go +++ b/handler/openid/flow_hybrid_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package openid import ( diff --git a/handler/openid/flow_implicit.go b/handler/openid/flow_implicit.go index 1f460b3f..3fd4833b 100644 --- a/handler/openid/flow_implicit.go +++ b/handler/openid/flow_implicit.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package openid import ( diff --git a/handler/openid/flow_implicit_test.go b/handler/openid/flow_implicit_test.go index b710d62a..739c912b 100644 --- a/handler/openid/flow_implicit_test.go +++ b/handler/openid/flow_implicit_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package openid import ( diff --git a/handler/openid/flow_refresh_token.go b/handler/openid/flow_refresh_token.go index f7020d30..b66379c3 100644 --- a/handler/openid/flow_refresh_token.go +++ b/handler/openid/flow_refresh_token.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package openid import ( diff --git a/handler/openid/flow_refresh_token_test.go b/handler/openid/flow_refresh_token_test.go index e8a00b0e..09d96d33 100644 --- a/handler/openid/flow_refresh_token_test.go +++ b/handler/openid/flow_refresh_token_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package openid import ( diff --git a/handler/openid/helper.go b/handler/openid/helper.go index ceaf10d2..a873585d 100644 --- a/handler/openid/helper.go +++ b/handler/openid/helper.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package openid import ( diff --git a/handler/openid/helper_test.go b/handler/openid/helper_test.go index fdc36d57..8740ba47 100644 --- a/handler/openid/helper_test.go +++ b/handler/openid/helper_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package openid import ( diff --git a/handler/openid/storage.go b/handler/openid/storage.go index 515b524c..4d2711cd 100644 --- a/handler/openid/storage.go +++ b/handler/openid/storage.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package openid import ( diff --git a/handler/openid/strategy.go b/handler/openid/strategy.go index ded8b5a7..e86ced0a 100644 --- a/handler/openid/strategy.go +++ b/handler/openid/strategy.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package openid import ( diff --git a/handler/openid/strategy_jwt.go b/handler/openid/strategy_jwt.go index 86490d9b..25cc6da1 100644 --- a/handler/openid/strategy_jwt.go +++ b/handler/openid/strategy_jwt.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package openid import ( diff --git a/handler/openid/strategy_jwt_test.go b/handler/openid/strategy_jwt_test.go index ecd0cef3..d234004d 100644 --- a/handler/openid/strategy_jwt_test.go +++ b/handler/openid/strategy_jwt_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package openid import ( diff --git a/hash.go b/hash.go index 5321c3e9..d25a61c4 100644 --- a/hash.go +++ b/hash.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite // Hasher defines how a oauth2-compatible hasher should look like. diff --git a/hash_bcrypt.go b/hash_bcrypt.go index 5243c065..2b5396dc 100644 --- a/hash_bcrypt.go +++ b/hash_bcrypt.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/hash_bcrypt_test.go b/hash_bcrypt_test.go index c931ad5b..0b488005 100644 --- a/hash_bcrypt_test.go +++ b/hash_bcrypt_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/helper.go b/helper.go index 62e5a673..4e640dd6 100644 --- a/helper.go +++ b/helper.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/helper_test.go b/helper_test.go index 97c98b10..c3093c2d 100644 --- a/helper_test.go +++ b/helper_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/integration/authorize_code_grant_test.go b/integration/authorize_code_grant_test.go index 76950adc..9d2348c3 100644 --- a/integration/authorize_code_grant_test.go +++ b/integration/authorize_code_grant_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package integration_test import ( diff --git a/integration/authorize_implicit_grant_test.go b/integration/authorize_implicit_grant_test.go index ed0a2a73..04b8e994 100644 --- a/integration/authorize_implicit_grant_test.go +++ b/integration/authorize_implicit_grant_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package integration_test import ( diff --git a/integration/client_credentials_grant_test.go b/integration/client_credentials_grant_test.go index c9bae2ed..9a90b0bf 100644 --- a/integration/client_credentials_grant_test.go +++ b/integration/client_credentials_grant_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package integration_test import ( diff --git a/integration/helper_endpoints_test.go b/integration/helper_endpoints_test.go index ded3aa52..2378b6d5 100644 --- a/integration/helper_endpoints_test.go +++ b/integration/helper_endpoints_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package integration_test import ( diff --git a/integration/helper_setup_test.go b/integration/helper_setup_test.go index 741b1f09..d31bd4c9 100644 --- a/integration/helper_setup_test.go +++ b/integration/helper_setup_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package integration_test import ( diff --git a/integration/introspect_token_test.go b/integration/introspect_token_test.go index 59ef67a2..f96db5e2 100644 --- a/integration/introspect_token_test.go +++ b/integration/introspect_token_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package integration_test import ( diff --git a/integration/oidc_explicit_test.go b/integration/oidc_explicit_test.go index d62bcb00..94fb8ad1 100644 --- a/integration/oidc_explicit_test.go +++ b/integration/oidc_explicit_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package integration_test import ( diff --git a/integration/oidc_implicit_hybrid_test.go b/integration/oidc_implicit_hybrid_test.go index ee8c9329..df1ad75d 100644 --- a/integration/oidc_implicit_hybrid_test.go +++ b/integration/oidc_implicit_hybrid_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package integration_test import ( diff --git a/integration/placeholder.go b/integration/placeholder.go index 76ab1b72..429eee64 100644 --- a/integration/placeholder.go +++ b/integration/placeholder.go @@ -1 +1,15 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package integration diff --git a/integration/refresh_token_grant_test.go b/integration/refresh_token_grant_test.go index 55ae85f2..9c09a4d1 100644 --- a/integration/refresh_token_grant_test.go +++ b/integration/refresh_token_grant_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package integration_test import ( diff --git a/integration/resource_owner_password_credentials_grant_test.go b/integration/resource_owner_password_credentials_grant_test.go index 6e98f14c..37a1e3f0 100644 --- a/integration/resource_owner_password_credentials_grant_test.go +++ b/integration/resource_owner_password_credentials_grant_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package integration_test import ( diff --git a/integration/revoke_token_test.go b/integration/revoke_token_test.go index c026f0b8..b7e4692a 100644 --- a/integration/revoke_token_test.go +++ b/integration/revoke_token_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package integration_test import ( diff --git a/internal/access_request.go b/internal/access_request.go index 136ab8f9..78cf7249 100644 --- a/internal/access_request.go +++ b/internal/access_request.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite (interfaces: AccessRequester) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/access_response.go b/internal/access_response.go index 802cdc03..53636108 100644 --- a/internal/access_response.go +++ b/internal/access_response.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite (interfaces: AccessResponder) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/access_token_storage.go b/internal/access_token_storage.go index 014a6f1e..c587dfed 100644 --- a/internal/access_token_storage.go +++ b/internal/access_token_storage.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/oauth2 (interfaces: AccessTokenStorage) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/access_token_strategy.go b/internal/access_token_strategy.go index 2449ece9..66dfb123 100644 --- a/internal/access_token_strategy.go +++ b/internal/access_token_strategy.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/oauth2 (interfaces: AccessTokenStrategy) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/authorize_code_storage.go b/internal/authorize_code_storage.go index 6d829abb..a3836812 100644 --- a/internal/authorize_code_storage.go +++ b/internal/authorize_code_storage.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/oauth2 (interfaces: AuthorizeCodeStorage) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/authorize_code_strategy.go b/internal/authorize_code_strategy.go index c2623cc1..17f64ba2 100644 --- a/internal/authorize_code_strategy.go +++ b/internal/authorize_code_strategy.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/oauth2 (interfaces: AuthorizeCodeStrategy) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/authorize_handler.go b/internal/authorize_handler.go index 9ffac1a9..a44937f1 100644 --- a/internal/authorize_handler.go +++ b/internal/authorize_handler.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite (interfaces: AuthorizeEndpointHandler) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/authorize_request.go b/internal/authorize_request.go index a4393561..f5abae42 100644 --- a/internal/authorize_request.go +++ b/internal/authorize_request.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite (interfaces: AuthorizeRequester) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/authorize_response.go b/internal/authorize_response.go index ed4c49b5..ddab7e1c 100644 --- a/internal/authorize_response.go +++ b/internal/authorize_response.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite (interfaces: AuthorizeResponder) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/client.go b/internal/client.go index 42801162..576bc551 100644 --- a/internal/client.go +++ b/internal/client.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite (interfaces: Client) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/hash.go b/internal/hash.go index 47d4da94..774f9a67 100644 --- a/internal/hash.go +++ b/internal/hash.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite (interfaces: Hasher) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/id_token_strategy.go b/internal/id_token_strategy.go index 22dde672..0bab466c 100644 --- a/internal/id_token_strategy.go +++ b/internal/id_token_strategy.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/openid (interfaces: OpenIDConnectTokenStrategy) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/introspector.go b/internal/introspector.go index 4063df7c..062246a5 100644 --- a/internal/introspector.go +++ b/internal/introspector.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite (interfaces: TokenIntrospector) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/key.go b/internal/key.go index 2bc3d5a0..743970f4 100644 --- a/internal/key.go +++ b/internal/key.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/oauth2_client_storage.go b/internal/oauth2_client_storage.go index 6434e119..b35c9c96 100644 --- a/internal/oauth2_client_storage.go +++ b/internal/oauth2_client_storage.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/oauth2 (interfaces: ClientCredentialsGrantStorage) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/oauth2_explicit_storage.go b/internal/oauth2_explicit_storage.go index 51e513cf..6356a7f7 100644 --- a/internal/oauth2_explicit_storage.go +++ b/internal/oauth2_explicit_storage.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/oauth2 (interfaces: AuthorizeCodeGrantStorage) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/oauth2_owner_storage.go b/internal/oauth2_owner_storage.go index 10737ed4..694a159d 100644 --- a/internal/oauth2_owner_storage.go +++ b/internal/oauth2_owner_storage.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/oauth2 (interfaces: ResourceOwnerPasswordCredentialsGrantStorage) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/oauth2_refresh_storage.go b/internal/oauth2_refresh_storage.go index b8750bb7..feb78dae 100644 --- a/internal/oauth2_refresh_storage.go +++ b/internal/oauth2_refresh_storage.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/oauth2 (interfaces: RefreshTokenGrantStorage) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/oauth2_revoke_storage.go b/internal/oauth2_revoke_storage.go index b3981a78..19e61755 100644 --- a/internal/oauth2_revoke_storage.go +++ b/internal/oauth2_revoke_storage.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/oauth2 (interfaces: TokenRevocationStorage) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/oauth2_storage.go b/internal/oauth2_storage.go index 611882ae..5f04e75c 100644 --- a/internal/oauth2_storage.go +++ b/internal/oauth2_storage.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/oauth2 (interfaces: CoreStorage) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/oauth2_strategy.go b/internal/oauth2_strategy.go index 198de19e..6a03c7ee 100644 --- a/internal/oauth2_strategy.go +++ b/internal/oauth2_strategy.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/oauth2 (interfaces: CoreStrategy) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/openid_id_token_storage.go b/internal/openid_id_token_storage.go index 742856e7..a7f71aa1 100644 --- a/internal/openid_id_token_storage.go +++ b/internal/openid_id_token_storage.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/openid (interfaces: OpenIDConnectRequestStorage) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/refresh_token_strategy.go b/internal/refresh_token_strategy.go index b7422cf4..2c3897cd 100644 --- a/internal/refresh_token_strategy.go +++ b/internal/refresh_token_strategy.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/oauth2 (interfaces: RefreshTokenStrategy) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/request.go b/internal/request.go index f908933a..6d0f6836 100644 --- a/internal/request.go +++ b/internal/request.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite (interfaces: Requester) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/revoke_handler.go b/internal/revoke_handler.go index 309be522..1ca9cfd0 100644 --- a/internal/revoke_handler.go +++ b/internal/revoke_handler.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite (interfaces: RevocationHandler) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/rw.go b/internal/rw.go index af37774a..0dce4267 100644 --- a/internal/rw.go +++ b/internal/rw.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: rw.go +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/storage.go b/internal/storage.go index 8b9d6dae..c5a0a5d5 100644 --- a/internal/storage.go +++ b/internal/storage.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite (interfaces: Storage) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/internal/token_handler.go b/internal/token_handler.go index d835568b..e472176a 100644 --- a/internal/token_handler.go +++ b/internal/token_handler.go @@ -1,6 +1,20 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite (interfaces: TokenEndpointHandler) +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package internal import ( diff --git a/introspect.go b/introspect.go index 0d0601b2..d8f1fe3a 100644 --- a/introspect.go +++ b/introspect.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/introspect_test.go b/introspect_test.go index e4e62c0a..ce2e2651 100644 --- a/introspect_test.go +++ b/introspect_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite_test import ( diff --git a/introspection_request_handler.go b/introspection_request_handler.go index 6afbb7e4..eadc50c9 100644 --- a/introspection_request_handler.go +++ b/introspection_request_handler.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/introspection_request_handler_test.go b/introspection_request_handler_test.go index a49eb574..7ffe889d 100644 --- a/introspection_request_handler_test.go +++ b/introspection_request_handler_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite_test import ( diff --git a/introspection_response_writer.go b/introspection_response_writer.go index 34a02bca..1d937511 100644 --- a/introspection_response_writer.go +++ b/introspection_response_writer.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/introspection_response_writer_test.go b/introspection_response_writer_test.go index f27a21ee..40eef834 100644 --- a/introspection_response_writer_test.go +++ b/introspection_response_writer_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite_test import ( diff --git a/oauth2.go b/oauth2.go index 775b5c6b..11db0bde 100644 --- a/oauth2.go +++ b/oauth2.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/request.go b/request.go index ffb566a2..7311cfec 100644 --- a/request.go +++ b/request.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/request_test.go b/request_test.go index 024dfc9d..f3bae9fc 100644 --- a/request_test.go +++ b/request_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite_test import ( diff --git a/revoke_handler.go b/revoke_handler.go index 75a0f186..aa349c06 100644 --- a/revoke_handler.go +++ b/revoke_handler.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/revoke_handler_test.go b/revoke_handler_test.go index a1eeaa61..d95c25a9 100644 --- a/revoke_handler_test.go +++ b/revoke_handler_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite_test import ( diff --git a/scope_strategy.go b/scope_strategy.go index 92789cda..a8178e62 100644 --- a/scope_strategy.go +++ b/scope_strategy.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import "strings" diff --git a/scope_strategy_test.go b/scope_strategy_test.go index 32ec6f95..512f1bb4 100644 --- a/scope_strategy_test.go +++ b/scope_strategy_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/session.go b/session.go index cc98d92f..85501237 100644 --- a/session.go +++ b/session.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/session_test.go b/session_test.go index 635649a6..bf2d52f2 100644 --- a/session_test.go +++ b/session_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite import ( diff --git a/storage.go b/storage.go index a5d3d1ce..10cea84e 100644 --- a/storage.go +++ b/storage.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package fosite // Storage defines fosite's minimal storage interface. diff --git a/storage/memory.go b/storage/memory.go index 7b2ddd8b..5f9ed39f 100644 --- a/storage/memory.go +++ b/storage/memory.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package storage import ( diff --git a/token/hmac/bytes.go b/token/hmac/bytes.go index ad84599d..32b6917f 100644 --- a/token/hmac/bytes.go +++ b/token/hmac/bytes.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package hmac import ( diff --git a/token/hmac/bytes_test.go b/token/hmac/bytes_test.go index 6d440e22..f39c57cf 100644 --- a/token/hmac/bytes_test.go +++ b/token/hmac/bytes_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package hmac import ( diff --git a/token/hmac/hmacsha.go b/token/hmac/hmacsha.go index aeae0782..9b3c1341 100644 --- a/token/hmac/hmacsha.go +++ b/token/hmac/hmacsha.go @@ -1,5 +1,19 @@ // Package hmac is the default implementation for generating and validating challenges. It uses HMAC-SHA256 to // generate and validate challenges. +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package hmac import ( diff --git a/token/hmac/hmacsha_test.go b/token/hmac/hmacsha_test.go index 154aa71c..b7e4a1cd 100644 --- a/token/hmac/hmacsha_test.go +++ b/token/hmac/hmacsha_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package hmac import ( diff --git a/token/jwt/claims.go b/token/jwt/claims.go index 4fc765e4..746a25e4 100644 --- a/token/jwt/claims.go +++ b/token/jwt/claims.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package jwt import "time" diff --git a/token/jwt/claims_id_token.go b/token/jwt/claims_id_token.go index 1e2112c5..0ccb2254 100644 --- a/token/jwt/claims_id_token.go +++ b/token/jwt/claims_id_token.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package jwt import ( diff --git a/token/jwt/claims_id_token_test.go b/token/jwt/claims_id_token_test.go index 7381bdd7..8d796949 100644 --- a/token/jwt/claims_id_token_test.go +++ b/token/jwt/claims_id_token_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package jwt_test import ( diff --git a/token/jwt/claims_jwt.go b/token/jwt/claims_jwt.go index e0518f6c..1e0a2dfe 100644 --- a/token/jwt/claims_jwt.go +++ b/token/jwt/claims_jwt.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package jwt import ( diff --git a/token/jwt/claims_jwt_test.go b/token/jwt/claims_jwt_test.go index 3d703183..2b9b2307 100644 --- a/token/jwt/claims_jwt_test.go +++ b/token/jwt/claims_jwt_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package jwt_test import ( diff --git a/token/jwt/claims_test.go b/token/jwt/claims_test.go index fbb8104c..17e381bf 100644 --- a/token/jwt/claims_test.go +++ b/token/jwt/claims_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package jwt import ( diff --git a/token/jwt/header.go b/token/jwt/header.go index 5ae7ede2..577f06cd 100644 --- a/token/jwt/header.go +++ b/token/jwt/header.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package jwt import "github.com/dgrijalva/jwt-go" diff --git a/token/jwt/header_test.go b/token/jwt/header_test.go index 209bd7c6..48b92eb9 100644 --- a/token/jwt/header_test.go +++ b/token/jwt/header_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package jwt import ( diff --git a/token/jwt/jwt.go b/token/jwt/jwt.go index 319b9f5a..4a6a7beb 100644 --- a/token/jwt/jwt.go +++ b/token/jwt/jwt.go @@ -1,5 +1,19 @@ // Package jwt is able to generate and validate json web tokens. // Follows https://tools.ietf.org/html/draft-ietf-oauth-json-web-token-32 +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package jwt import ( diff --git a/token/jwt/jwt_test.go b/token/jwt/jwt_test.go index 97414e5a..69b61afc 100644 --- a/token/jwt/jwt_test.go +++ b/token/jwt/jwt_test.go @@ -1,3 +1,17 @@ +// Copyright © 2017 Aeneas Rekkas +// +// 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. + package jwt import ( From ff751ee3691f79886ccfc6afa3936c2c3b506a9e Mon Sep 17 00:00:00 2001 From: Davor Kapsa Date: Thu, 16 Nov 2017 10:33:54 +0100 Subject: [PATCH 13/35] travis: update go version (#220) --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 14f42cd9..30d55f32 100644 --- a/.travis.yml +++ b/.travis.yml @@ -3,7 +3,7 @@ language: go go_import_path: github.com/ory/fosite go: - - 1.9 + - 1.9.x env: - DEP_VERSION="0.3.2" From 83136a3ed5ed99b3a525f0ad87d693eadf273e8a Mon Sep 17 00:00:00 2001 From: Aeneas Date: Mon, 4 Dec 2017 13:41:40 +0100 Subject: [PATCH 14/35] handler/oauth2: Client IDs in revokation requests must match now (#226) Closes #225 --- errors.go | 45 +++++++++++++++-------------- handler.go | 2 +- handler/oauth2/revocation.go | 7 ++++- handler/oauth2/revocation_test.go | 29 +++++++++++++++++-- internal/access_request.go | 14 --------- internal/access_response.go | 14 --------- internal/access_token_storage.go | 14 --------- internal/access_token_strategy.go | 14 --------- internal/authorize_code_storage.go | 14 --------- internal/authorize_code_strategy.go | 14 --------- internal/authorize_handler.go | 14 --------- internal/authorize_request.go | 14 --------- internal/authorize_response.go | 14 --------- internal/client.go | 14 --------- internal/hash.go | 14 --------- internal/id_token_strategy.go | 14 --------- internal/introspector.go | 14 --------- internal/oauth2_client_storage.go | 14 --------- internal/oauth2_owner_storage.go | 14 --------- internal/oauth2_revoke_storage.go | 14 --------- internal/oauth2_storage.go | 14 --------- internal/oauth2_strategy.go | 14 --------- internal/openid_id_token_storage.go | 14 --------- internal/refresh_token_strategy.go | 14 --------- internal/request.go | 14 --------- internal/revoke_handler.go | 22 +++----------- internal/storage.go | 14 --------- internal/token_handler.go | 14 --------- revoke_handler.go | 2 +- revoke_handler_test.go | 10 +++---- 30 files changed, 66 insertions(+), 373 deletions(-) diff --git a/errors.go b/errors.go index f35735fa..4f580faa 100644 --- a/errors.go +++ b/errors.go @@ -21,28 +21,29 @@ import ( ) var ( - ErrRequestUnauthorized = errors.New("The request could not be authorized") - ErrRequestForbidden = errors.New("The request is not allowed") - ErrInvalidRequest = errors.New("The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed") - ErrUnauthorizedClient = errors.New("The client is not authorized to request a token using this method") - ErrAccessDenied = errors.New("The resource owner or authorization server denied the request") - ErrUnsupportedResponseType = errors.New("The authorization server does not support obtaining a token using this method") - ErrInvalidScope = errors.New("The requested scope is invalid, unknown, or malformed") - ErrServerError = errors.New("The authorization server encountered an unexpected condition that prevented it from fulfilling the request") - ErrTemporarilyUnavailable = errors.New("The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server") - ErrUnsupportedGrantType = errors.New("The authorization grant type is not supported by the authorization server") - ErrInvalidGrant = errors.New("The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client") - ErrInvalidClient = errors.New("Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method)") - ErrInvalidState = errors.Errorf("The state is missing or has less than %d characters and is therefore considered too weak", MinParameterEntropy) - ErrInsufficientEntropy = errors.Errorf("The request used a security parameter (e.g., anti-replay, anti-csrf) with insufficient entropy (minimum of %d characters)", MinParameterEntropy) - ErrMisconfiguration = errors.New("The request failed because of an internal error that is probably caused by misconfiguration") - ErrNotFound = errors.New("Could not find the requested resource(s)") - ErrInvalidTokenFormat = errors.New("Invalid token format") - ErrTokenSignatureMismatch = errors.New("Token signature mismatch") - ErrTokenExpired = errors.New("Token expired") - ErrScopeNotGranted = errors.New("The token was not granted the requested scope") - ErrTokenClaim = errors.New("The token failed validation due to a claim mismatch") - ErrInactiveToken = errors.New("Token is inactive because it is malformed, expired or otherwise invalid") + ErrRequestUnauthorized = errors.New("The request could not be authorized") + ErrRequestForbidden = errors.New("The request is not allowed") + ErrInvalidRequest = errors.New("The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed") + ErrUnauthorizedClient = errors.New("The client is not authorized to request a token using this method") + ErrAccessDenied = errors.New("The resource owner or authorization server denied the request") + ErrUnsupportedResponseType = errors.New("The authorization server does not support obtaining a token using this method") + ErrInvalidScope = errors.New("The requested scope is invalid, unknown, or malformed") + ErrServerError = errors.New("The authorization server encountered an unexpected condition that prevented it from fulfilling the request") + ErrTemporarilyUnavailable = errors.New("The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server") + ErrUnsupportedGrantType = errors.New("The authorization grant type is not supported by the authorization server") + ErrInvalidGrant = errors.New("The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client") + ErrInvalidClient = errors.New("Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method)") + ErrInvalidState = errors.Errorf("The state is missing or has less than %d characters and is therefore considered too weak", MinParameterEntropy) + ErrInsufficientEntropy = errors.Errorf("The request used a security parameter (e.g., anti-replay, anti-csrf) with insufficient entropy (minimum of %d characters)", MinParameterEntropy) + ErrMisconfiguration = errors.New("The request failed because of an internal error that is probably caused by misconfiguration") + ErrNotFound = errors.New("Could not find the requested resource(s)") + ErrInvalidTokenFormat = errors.New("Invalid token format") + ErrTokenSignatureMismatch = errors.New("Token signature mismatch") + ErrTokenExpired = errors.New("Token expired") + ErrScopeNotGranted = errors.New("The token was not granted the requested scope") + ErrTokenClaim = errors.New("The token failed validation due to a claim mismatch") + ErrInactiveToken = errors.New("Token is inactive because it is malformed, expired or otherwise invalid") + ErrRevokationClientMismatch = errors.New("Token was not issued to the client making the revokation request") ) const ( diff --git a/handler.go b/handler.go index 984e3024..4e7acaa4 100644 --- a/handler.go +++ b/handler.go @@ -62,5 +62,5 @@ type TokenEndpointHandler interface { // token as well. type RevocationHandler interface { // RevokeToken handles access and refresh token revocation. - RevokeToken(ctx context.Context, token string, tokenType TokenType) error + RevokeToken(ctx context.Context, token string, tokenType TokenType, client Client) error } diff --git a/handler/oauth2/revocation.go b/handler/oauth2/revocation.go index 79d8cab1..b36fd06b 100644 --- a/handler/oauth2/revocation.go +++ b/handler/oauth2/revocation.go @@ -18,6 +18,7 @@ import ( "context" "github.com/ory/fosite" + "github.com/pkg/errors" ) type TokenRevocationHandler struct { @@ -28,7 +29,7 @@ type TokenRevocationHandler struct { // RevokeToken implements https://tools.ietf.org/html/rfc7009#section-2.1 // The token type hint indicates which token type check should be performed first. -func (r *TokenRevocationHandler) RevokeToken(ctx context.Context, token string, tokenType fosite.TokenType) error { +func (r *TokenRevocationHandler) RevokeToken(ctx context.Context, token string, tokenType fosite.TokenType, client fosite.Client) error { discoveryFuncs := []func() (request fosite.Requester, err error){ func() (request fosite.Requester, err error) { // Refresh token @@ -56,6 +57,10 @@ func (r *TokenRevocationHandler) RevokeToken(ctx context.Context, token string, return err } + if ar.GetClient().GetID() != client.GetID() { + return errors.WithStack(fosite.ErrRevokationClientMismatch) + } + requestID := ar.GetID() r.TokenRevocationStorage.RevokeRefreshToken(ctx, requestID) r.TokenRevocationStorage.RevokeAccessToken(ctx, requestID) diff --git a/handler/oauth2/revocation_test.go b/handler/oauth2/revocation_test.go index 57be6632..ce8ce941 100644 --- a/handler/oauth2/revocation_test.go +++ b/handler/oauth2/revocation_test.go @@ -45,16 +45,31 @@ func TestRevokeToken(t *testing.T) { description string mock func() expectErr error + client fosite.Client }{ + { + description: "should fail - token was issued to another client", + expectErr: fosite.ErrRevokationClientMismatch, + client: &fosite.DefaultClient{ID: "bar"}, + mock: func() { + token = "foo" + tokenType = fosite.RefreshToken + rtStrat.EXPECT().RefreshTokenSignature(token) + store.EXPECT().GetRefreshTokenSession(gomock.Any(), gomock.Any(), gomock.Any()).Return(ar, nil) + ar.EXPECT().GetClient().Return(&fosite.DefaultClient{ID: "foo"}) + }, + }, { description: "should pass - refresh token discovery first; refresh token found", expectErr: nil, + client: &fosite.DefaultClient{ID: "bar"}, mock: func() { token = "foo" tokenType = fosite.RefreshToken rtStrat.EXPECT().RefreshTokenSignature(token) store.EXPECT().GetRefreshTokenSession(gomock.Any(), gomock.Any(), gomock.Any()).Return(ar, nil) ar.EXPECT().GetID() + ar.EXPECT().GetClient().Return(&fosite.DefaultClient{ID: "bar"}) store.EXPECT().RevokeRefreshToken(gomock.Any(), gomock.Any()) store.EXPECT().RevokeAccessToken(gomock.Any(), gomock.Any()) }, @@ -62,12 +77,14 @@ func TestRevokeToken(t *testing.T) { { description: "should pass - access token discovery first; access token found", expectErr: nil, + client: &fosite.DefaultClient{ID: "bar"}, mock: func() { token = "foo" tokenType = fosite.AccessToken atStrat.EXPECT().AccessTokenSignature(token) store.EXPECT().GetAccessTokenSession(gomock.Any(), gomock.Any(), gomock.Any()).Return(ar, nil) ar.EXPECT().GetID() + ar.EXPECT().GetClient().Return(&fosite.DefaultClient{ID: "bar"}) store.EXPECT().RevokeRefreshToken(gomock.Any(), gomock.Any()) store.EXPECT().RevokeAccessToken(gomock.Any(), gomock.Any()) }, @@ -75,6 +92,7 @@ func TestRevokeToken(t *testing.T) { { description: "should pass - refresh token discovery first; refresh token not found", expectErr: nil, + client: &fosite.DefaultClient{ID: "bar"}, mock: func() { token = "foo" tokenType = fosite.AccessToken @@ -84,6 +102,7 @@ func TestRevokeToken(t *testing.T) { rtStrat.EXPECT().RefreshTokenSignature(token) store.EXPECT().GetRefreshTokenSession(gomock.Any(), gomock.Any(), gomock.Any()).Return(ar, nil) ar.EXPECT().GetID() + ar.EXPECT().GetClient().Return(&fosite.DefaultClient{ID: "bar"}) store.EXPECT().RevokeRefreshToken(gomock.Any(), gomock.Any()) store.EXPECT().RevokeAccessToken(gomock.Any(), gomock.Any()) }, @@ -91,6 +110,7 @@ func TestRevokeToken(t *testing.T) { { description: "should pass - access token discovery first; access token not found", expectErr: nil, + client: &fosite.DefaultClient{ID: "bar"}, mock: func() { token = "foo" tokenType = fosite.RefreshToken @@ -100,13 +120,15 @@ func TestRevokeToken(t *testing.T) { atStrat.EXPECT().AccessTokenSignature(token) store.EXPECT().GetAccessTokenSession(gomock.Any(), gomock.Any(), gomock.Any()).Return(ar, nil) ar.EXPECT().GetID() + ar.EXPECT().GetClient().Return(&fosite.DefaultClient{ID: "bar"}) store.EXPECT().RevokeRefreshToken(gomock.Any(), gomock.Any()) store.EXPECT().RevokeAccessToken(gomock.Any(), gomock.Any()) }, }, { - description: "should pass - refresh token discovery first; both tokens not found", + description: "should fail - refresh token discovery first; both tokens not found", expectErr: fosite.ErrNotFound, + client: &fosite.DefaultClient{ID: "bar"}, mock: func() { token = "foo" tokenType = fosite.RefreshToken @@ -118,8 +140,9 @@ func TestRevokeToken(t *testing.T) { }, }, { - description: "should pass - access token discovery first; both tokens not found", + description: "should fail - access token discovery first; both tokens not found", expectErr: fosite.ErrNotFound, + client: &fosite.DefaultClient{ID: "bar"}, mock: func() { token = "foo" tokenType = fosite.AccessToken @@ -132,7 +155,7 @@ func TestRevokeToken(t *testing.T) { }, } { c.mock() - err := h.RevokeToken(nil, token, tokenType) + err := h.RevokeToken(nil, token, tokenType, c.client) assert.True(t, errors.Cause(err) == c.expectErr, "(%d) %s\n%s\n%s", k, c.description, err, c.expectErr) t.Logf("Passed test case %d", k) } diff --git a/internal/access_request.go b/internal/access_request.go index 78cf7249..136ab8f9 100644 --- a/internal/access_request.go +++ b/internal/access_request.go @@ -1,20 +1,6 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite (interfaces: AccessRequester) -// Copyright © 2017 Aeneas Rekkas -// -// 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. - package internal import ( diff --git a/internal/access_response.go b/internal/access_response.go index 53636108..802cdc03 100644 --- a/internal/access_response.go +++ b/internal/access_response.go @@ -1,20 +1,6 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite (interfaces: AccessResponder) -// Copyright © 2017 Aeneas Rekkas -// -// 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. - package internal import ( diff --git a/internal/access_token_storage.go b/internal/access_token_storage.go index c587dfed..014a6f1e 100644 --- a/internal/access_token_storage.go +++ b/internal/access_token_storage.go @@ -1,20 +1,6 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/oauth2 (interfaces: AccessTokenStorage) -// Copyright © 2017 Aeneas Rekkas -// -// 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. - package internal import ( diff --git a/internal/access_token_strategy.go b/internal/access_token_strategy.go index 66dfb123..2449ece9 100644 --- a/internal/access_token_strategy.go +++ b/internal/access_token_strategy.go @@ -1,20 +1,6 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/oauth2 (interfaces: AccessTokenStrategy) -// Copyright © 2017 Aeneas Rekkas -// -// 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. - package internal import ( diff --git a/internal/authorize_code_storage.go b/internal/authorize_code_storage.go index a3836812..6d829abb 100644 --- a/internal/authorize_code_storage.go +++ b/internal/authorize_code_storage.go @@ -1,20 +1,6 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/oauth2 (interfaces: AuthorizeCodeStorage) -// Copyright © 2017 Aeneas Rekkas -// -// 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. - package internal import ( diff --git a/internal/authorize_code_strategy.go b/internal/authorize_code_strategy.go index 17f64ba2..c2623cc1 100644 --- a/internal/authorize_code_strategy.go +++ b/internal/authorize_code_strategy.go @@ -1,20 +1,6 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/oauth2 (interfaces: AuthorizeCodeStrategy) -// Copyright © 2017 Aeneas Rekkas -// -// 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. - package internal import ( diff --git a/internal/authorize_handler.go b/internal/authorize_handler.go index a44937f1..9ffac1a9 100644 --- a/internal/authorize_handler.go +++ b/internal/authorize_handler.go @@ -1,20 +1,6 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite (interfaces: AuthorizeEndpointHandler) -// Copyright © 2017 Aeneas Rekkas -// -// 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. - package internal import ( diff --git a/internal/authorize_request.go b/internal/authorize_request.go index f5abae42..a4393561 100644 --- a/internal/authorize_request.go +++ b/internal/authorize_request.go @@ -1,20 +1,6 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite (interfaces: AuthorizeRequester) -// Copyright © 2017 Aeneas Rekkas -// -// 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. - package internal import ( diff --git a/internal/authorize_response.go b/internal/authorize_response.go index ddab7e1c..ed4c49b5 100644 --- a/internal/authorize_response.go +++ b/internal/authorize_response.go @@ -1,20 +1,6 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite (interfaces: AuthorizeResponder) -// Copyright © 2017 Aeneas Rekkas -// -// 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. - package internal import ( diff --git a/internal/client.go b/internal/client.go index 576bc551..42801162 100644 --- a/internal/client.go +++ b/internal/client.go @@ -1,20 +1,6 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite (interfaces: Client) -// Copyright © 2017 Aeneas Rekkas -// -// 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. - package internal import ( diff --git a/internal/hash.go b/internal/hash.go index 774f9a67..47d4da94 100644 --- a/internal/hash.go +++ b/internal/hash.go @@ -1,20 +1,6 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite (interfaces: Hasher) -// Copyright © 2017 Aeneas Rekkas -// -// 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. - package internal import ( diff --git a/internal/id_token_strategy.go b/internal/id_token_strategy.go index 0bab466c..22dde672 100644 --- a/internal/id_token_strategy.go +++ b/internal/id_token_strategy.go @@ -1,20 +1,6 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/openid (interfaces: OpenIDConnectTokenStrategy) -// Copyright © 2017 Aeneas Rekkas -// -// 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. - package internal import ( diff --git a/internal/introspector.go b/internal/introspector.go index 062246a5..4063df7c 100644 --- a/internal/introspector.go +++ b/internal/introspector.go @@ -1,20 +1,6 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite (interfaces: TokenIntrospector) -// Copyright © 2017 Aeneas Rekkas -// -// 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. - package internal import ( diff --git a/internal/oauth2_client_storage.go b/internal/oauth2_client_storage.go index b35c9c96..6434e119 100644 --- a/internal/oauth2_client_storage.go +++ b/internal/oauth2_client_storage.go @@ -1,20 +1,6 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/oauth2 (interfaces: ClientCredentialsGrantStorage) -// Copyright © 2017 Aeneas Rekkas -// -// 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. - package internal import ( diff --git a/internal/oauth2_owner_storage.go b/internal/oauth2_owner_storage.go index 694a159d..10737ed4 100644 --- a/internal/oauth2_owner_storage.go +++ b/internal/oauth2_owner_storage.go @@ -1,20 +1,6 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/oauth2 (interfaces: ResourceOwnerPasswordCredentialsGrantStorage) -// Copyright © 2017 Aeneas Rekkas -// -// 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. - package internal import ( diff --git a/internal/oauth2_revoke_storage.go b/internal/oauth2_revoke_storage.go index 19e61755..b3981a78 100644 --- a/internal/oauth2_revoke_storage.go +++ b/internal/oauth2_revoke_storage.go @@ -1,20 +1,6 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/oauth2 (interfaces: TokenRevocationStorage) -// Copyright © 2017 Aeneas Rekkas -// -// 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. - package internal import ( diff --git a/internal/oauth2_storage.go b/internal/oauth2_storage.go index 5f04e75c..611882ae 100644 --- a/internal/oauth2_storage.go +++ b/internal/oauth2_storage.go @@ -1,20 +1,6 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/oauth2 (interfaces: CoreStorage) -// Copyright © 2017 Aeneas Rekkas -// -// 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. - package internal import ( diff --git a/internal/oauth2_strategy.go b/internal/oauth2_strategy.go index 6a03c7ee..198de19e 100644 --- a/internal/oauth2_strategy.go +++ b/internal/oauth2_strategy.go @@ -1,20 +1,6 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/oauth2 (interfaces: CoreStrategy) -// Copyright © 2017 Aeneas Rekkas -// -// 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. - package internal import ( diff --git a/internal/openid_id_token_storage.go b/internal/openid_id_token_storage.go index a7f71aa1..742856e7 100644 --- a/internal/openid_id_token_storage.go +++ b/internal/openid_id_token_storage.go @@ -1,20 +1,6 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/openid (interfaces: OpenIDConnectRequestStorage) -// Copyright © 2017 Aeneas Rekkas -// -// 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. - package internal import ( diff --git a/internal/refresh_token_strategy.go b/internal/refresh_token_strategy.go index 2c3897cd..b7422cf4 100644 --- a/internal/refresh_token_strategy.go +++ b/internal/refresh_token_strategy.go @@ -1,20 +1,6 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite/handler/oauth2 (interfaces: RefreshTokenStrategy) -// Copyright © 2017 Aeneas Rekkas -// -// 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. - package internal import ( diff --git a/internal/request.go b/internal/request.go index 6d0f6836..f908933a 100644 --- a/internal/request.go +++ b/internal/request.go @@ -1,20 +1,6 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite (interfaces: Requester) -// Copyright © 2017 Aeneas Rekkas -// -// 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. - package internal import ( diff --git a/internal/revoke_handler.go b/internal/revoke_handler.go index 1ca9cfd0..82f9134b 100644 --- a/internal/revoke_handler.go +++ b/internal/revoke_handler.go @@ -1,20 +1,6 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite (interfaces: RevocationHandler) -// Copyright © 2017 Aeneas Rekkas -// -// 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. - package internal import ( @@ -45,12 +31,12 @@ func (_m *MockRevocationHandler) EXPECT() *_MockRevocationHandlerRecorder { return _m.recorder } -func (_m *MockRevocationHandler) RevokeToken(_param0 context.Context, _param1 string, _param2 fosite.TokenType) error { - ret := _m.ctrl.Call(_m, "RevokeToken", _param0, _param1, _param2) +func (_m *MockRevocationHandler) RevokeToken(_param0 context.Context, _param1 string, _param2 fosite.TokenType, _param3 fosite.Client) error { + ret := _m.ctrl.Call(_m, "RevokeToken", _param0, _param1, _param2, _param3) ret0, _ := ret[0].(error) return ret0 } -func (_mr *_MockRevocationHandlerRecorder) RevokeToken(arg0, arg1, arg2 interface{}) *gomock.Call { - return _mr.mock.ctrl.RecordCall(_mr.mock, "RevokeToken", arg0, arg1, arg2) +func (_mr *_MockRevocationHandlerRecorder) RevokeToken(arg0, arg1, arg2, arg3 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCall(_mr.mock, "RevokeToken", arg0, arg1, arg2, arg3) } diff --git a/internal/storage.go b/internal/storage.go index c5a0a5d5..8b9d6dae 100644 --- a/internal/storage.go +++ b/internal/storage.go @@ -1,20 +1,6 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite (interfaces: Storage) -// Copyright © 2017 Aeneas Rekkas -// -// 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. - package internal import ( diff --git a/internal/token_handler.go b/internal/token_handler.go index e472176a..d835568b 100644 --- a/internal/token_handler.go +++ b/internal/token_handler.go @@ -1,20 +1,6 @@ // Automatically generated by MockGen. DO NOT EDIT! // Source: github.com/ory/fosite (interfaces: TokenEndpointHandler) -// Copyright © 2017 Aeneas Rekkas -// -// 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. - package internal import ( diff --git a/revoke_handler.go b/revoke_handler.go index aa349c06..b53438b1 100644 --- a/revoke_handler.go +++ b/revoke_handler.go @@ -70,7 +70,7 @@ func (f *Fosite) NewRevocationRequest(ctx context.Context, r *http.Request) erro var found bool for _, loader := range f.RevocationHandlers { - if err := loader.RevokeToken(ctx, token, tokenTypeHint); err == nil { + if err := loader.RevokeToken(ctx, token, tokenTypeHint, client); err == nil { found = true } else if errors.Cause(err) == ErrUnknownRequest { // do nothing diff --git a/revoke_handler_test.go b/revoke_handler_test.go index d95c25a9..697366b4 100644 --- a/revoke_handler_test.go +++ b/revoke_handler_test.go @@ -108,7 +108,7 @@ func TestNewRevocationRequest(t *testing.T) { client.EXPECT().GetHashedSecret().Return([]byte("foo")) client.EXPECT().IsPublic().Return(false) hasher.EXPECT().Compare(gomock.Eq([]byte("foo")), gomock.Eq([]byte("bar"))).Return(nil) - handler.EXPECT().RevokeToken(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + handler.EXPECT().RevokeToken(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) }, handlers: RevocationHandlers{handler}, }, @@ -127,7 +127,7 @@ func TestNewRevocationRequest(t *testing.T) { client.EXPECT().GetHashedSecret().Return([]byte("foo")) client.EXPECT().IsPublic().Return(false) hasher.EXPECT().Compare(gomock.Eq([]byte("foo")), gomock.Eq([]byte("bar"))).Return(nil) - handler.EXPECT().RevokeToken(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + handler.EXPECT().RevokeToken(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) }, handlers: RevocationHandlers{handler}, }, @@ -145,7 +145,7 @@ func TestNewRevocationRequest(t *testing.T) { store.EXPECT().GetClient(gomock.Any(), gomock.Eq("foo")).Return(client, nil) client.EXPECT().IsPublic().Return(true) hasher.EXPECT().Compare(gomock.Eq([]byte("foo")), gomock.Eq([]byte("bar"))).Return(nil) - handler.EXPECT().RevokeToken(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + handler.EXPECT().RevokeToken(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) }, handlers: RevocationHandlers{handler}, }, @@ -163,7 +163,7 @@ func TestNewRevocationRequest(t *testing.T) { store.EXPECT().GetClient(gomock.Any(), gomock.Eq("foo")).Return(client, nil) client.EXPECT().GetHashedSecret().Return([]byte("foo")) client.EXPECT().IsPublic().Return(false) - handler.EXPECT().RevokeToken(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + handler.EXPECT().RevokeToken(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) }, handlers: RevocationHandlers{handler}, }, @@ -182,7 +182,7 @@ func TestNewRevocationRequest(t *testing.T) { client.EXPECT().GetHashedSecret().Return([]byte("foo")) client.EXPECT().IsPublic().Return(false) hasher.EXPECT().Compare(gomock.Eq([]byte("foo")), gomock.Eq([]byte("bar"))).Return(nil) - handler.EXPECT().RevokeToken(gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) + handler.EXPECT().RevokeToken(gomock.Any(), gomock.Any(), gomock.Any(), gomock.Any()).Return(nil) }, handlers: RevocationHandlers{handler}, }, From 8961d861814862f9432f0608bcd14dfbcd4ec979 Mon Sep 17 00:00:00 2001 From: Aeneas Date: Wed, 6 Dec 2017 15:05:22 +0100 Subject: [PATCH 15/35] Simplifies error contexts (#227) Simplifies how errors are instantiated. Errors now contain all necessary information without relying on `fosite.ErrorToRFC6749Error` any more. `fosite.ErrorToRFC6749Error` is now an internal method and was renamed to `fosite.errorToRFC6749Error`. --- access_error.go | 4 +- access_error_test.go | 4 +- authorize_error.go | 2 +- errors.go | 410 +++++++++++---------------- errors_test.go | 40 --- integration/helper_endpoints_test.go | 17 +- revoke_handler.go | 5 +- 7 files changed, 180 insertions(+), 302 deletions(-) delete mode 100644 errors_test.go diff --git a/access_error.go b/access_error.go index 09ce8c4b..f4165738 100644 --- a/access_error.go +++ b/access_error.go @@ -27,8 +27,8 @@ func (c *Fosite) WriteAccessError(rw http.ResponseWriter, _ AccessRequester, err func writeJsonError(rw http.ResponseWriter, err error) { rw.Header().Set("Content-Type", "application/json;charset=UTF-8") - rfcerr := ErrorToRFC6749Error(err) - js, err := json.Marshal(rfcerr) + rfcerr := errorToRFC6749Error(err) + js, err := json.Marshal(err) if err != nil { http.Error(rw, fmt.Sprintf(`{"error": "%s"}`, err.Error()), http.StatusInternalServerError) return diff --git a/access_error_test.go b/access_error_test.go index e917950f..90b47623 100644 --- a/access_error_test.go +++ b/access_error_test.go @@ -47,7 +47,7 @@ func TestWriteAccessError_RFC6749(t *testing.T) { f := &Fosite{} for k, c := range []struct { - err error + err *RFC6749Error code string }{ {ErrInvalidRequest, "invalid_request"}, @@ -70,6 +70,6 @@ func TestWriteAccessError_RFC6749(t *testing.T) { require.NoError(t, err, "(%d) %s", k, c.code) assert.Equal(t, c.code, params.Error, "(%d) %s: error", k, c.code) - assert.Equal(t, c.err.Error(), params.Description, "(%d) %s: description", k, c.code) + assert.Equal(t, c.err.Description, params.Description, "(%d) %s: description", k, c.code) } } diff --git a/authorize_error.go b/authorize_error.go index eaa41d48..ece1648a 100644 --- a/authorize_error.go +++ b/authorize_error.go @@ -21,7 +21,7 @@ import ( ) func (c *Fosite) WriteAuthorizeError(rw http.ResponseWriter, ar AuthorizeRequester, err error) { - rfcerr := ErrorToRFC6749Error(err) + rfcerr := errorToRFC6749Error(err) if !ar.IsRedirectURIValid() { js, err := json.MarshalIndent(rfcerr, "", "\t") if err != nil { diff --git a/errors.go b/errors.go index 4f580faa..35885478 100644 --- a/errors.go +++ b/errors.go @@ -15,63 +15,182 @@ package fosite import ( + "fmt" "net/http" "github.com/pkg/errors" ) var ( - ErrRequestUnauthorized = errors.New("The request could not be authorized") - ErrRequestForbidden = errors.New("The request is not allowed") - ErrInvalidRequest = errors.New("The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed") - ErrUnauthorizedClient = errors.New("The client is not authorized to request a token using this method") - ErrAccessDenied = errors.New("The resource owner or authorization server denied the request") - ErrUnsupportedResponseType = errors.New("The authorization server does not support obtaining a token using this method") - ErrInvalidScope = errors.New("The requested scope is invalid, unknown, or malformed") - ErrServerError = errors.New("The authorization server encountered an unexpected condition that prevented it from fulfilling the request") - ErrTemporarilyUnavailable = errors.New("The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server") - ErrUnsupportedGrantType = errors.New("The authorization grant type is not supported by the authorization server") - ErrInvalidGrant = errors.New("The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client") - ErrInvalidClient = errors.New("Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method)") - ErrInvalidState = errors.Errorf("The state is missing or has less than %d characters and is therefore considered too weak", MinParameterEntropy) - ErrInsufficientEntropy = errors.Errorf("The request used a security parameter (e.g., anti-replay, anti-csrf) with insufficient entropy (minimum of %d characters)", MinParameterEntropy) - ErrMisconfiguration = errors.New("The request failed because of an internal error that is probably caused by misconfiguration") - ErrNotFound = errors.New("Could not find the requested resource(s)") - ErrInvalidTokenFormat = errors.New("Invalid token format") - ErrTokenSignatureMismatch = errors.New("Token signature mismatch") - ErrTokenExpired = errors.New("Token expired") - ErrScopeNotGranted = errors.New("The token was not granted the requested scope") - ErrTokenClaim = errors.New("The token failed validation due to a claim mismatch") - ErrInactiveToken = errors.New("Token is inactive because it is malformed, expired or otherwise invalid") - ErrRevokationClientMismatch = errors.New("Token was not issued to the client making the revokation request") + ErrRequestForbidden = &RFC6749Error{ + Name: errRequestForbidden, + Description: "The request is not allowed", + Hint: "You are not allowed to perform this action.", + Code: http.StatusForbidden, + } + ErrInvalidRequest = &RFC6749Error{ + Name: errInvalidRequestName, + Description: "The request is missing a required parameter, includes an invalid parameter value, includes a parameter more than once, or is otherwise malformed", + Hint: "Make sure that the various parameters are correct, be aware of case sensitivity and trim your parameters. Make sure that the client you are using has exactly whitelisted the redirect_uri you specified.", + Code: http.StatusBadRequest, + } + ErrUnauthorizedClient = &RFC6749Error{ + Name: errUnauthorizedClientName, + Description: "The client is not authorized to request a token using this method", + Hint: "Make sure that client id and secret are correctly specified and that the client exists.", + Code: http.StatusUnauthorized, + } + ErrAccessDenied = &RFC6749Error{ + Name: errAccessDeniedName, + Description: "The resource owner or authorization server denied the request", + Hint: "Make sure that the request you are making is valid. Maybe the credential or request parameters you are using are limited in scope or otherwise restricted.", + Code: http.StatusForbidden, + } + ErrUnsupportedResponseType = &RFC6749Error{ + Name: errUnsupportedResponseTypeName, + Description: "The authorization server does not support obtaining a token using this method", + Code: http.StatusBadRequest, + } + ErrInvalidScope = &RFC6749Error{ + Name: errInvalidScopeName, + Description: "The requested scope is invalid, unknown, or malformed", + Code: http.StatusBadRequest, + } + ErrServerError = &RFC6749Error{ + Name: errServerErrorName, + Description: "The authorization server encountered an unexpected condition that prevented it from fulfilling the request", + Code: http.StatusInternalServerError, + } + ErrTemporarilyUnavailable = &RFC6749Error{ + Name: errTemporarilyUnavailableName, + Description: "The authorization server is currently unable to handle the request due to a temporary overloading or maintenance of the server", + Code: http.StatusServiceUnavailable, + } + ErrUnsupportedGrantType = &RFC6749Error{ + Name: errUnsupportedGrantTypeName, + Description: "The authorization grant type is not supported by the authorization server", + Code: http.StatusBadRequest, + } + ErrInvalidGrant = &RFC6749Error{ + Name: errInvalidGrantName, + Description: "The provided authorization grant (e.g., authorization code, resource owner credentials) or refresh token is invalid, expired, revoked, does not match the redirection URI used in the authorization request, or was issued to another client", + Code: http.StatusBadRequest, + } + ErrInvalidClient = &RFC6749Error{ + Name: errInvalidClientName, + Description: "Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method)", + Code: http.StatusForbidden, + } + ErrInvalidState = &RFC6749Error{ + Name: errInvalidStateName, + Description: fmt.Sprintf("The state is missing or has less than %d characters and is therefore considered too weak", MinParameterEntropy), + Code: http.StatusBadRequest, + } + ErrMisconfiguration = &RFC6749Error{ + Name: errMisconfigurationName, + Description: "The request failed because of an internal error that is probably caused by misconfiguration", + Code: http.StatusInternalServerError, + } + ErrInsufficientEntropy = &RFC6749Error{ + Name: errInsufficientEntropyName, + Description: fmt.Sprintf("The request used a security parameter (e.g., anti-replay, anti-csrf) with insufficient entropy (minimum of %d characters)", MinParameterEntropy), + Code: http.StatusBadRequest, + } + ErrNotFound = &RFC6749Error{ + Name: errNotFoundName, + Description: "Could not find the requested resource(s)", + Code: http.StatusNotFound, + } + ErrRequestUnauthorized = &RFC6749Error{ + Name: errRequestUnauthorizedName, + Description: "The request could not be authorized", + Hint: "Check that you provided valid credentials in the right format.", + Code: http.StatusUnauthorized, + } + ErrTokenSignatureMismatch = &RFC6749Error{ + Name: errTokenSignatureMismatchName, + Description: "Token signature mismatch", + Hint: "Check that you provided a valid token in the right format.", + Code: http.StatusBadRequest, + } + ErrInvalidTokenFormat = &RFC6749Error{ + Name: errInvalidTokenFormatName, + Description: "Invalid token format", + Hint: "Check that you provided a valid token in the right format.", + Code: http.StatusBadRequest, + } + ErrTokenExpired = &RFC6749Error{ + Name: errTokenExpiredName, + Description: "Token expired", + Hint: "The token expired.", + Code: http.StatusUnauthorized, + } + ErrScopeNotGranted = &RFC6749Error{ + Name: errScopeNotGrantedName, + Description: "The token was not granted the requested scope", + Hint: "The resource owner did not grant the requested scope.", + Code: http.StatusForbidden, + } + ErrTokenClaim = &RFC6749Error{ + Name: errTokenClaimName, + Description: "The token failed validation due to a claim mismatch", + Hint: "One or more token claims failed validation.", + Code: http.StatusUnauthorized, + } + ErrInactiveToken = &RFC6749Error{ + Name: errTokenInactiveName, + Description: "Token is inactive because it is malformed, expired or otherwise invalid", + Hint: "Token validation failed.", + Code: http.StatusUnauthorized, + } + ErrRevokationClientMismatch = &RFC6749Error{ + Name: errRevokationClientMismatchName, + Description: "Token was not issued to the client making the revokation request", + Code: http.StatusBadRequest, + } ) const ( - errRequestUnauthorized = "request_unauthorized" - errRequestForbidden = "request_forbidden" - errInvalidRequestName = "invalid_request" - errUnauthorizedClientName = "unauthorized_client" - errAccessDeniedName = "access_denied" - errUnsupportedResponseTypeName = "unsupported_response_type" - errInvalidScopeName = "invalid_scope" - errServerErrorName = "server_error" - errTemporarilyUnavailableName = "temporarily_unavailable" - errUnsupportedGrantTypeName = "unsupported_grant_type" - errInvalidGrantName = "invalid_grant" - errInvalidClientName = "invalid_client" - UnknownErrorName = "unknown_error" - errNotFound = "not_found" - errInvalidState = "invalid_state" - errMisconfiguration = "misconfiguration" - errInsufficientEntropy = "insufficient_entropy" - errInvalidTokenFormat = "invalid_token" - errTokenSignatureMismatch = "token_signature_mismatch" - errTokenExpired = "token_expired" - errScopeNotGranted = "scope_not_granted" - errTokenClaim = "token_claim" - errTokenInactive = "token_inactive" + errRequestUnauthorizedName = "request_unauthorized" + errRequestForbidden = "request_forbidden" + errInvalidRequestName = "invalid_request" + errUnauthorizedClientName = "unauthorized_client" + errAccessDeniedName = "access_denied" + errUnsupportedResponseTypeName = "unsupported_response_type" + errInvalidScopeName = "invalid_scope" + errServerErrorName = "server_error" + errTemporarilyUnavailableName = "temporarily_unavailable" + errUnsupportedGrantTypeName = "unsupported_grant_type" + errInvalidGrantName = "invalid_grant" + errInvalidClientName = "invalid_client" + errNotFoundName = "not_found" + errInvalidStateName = "invalid_state" + errMisconfigurationName = "misconfiguration" + errInsufficientEntropyName = "insufficient_entropy" + errInvalidTokenFormatName = "invalid_token" + errTokenSignatureMismatchName = "token_signature_mismatch" + errTokenExpiredName = "token_expired" + errScopeNotGrantedName = "scope_not_granted" + errTokenClaimName = "token_claim" + errTokenInactiveName = "token_inactive" + errUnknownErrorName = "error" + errRevokationClientMismatchName = "revokation_client_mismatch" ) +func errorToRFC6749Error(err error) *RFC6749Error { + if e, ok := err.(*RFC6749Error); ok { + return e + } else if e, ok := errors.Cause(err).(*RFC6749Error); ok { + return e + } + return &RFC6749Error{ + Name: errUnknownErrorName, + Description: "The error is unrecognizable.", + Debug: err.Error(), + Code: http.StatusInternalServerError, + } +} + type RFC6749Error struct { Name string `json:"error"` Description string `json:"error_description"` @@ -80,205 +199,6 @@ type RFC6749Error struct { Debug string `json:"-"` } -func ErrorToRFC6749Error(err error) *RFC6749Error { - if e, ok := err.(*RFC6749Error); ok { - return e - } - - switch errors.Cause(err) { - case ErrInactiveToken: - { - { - return &RFC6749Error{ - Name: errTokenInactive, - Description: ErrInactiveToken.Error(), - Debug: err.Error(), - Hint: "Token validation failed.", - Code: http.StatusUnauthorized, - } - } - } - case ErrTokenClaim: - { - return &RFC6749Error{ - Name: errTokenClaim, - Description: ErrTokenClaim.Error(), - Debug: err.Error(), - Hint: "One or more token claims failed validation.", - Code: http.StatusUnauthorized, - } - } - case ErrScopeNotGranted: - { - return &RFC6749Error{ - Name: errScopeNotGranted, - Description: ErrScopeNotGranted.Error(), - Debug: err.Error(), - Hint: "The resource owner did not grant the requested scope.", - Code: http.StatusForbidden, - } - } - case ErrTokenExpired: - { - return &RFC6749Error{ - Name: errTokenExpired, - Description: ErrTokenExpired.Error(), - Debug: err.Error(), - Hint: "The token expired.", - Code: http.StatusUnauthorized, - } - } - case ErrInvalidTokenFormat: - { - return &RFC6749Error{ - Name: errInvalidTokenFormat, - Description: ErrInvalidTokenFormat.Error(), - Debug: err.Error(), - Hint: "Check that you provided a valid token in the right format.", - Code: http.StatusBadRequest, - } - } - case ErrTokenSignatureMismatch: - { - return &RFC6749Error{ - Name: errTokenSignatureMismatch, - Description: ErrTokenSignatureMismatch.Error(), - Debug: err.Error(), - Hint: "Check that you provided a valid token in the right format.", - Code: http.StatusBadRequest, - } - } - case ErrRequestUnauthorized: - { - return &RFC6749Error{ - Name: errRequestUnauthorized, - Description: ErrRequestUnauthorized.Error(), - Debug: err.Error(), - Hint: "Check that you provided valid credentials in the right format.", - Code: http.StatusUnauthorized, - } - } - case ErrRequestForbidden: - { - return &RFC6749Error{ - Name: errRequestForbidden, - Description: ErrRequestForbidden.Error(), - Debug: err.Error(), - Hint: "You are not allowed to perform this action.", - Code: http.StatusForbidden, - } - } - case ErrInvalidRequest: - return &RFC6749Error{ - Name: errInvalidRequestName, - Description: ErrInvalidRequest.Error(), - Debug: err.Error(), - Hint: "Make sure that the various parameters are correct, be aware of case sensitivity and trim your parameters. Make sure that the client you are using has exactly whitelisted the redirect_uri you specified.", - Code: http.StatusBadRequest, - } - case ErrUnauthorizedClient: - return &RFC6749Error{ - Name: errUnauthorizedClientName, - Description: ErrUnauthorizedClient.Error(), - Debug: err.Error(), - Hint: "Make sure that client id and secret are correctly specified and that the client exists.", - Code: http.StatusUnauthorized, - } - case ErrAccessDenied: - return &RFC6749Error{ - Name: errAccessDeniedName, - Description: ErrAccessDenied.Error(), - Debug: err.Error(), - Hint: "Make sure that the request you are making is valid. Maybe the credential or request parameters you are using are limited in scope or otherwise restricted.", - Code: http.StatusForbidden, - } - case ErrUnsupportedResponseType: - return &RFC6749Error{ - Name: errUnsupportedResponseTypeName, - Description: ErrUnsupportedResponseType.Error(), - Debug: err.Error(), - Code: http.StatusBadRequest, - } - case ErrInvalidScope: - return &RFC6749Error{ - Name: errInvalidScopeName, - Description: ErrInvalidScope.Error(), - Debug: err.Error(), - Code: http.StatusBadRequest, - } - case ErrServerError: - return &RFC6749Error{ - Name: errServerErrorName, - Description: ErrServerError.Error(), - Debug: err.Error(), - Code: http.StatusInternalServerError, - } - case ErrTemporarilyUnavailable: - return &RFC6749Error{ - Name: errTemporarilyUnavailableName, - Description: ErrTemporarilyUnavailable.Error(), - Debug: err.Error(), - Code: http.StatusServiceUnavailable, - } - case ErrUnsupportedGrantType: - return &RFC6749Error{ - Name: errUnsupportedGrantTypeName, - Description: ErrUnsupportedGrantType.Error(), - Debug: err.Error(), - Code: http.StatusBadRequest, - } - case ErrInvalidGrant: - return &RFC6749Error{ - Name: errInvalidGrantName, - Description: ErrInvalidGrant.Error(), - Debug: err.Error(), - Code: http.StatusBadRequest, - } - case ErrInvalidClient: - return &RFC6749Error{ - Name: errInvalidClientName, - Description: ErrInvalidClient.Error(), - Debug: err.Error(), - Code: http.StatusUnauthorized, - } - case ErrInvalidState: - return &RFC6749Error{ - Name: errInvalidState, - Description: ErrInvalidState.Error(), - Debug: err.Error(), - Code: http.StatusBadRequest, - } - case ErrInsufficientEntropy: - return &RFC6749Error{ - Name: errInsufficientEntropy, - Description: ErrInsufficientEntropy.Error(), - Debug: err.Error(), - Code: http.StatusBadRequest, - } - case ErrMisconfiguration: - return &RFC6749Error{ - Name: errMisconfiguration, - Description: ErrMisconfiguration.Error(), - Debug: err.Error(), - Code: http.StatusInternalServerError, - } - case ErrNotFound: - return &RFC6749Error{ - Name: errNotFound, - Description: ErrNotFound.Error(), - Debug: err.Error(), - Code: http.StatusNotFound, - } - default: - return &RFC6749Error{ - Name: UnknownErrorName, - Description: "The error is unrecognizable.", - Debug: err.Error(), - Code: http.StatusInternalServerError, - } - } -} - func (e *RFC6749Error) Status() string { return http.StatusText(e.Code) } diff --git a/errors_test.go b/errors_test.go deleted file mode 100644 index 65d86ba4..00000000 --- a/errors_test.go +++ /dev/null @@ -1,40 +0,0 @@ -// Copyright © 2017 Aeneas Rekkas -// -// 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. - -package fosite - -import ( - native "errors" - "testing" - - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" -) - -func TestErrorToRFC6749(t *testing.T) { - assert.Equal(t, UnknownErrorName, ErrorToRFC6749Error(errors.New("")).Name) - assert.Equal(t, UnknownErrorName, ErrorToRFC6749Error(native.New("")).Name) - - assert.Equal(t, errInvalidRequestName, ErrorToRFC6749Error(errors.WithStack(ErrInvalidRequest)).Name) - assert.Equal(t, errUnauthorizedClientName, ErrorToRFC6749Error(errors.WithStack(ErrUnauthorizedClient)).Name) - assert.Equal(t, errAccessDeniedName, ErrorToRFC6749Error(errors.WithStack(ErrAccessDenied)).Name) - assert.Equal(t, errUnsupportedResponseTypeName, ErrorToRFC6749Error(errors.WithStack(ErrUnsupportedResponseType)).Name) - assert.Equal(t, errInvalidScopeName, ErrorToRFC6749Error(errors.WithStack(ErrInvalidScope)).Name) - assert.Equal(t, errServerErrorName, ErrorToRFC6749Error(errors.WithStack(ErrServerError)).Name) - assert.Equal(t, errTemporarilyUnavailableName, ErrorToRFC6749Error(errors.WithStack(ErrTemporarilyUnavailable)).Name) - assert.Equal(t, errUnsupportedGrantTypeName, ErrorToRFC6749Error(errors.WithStack(ErrUnsupportedGrantType)).Name) - assert.Equal(t, errInvalidGrantName, ErrorToRFC6749Error(errors.WithStack(ErrInvalidGrant)).Name) - assert.Equal(t, errInvalidClientName, ErrorToRFC6749Error(errors.WithStack(ErrInvalidClient)).Name) - assert.Equal(t, errInvalidState, ErrorToRFC6749Error(errors.WithStack(ErrInvalidState)).Name) -} diff --git a/integration/helper_endpoints_test.go b/integration/helper_endpoints_test.go index 2378b6d5..4600eb08 100644 --- a/integration/helper_endpoints_test.go +++ b/integration/helper_endpoints_test.go @@ -34,7 +34,7 @@ func tokenRevocationHandler(t *testing.T, oauth2 fosite.OAuth2Provider, session err := oauth2.NewRevocationRequest(ctx, req) if err != nil { t.Logf("Revoke request failed because %s.", err.Error()) - t.Logf("Stack: %v", err.(stackTracer).StackTrace()) + // t.Logf("Stack: %v", err.(stackTracer).StackTrace()) } oauth2.WriteRevocationResponse(rw, err) } @@ -46,7 +46,7 @@ func tokenIntrospectionHandler(t *testing.T, oauth2 fosite.OAuth2Provider, sessi ar, err := oauth2.NewIntrospectionRequest(ctx, req, session) if err != nil { t.Logf("Introspection request failed because %s.", err.Error()) - t.Logf("Stack: %s", err.(stackTracer).StackTrace()) + // t.Logf("Stack: %s", err.(stackTracer).StackTrace()) oauth2.WriteIntrospectionError(rw, err) return } @@ -59,10 +59,9 @@ func tokenInfoHandler(t *testing.T, oauth2 fosite.OAuth2Provider, session fosite return func(rw http.ResponseWriter, req *http.Request) { ctx := fosite.NewContext() if _, err := oauth2.IntrospectToken(ctx, fosite.AccessTokenFromRequest(req), fosite.AccessToken, session); err != nil { - rfcerr := fosite.ErrorToRFC6749Error(err) t.Logf("Info request failed because `%s`.", err.Error()) - t.Logf("Stack: %s", err.(stackTracer).StackTrace()) - http.Error(rw, rfcerr.Description, rfcerr.Code) + // t.Logf("Stack: %s", err.(stackTracer).StackTrace()) + http.Error(rw, errors.Cause(err).(*fosite.RFC6749Error).Description, errors.Cause(err).(*fosite.RFC6749Error).Code) return } @@ -78,7 +77,7 @@ func authEndpointHandler(t *testing.T, oauth2 fosite.OAuth2Provider, session fos if err != nil { t.Logf("Access request failed because %s.", err.Error()) t.Logf("Request: %s.", ar) - t.Logf("Stack: %s.", err.(stackTracer).StackTrace()) + // t.Logf("Stack: %s.", err.(stackTracer).StackTrace()) oauth2.WriteAuthorizeError(rw, ar, err) return } @@ -100,7 +99,7 @@ func authEndpointHandler(t *testing.T, oauth2 fosite.OAuth2Provider, session fos if err != nil { t.Logf("Access request failed because %s.", err.Error()) t.Logf("Request: %s.", ar) - t.Logf("Stack: %s.", err.(stackTracer).StackTrace()) + // t.Logf("Stack: %s.", err.(stackTracer).StackTrace()) oauth2.WriteAuthorizeError(rw, ar, err) return } @@ -137,7 +136,7 @@ func tokenEndpointHandler(t *testing.T, provider fosite.OAuth2Provider) func(rw if err != nil { t.Logf("Access request failed because %s.", err.Error()) t.Logf("Request: %s.", accessRequest) - t.Logf("Stack: %v.", err.(stackTracer).StackTrace()) + // t.Logf("Stack: %v.", err.(stackTracer).StackTrace()) provider.WriteAccessError(rw, accessRequest, err) return } @@ -150,7 +149,7 @@ func tokenEndpointHandler(t *testing.T, provider fosite.OAuth2Provider) func(rw if err != nil { t.Logf("Access request failed because %s.", err.Error()) t.Logf("Request: %s.", accessRequest) - t.Logf("Stack: %v.", err.(stackTracer).StackTrace()) + // t.Logf("Stack: %v.", err.(stackTracer).StackTrace()) provider.WriteAccessError(rw, accessRequest, err) return } diff --git a/revoke_handler.go b/revoke_handler.go index b53438b1..c611ad58 100644 --- a/revoke_handler.go +++ b/revoke_handler.go @@ -104,14 +104,13 @@ func (f *Fosite) WriteRevocationResponse(rw http.ResponseWriter, err error) { case ErrInvalidClient: rw.Header().Set("Content-Type", "application/json;charset=UTF-8") - rfcerr := ErrorToRFC6749Error(err) - js, err := json.Marshal(rfcerr) + js, err := json.Marshal(ErrInvalidClient) if err != nil { http.Error(rw, fmt.Sprintf(`{"error": "%s"}`, err.Error()), http.StatusInternalServerError) return } - rw.WriteHeader(rfcerr.Code) + rw.WriteHeader(ErrInvalidClient.Code) rw.Write(js) default: // 200 OK From 8d35b668079db8642ede3b1d345d74692926515f Mon Sep 17 00:00:00 2001 From: Aeneas Date: Wed, 6 Dec 2017 15:22:10 +0100 Subject: [PATCH 16/35] Exports ErrorToRFC6749Error again (#228) --- access_error.go | 2 +- authorize_error.go | 2 +- errors.go | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/access_error.go b/access_error.go index f4165738..59cc2830 100644 --- a/access_error.go +++ b/access_error.go @@ -27,7 +27,7 @@ func (c *Fosite) WriteAccessError(rw http.ResponseWriter, _ AccessRequester, err func writeJsonError(rw http.ResponseWriter, err error) { rw.Header().Set("Content-Type", "application/json;charset=UTF-8") - rfcerr := errorToRFC6749Error(err) + rfcerr := ErrorToRFC6749Error(err) js, err := json.Marshal(err) if err != nil { http.Error(rw, fmt.Sprintf(`{"error": "%s"}`, err.Error()), http.StatusInternalServerError) diff --git a/authorize_error.go b/authorize_error.go index ece1648a..eaa41d48 100644 --- a/authorize_error.go +++ b/authorize_error.go @@ -21,7 +21,7 @@ import ( ) func (c *Fosite) WriteAuthorizeError(rw http.ResponseWriter, ar AuthorizeRequester, err error) { - rfcerr := errorToRFC6749Error(err) + rfcerr := ErrorToRFC6749Error(err) if !ar.IsRedirectURIValid() { js, err := json.MarshalIndent(rfcerr, "", "\t") if err != nil { diff --git a/errors.go b/errors.go index 35885478..bc0a6764 100644 --- a/errors.go +++ b/errors.go @@ -177,7 +177,7 @@ const ( errRevokationClientMismatchName = "revokation_client_mismatch" ) -func errorToRFC6749Error(err error) *RFC6749Error { +func ErrorToRFC6749Error(err error) *RFC6749Error { if e, ok := err.(*RFC6749Error); ok { return e } else if e, ok := errors.Cause(err).(*RFC6749Error); ok { From 701d85072d1ea5c35c7d05acf19bccdef626ba3c Mon Sep 17 00:00:00 2001 From: Aeneas Date: Wed, 6 Dec 2017 17:17:58 +0100 Subject: [PATCH 17/35] Makes use of rfcerr in access error endpoint writer explicit --- access_error.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/access_error.go b/access_error.go index 59cc2830..09ce8c4b 100644 --- a/access_error.go +++ b/access_error.go @@ -28,7 +28,7 @@ func writeJsonError(rw http.ResponseWriter, err error) { rw.Header().Set("Content-Type", "application/json;charset=UTF-8") rfcerr := ErrorToRFC6749Error(err) - js, err := json.Marshal(err) + js, err := json.Marshal(rfcerr) if err != nil { http.Error(rw, fmt.Sprintf(`{"error": "%s"}`, err.Error()), http.StatusInternalServerError) return From d6e0fbd9bdde624fa2e9feada3dec5b4266c4b9e Mon Sep 17 00:00:00 2001 From: arekkas Date: Sat, 9 Dec 2017 19:34:00 +0100 Subject: [PATCH 18/35] handler/oauth2: Improves authorization code error handling --- errors.go | 7 +++++++ handler/oauth2/flow_authorize_code_token.go | 6 +++--- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/errors.go b/errors.go index bc0a6764..96ee6a47 100644 --- a/errors.go +++ b/errors.go @@ -143,6 +143,12 @@ var ( Hint: "Token validation failed.", Code: http.StatusUnauthorized, } + ErrInactiveCode = &RFC6749Error{ + Name: errAuthorizaionCodeInactiveName, + Description: "Authorization code is inactive because it is malformed, expired or otherwise invalid", + Hint: "Authorization code validation failed.", + Code: http.StatusForbidden, + } ErrRevokationClientMismatch = &RFC6749Error{ Name: errRevokationClientMismatchName, Description: "Token was not issued to the client making the revokation request", @@ -173,6 +179,7 @@ const ( errScopeNotGrantedName = "scope_not_granted" errTokenClaimName = "token_claim" errTokenInactiveName = "token_inactive" + errAuthorizaionCodeInactiveName = "authorization_code_inactive" errUnknownErrorName = "error" errRevokationClientMismatchName = "revokation_client_mismatch" ) diff --git a/handler/oauth2/flow_authorize_code_token.go b/handler/oauth2/flow_authorize_code_token.go index 1cf449b4..c738d4a1 100644 --- a/handler/oauth2/flow_authorize_code_token.go +++ b/handler/oauth2/flow_authorize_code_token.go @@ -39,7 +39,7 @@ func (c *AuthorizeExplicitGrantHandler) HandleTokenEndpointRequest(ctx context.C signature := c.AuthorizeCodeStrategy.AuthorizeCodeSignature(code) authorizeRequest, err := c.CoreStorage.GetAuthorizeCodeSession(ctx, signature, request.GetSession()) if errors.Cause(err) == fosite.ErrNotFound { - return errors.Wrap(fosite.ErrInvalidRequest, err.Error()) + return errors.WithStack(fosite.ErrInactiveCode) } else if err != nil { return errors.Wrap(errors.WithStack(fosite.ErrServerError), err.Error()) } @@ -47,7 +47,7 @@ func (c *AuthorizeExplicitGrantHandler) HandleTokenEndpointRequest(ctx context.C // The authorization server MUST verify that the authorization code is valid // This needs to happen after store retrieval for the session to be hydrated properly if err := c.AuthorizeCodeStrategy.ValidateAuthorizeCode(ctx, request, code); err != nil { - return errors.Wrap(errors.WithStack(fosite.ErrInvalidRequest), err.Error()) + return errors.Wrap(errors.WithStack(fosite.ErrInactiveCode), err.Error()) } // Override scopes @@ -57,7 +57,7 @@ func (c *AuthorizeExplicitGrantHandler) HandleTokenEndpointRequest(ctx context.C // confidential client, or if the client is public, ensure that the // code was issued to "client_id" in the request, if authorizeRequest.GetClient().GetID() != request.GetClient().GetID() { - return errors.Wrap(errors.WithStack(fosite.ErrInvalidRequest), "Client ID mismatch") + return errors.Wrap(errors.WithStack(fosite.ErrInactiveCode), "Client ID mismatch") } // ensure that the "redirect_uri" parameter is present if the From 2341dec8febeda9da535dc898c7d19aa3ecc8c00 Mon Sep 17 00:00:00 2001 From: arekkas Date: Sat, 9 Dec 2017 20:32:01 +0100 Subject: [PATCH 19/35] handler/oauth2: Adds token revokation on authorize code reuse --- compose/compose_oauth2.go | 15 ++++++++------- handler/oauth2/flow_authorize_code_auth.go | 9 +++++---- handler/oauth2/flow_authorize_code_token.go | 10 ++++++++-- handler/oauth2/flow_authorize_code_token_test.go | 13 +++++++------ oauth2.go | 3 +++ request.go | 4 ++++ 6 files changed, 35 insertions(+), 19 deletions(-) diff --git a/compose/compose_oauth2.go b/compose/compose_oauth2.go index 775a9577..79b7ae70 100644 --- a/compose/compose_oauth2.go +++ b/compose/compose_oauth2.go @@ -22,13 +22,14 @@ import ( // an access token, refresh token and authorize code validator. func OAuth2AuthorizeExplicitFactory(config *Config, storage interface{}, strategy interface{}) interface{} { return &oauth2.AuthorizeExplicitGrantHandler{ - AccessTokenStrategy: strategy.(oauth2.AccessTokenStrategy), - RefreshTokenStrategy: strategy.(oauth2.RefreshTokenStrategy), - AuthorizeCodeStrategy: strategy.(oauth2.AuthorizeCodeStrategy), - CoreStorage: storage.(oauth2.CoreStorage), - AuthCodeLifespan: config.GetAuthorizeCodeLifespan(), - AccessTokenLifespan: config.GetAccessTokenLifespan(), - ScopeStrategy: config.GetScopeStrategy(), + AccessTokenStrategy: strategy.(oauth2.AccessTokenStrategy), + RefreshTokenStrategy: strategy.(oauth2.RefreshTokenStrategy), + AuthorizeCodeStrategy: strategy.(oauth2.AuthorizeCodeStrategy), + CoreStorage: storage.(oauth2.CoreStorage), + AuthCodeLifespan: config.GetAuthorizeCodeLifespan(), + AccessTokenLifespan: config.GetAccessTokenLifespan(), + ScopeStrategy: config.GetScopeStrategy(), + TokenRevocationStorage: storage.(oauth2.TokenRevocationStorage), } } diff --git a/handler/oauth2/flow_authorize_code_auth.go b/handler/oauth2/flow_authorize_code_auth.go index 3061cb82..88357802 100644 --- a/handler/oauth2/flow_authorize_code_auth.go +++ b/handler/oauth2/flow_authorize_code_auth.go @@ -29,10 +29,11 @@ import ( // AuthorizeExplicitGrantTypeHandler is a response handler for the Authorize Code grant using the explicit grant type // as defined in https://tools.ietf.org/html/rfc6749#section-4.1 type AuthorizeExplicitGrantHandler struct { - AccessTokenStrategy AccessTokenStrategy - RefreshTokenStrategy RefreshTokenStrategy - AuthorizeCodeStrategy AuthorizeCodeStrategy - CoreStorage CoreStorage + AccessTokenStrategy AccessTokenStrategy + RefreshTokenStrategy RefreshTokenStrategy + AuthorizeCodeStrategy AuthorizeCodeStrategy + CoreStorage CoreStorage + TokenRevocationStorage TokenRevocationStorage // AuthCodeLifespan defines the lifetime of an authorize code. AuthCodeLifespan time.Duration diff --git a/handler/oauth2/flow_authorize_code_token.go b/handler/oauth2/flow_authorize_code_token.go index c738d4a1..25b6896b 100644 --- a/handler/oauth2/flow_authorize_code_token.go +++ b/handler/oauth2/flow_authorize_code_token.go @@ -39,15 +39,20 @@ func (c *AuthorizeExplicitGrantHandler) HandleTokenEndpointRequest(ctx context.C signature := c.AuthorizeCodeStrategy.AuthorizeCodeSignature(code) authorizeRequest, err := c.CoreStorage.GetAuthorizeCodeSession(ctx, signature, request.GetSession()) if errors.Cause(err) == fosite.ErrNotFound { + // If an authorize code is used twice (which is likely the case here), we should try and invalidate any previously + // issued access and refresh tokens. + c.TokenRevocationStorage.RevokeAccessToken(ctx, authorizeRequest.GetID()) + c.TokenRevocationStorage.RevokeRefreshToken(ctx, authorizeRequest.GetID()) + return errors.WithStack(fosite.ErrInactiveCode) } else if err != nil { - return errors.Wrap(errors.WithStack(fosite.ErrServerError), err.Error()) + return errors.Wrap(fosite.ErrServerError, err.Error()) } // The authorization server MUST verify that the authorization code is valid // This needs to happen after store retrieval for the session to be hydrated properly if err := c.AuthorizeCodeStrategy.ValidateAuthorizeCode(ctx, request, code); err != nil { - return errors.Wrap(errors.WithStack(fosite.ErrInactiveCode), err.Error()) + return errors.Wrap(fosite.ErrInactiveCode, err.Error()) } // Override scopes @@ -76,6 +81,7 @@ func (c *AuthorizeExplicitGrantHandler) HandleTokenEndpointRequest(ctx context.C // in Section 3.2.1. request.SetSession(authorizeRequest.GetSession()) request.GetSession().SetExpiresAt(fosite.AccessToken, time.Now().Add(c.AccessTokenLifespan)) + request.SetID(authorizeRequest.GetID()) return nil } diff --git a/handler/oauth2/flow_authorize_code_token_test.go b/handler/oauth2/flow_authorize_code_token_test.go index 06fa1c6d..23826db4 100644 --- a/handler/oauth2/flow_authorize_code_token_test.go +++ b/handler/oauth2/flow_authorize_code_token_test.go @@ -38,12 +38,13 @@ func TestAuthorizeCode_PopulateTokenEndpointResponse(t *testing.T) { store := storage.NewMemoryStore() h := AuthorizeExplicitGrantHandler{ - CoreStorage: store, - AuthorizeCodeStrategy: strategy, - AccessTokenStrategy: strategy, - RefreshTokenStrategy: strategy, - ScopeStrategy: fosite.HierarchicScopeStrategy, - AccessTokenLifespan: time.Minute, + CoreStorage: store, + AuthorizeCodeStrategy: strategy, + AccessTokenStrategy: strategy, + RefreshTokenStrategy: strategy, + ScopeStrategy: fosite.HierarchicScopeStrategy, + AccessTokenLifespan: time.Minute, + TokenRevocationStorage: store, } for _, c := range []struct { areq *fosite.AccessRequest diff --git a/oauth2.go b/oauth2.go index 11db0bde..677711c1 100644 --- a/oauth2.go +++ b/oauth2.go @@ -167,6 +167,9 @@ type IntrospectionResponder interface { // Requester is an abstract interface for handling requests in Fosite. type Requester interface { + // SetID sets the unique identifier. + SetID(id string) + // GetID returns a unique identifier. GetID() string diff --git a/request.go b/request.go index 7311cfec..b9e6cd68 100644 --- a/request.go +++ b/request.go @@ -49,6 +49,10 @@ func (a *Request) GetID() string { return a.ID } +func (a *Request) SetID(id string) { + a.ID = id +} + func (a *Request) GetRequestForm() url.Values { return a.Form } From 1f9d07d15e8f70986ed12cfb3ac9fac4a6e7e278 Mon Sep 17 00:00:00 2001 From: arekkas Date: Sat, 9 Dec 2017 20:33:00 +0100 Subject: [PATCH 20/35] internal: Updates mocks and mock generation --- generate-mocks.sh | 2 -- internal/access_request.go | 8 ++++++++ internal/authorize_request.go | 8 ++++++++ internal/request.go | 8 ++++++++ 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/generate-mocks.sh b/generate-mocks.sh index a309df6f..8720b39e 100755 --- a/generate-mocks.sh +++ b/generate-mocks.sh @@ -8,9 +8,7 @@ mockgen -package internal -destination internal/authorize_code_storage.go github mockgen -package internal -destination internal/access_token_storage.go github.com/ory/fosite/handler/oauth2 AccessTokenStorage mockgen -package internal -destination internal/refresh_token_strategy.go github.com/ory/fosite/handler/oauth2 RefreshTokenStorage mockgen -package internal -destination internal/oauth2_client_storage.go github.com/ory/fosite/handler/oauth2 ClientCredentialsGrantStorage -mockgen -package internal -destination internal/oauth2_explicit_storage.go github.com/ory/fosite/handler/oauth2 AuthorizeCodeGrantStorage mockgen -package internal -destination internal/oauth2_owner_storage.go github.com/ory/fosite/handler/oauth2 ResourceOwnerPasswordCredentialsGrantStorage -mockgen -package internal -destination internal/oauth2_refresh_storage.go github.com/ory/fosite/handler/oauth2 RefreshTokenGrantStorage mockgen -package internal -destination internal/oauth2_revoke_storage.go github.com/ory/fosite/handler/oauth2 TokenRevocationStorage mockgen -package internal -destination internal/openid_id_token_storage.go github.com/ory/fosite/handler/openid OpenIDConnectRequestStorage mockgen -package internal -destination internal/access_token_strategy.go github.com/ory/fosite/handler/oauth2 AccessTokenStrategy diff --git a/internal/access_request.go b/internal/access_request.go index 136ab8f9..6a285802 100644 --- a/internal/access_request.go +++ b/internal/access_request.go @@ -136,6 +136,14 @@ func (_mr *_MockAccessRequesterRecorder) Merge(arg0 interface{}) *gomock.Call { return _mr.mock.ctrl.RecordCall(_mr.mock, "Merge", arg0) } +func (_m *MockAccessRequester) SetID(_param0 string) { + _m.ctrl.Call(_m, "SetID", _param0) +} + +func (_mr *_MockAccessRequesterRecorder) SetID(arg0 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCall(_mr.mock, "SetID", arg0) +} + func (_m *MockAccessRequester) SetRequestedScopes(_param0 fosite.Arguments) { _m.ctrl.Call(_m, "SetRequestedScopes", _param0) } diff --git a/internal/authorize_request.go b/internal/authorize_request.go index a4393561..b2f9c1d9 100644 --- a/internal/authorize_request.go +++ b/internal/authorize_request.go @@ -176,6 +176,14 @@ func (_mr *_MockAuthorizeRequesterRecorder) Merge(arg0 interface{}) *gomock.Call return _mr.mock.ctrl.RecordCall(_mr.mock, "Merge", arg0) } +func (_m *MockAuthorizeRequester) SetID(_param0 string) { + _m.ctrl.Call(_m, "SetID", _param0) +} + +func (_mr *_MockAuthorizeRequesterRecorder) SetID(arg0 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCall(_mr.mock, "SetID", arg0) +} + func (_m *MockAuthorizeRequester) SetRequestedScopes(_param0 fosite.Arguments) { _m.ctrl.Call(_m, "SetRequestedScopes", _param0) } diff --git a/internal/request.go b/internal/request.go index f908933a..8a2ab851 100644 --- a/internal/request.go +++ b/internal/request.go @@ -126,6 +126,14 @@ func (_mr *_MockRequesterRecorder) Merge(arg0 interface{}) *gomock.Call { return _mr.mock.ctrl.RecordCall(_mr.mock, "Merge", arg0) } +func (_m *MockRequester) SetID(_param0 string) { + _m.ctrl.Call(_m, "SetID", _param0) +} + +func (_mr *_MockRequesterRecorder) SetID(arg0 interface{}) *gomock.Call { + return _mr.mock.ctrl.RecordCall(_mr.mock, "SetID", arg0) +} + func (_m *MockRequester) SetRequestedScopes(_param0 fosite.Arguments) { _m.ctrl.Call(_m, "SetRequestedScopes", _param0) } From 392c191bc1859ca57e3d0cf4d2b996d5ab382530 Mon Sep 17 00:00:00 2001 From: arekkas Date: Sat, 9 Dec 2017 20:33:52 +0100 Subject: [PATCH 21/35] oauth2: Allows client credentials in POST body and solves public client auth Closes #231 Closes #217 --- access_request_handler.go | 39 +++++++++++++++++++++++++------ access_request_handler_test.go | 42 +++++++++++++++++++--------------- 2 files changed, 55 insertions(+), 26 deletions(-) diff --git a/access_request_handler.go b/access_request_handler.go index 3c7a6144..d55d78b1 100644 --- a/access_request_handler.go +++ b/access_request_handler.go @@ -71,13 +71,9 @@ func (f *Fosite) NewAccessRequest(ctx context.Context, r *http.Request, session } // Decode client_id and client_secret which should be in "application/x-www-form-urlencoded" format. - var clientID, clientSecret string - if id, secret, ok := r.BasicAuth(); !ok { - return accessRequest, errors.Wrap(ErrInvalidRequest, "HTTP authorization header missing or invalid") - } else if clientID, err = url.QueryUnescape(id); err != nil { - return accessRequest, errors.Wrap(ErrInvalidRequest, `The client id in the HTTP authorization header could not be decoded from "application/x-www-form-urlencoded"`) - } else if clientSecret, err = url.QueryUnescape(secret); err != nil { - return accessRequest, errors.Wrap(ErrInvalidRequest, `The client secret in the HTTP authorization header could not be decoded from "application/x-www-form-urlencoded"`) + clientID, clientSecret, err := clientCredentialsFromRequest(r) + if err != nil { + return accessRequest, err } client, err := f.Store.GetClient(ctx, clientID) @@ -109,3 +105,32 @@ func (f *Fosite) NewAccessRequest(ctx context.Context, r *http.Request, session } return accessRequest, nil } + +func clientCredentialsFromRequest(r *http.Request) (clientID, clientSecret string, err error) { + if id, secret, ok := r.BasicAuth(); !ok { + return clientCredentialsFromRequestBody(r) + } else if clientID, err = url.QueryUnescape(id); err != nil { + return "", "", errors.Wrap(ErrInvalidRequest, `The client id in the HTTP authorization header could not be decoded from "application/x-www-form-urlencoded"`) + } else if clientSecret, err = url.QueryUnescape(secret); err != nil { + return "", "", errors.Wrap(ErrInvalidRequest, `The client secret in the HTTP authorization header could not be decoded from "application/x-www-form-urlencoded"`) + } + + return clientID, clientSecret, nil +} + +func clientCredentialsFromRequestBody(r *http.Request) (clientID, clientSecret string, err error) { + clientID = r.PostForm.Get("client_id") + clientSecret = r.PostForm.Get("client_secret") + + if clientID == "" { + return "", "", errors.Wrap(ErrInvalidRequest, "Client credentials missing or malformed in both HTTP Authorization header and HTTP POST body") + } + + if clientID, err = url.QueryUnescape(clientID); err != nil { + return "", "", errors.Wrap(ErrInvalidRequest, `The client id in the HTTP authorization header could not be decoded from "application/x-www-form-urlencoded"`) + } else if clientSecret, err = url.QueryUnescape(clientSecret); err != nil { + return "", "", errors.Wrap(ErrInvalidRequest, `The client secret in the HTTP authorization header could not be decoded from "application/x-www-form-urlencoded"`) + } + + return clientID, clientSecret, nil +} diff --git a/access_request_handler_test.go b/access_request_handler_test.go index d4e03553..3dc740a4 100644 --- a/access_request_handler_test.go +++ b/access_request_handler_test.go @@ -26,6 +26,7 @@ import ( "github.com/ory/fosite/internal" "github.com/pkg/errors" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestNewAccessRequest(t *testing.T) { @@ -49,6 +50,7 @@ func TestNewAccessRequest(t *testing.T) { { header: http.Header{}, expectErr: ErrInvalidRequest, + form: url.Values{}, method: "POST", mock: func() {}, }, @@ -66,7 +68,7 @@ func TestNewAccessRequest(t *testing.T) { method: "POST", form: url.Values{ "grant_type": {"foo"}, - "client_id": {"foo"}, + "client_id": {""}, }, expectErr: ErrInvalidRequest, mock: func() {}, @@ -187,24 +189,26 @@ func TestNewAccessRequest(t *testing.T) { }, }, } { - r := &http.Request{ - Header: c.header, - PostForm: c.form, - Form: c.form, - Method: c.method, - } - c.mock() - ctx := NewContext() - fosite.TokenEndpointHandlers = c.handlers - ar, err := fosite.NewAccessRequest(ctx, r, new(DefaultSession)) - assert.True(t, errors.Cause(err) == c.expectErr, "%d\nwant: %s \ngot: %s", k, c.expectErr, err) - if err != nil { - t.Logf("Error occured: %v", err) - } else { - AssertObjectKeysEqual(t, c.expect, ar, "GrantTypes", "Client") - assert.NotNil(t, ar.GetRequestedAt()) - } - t.Logf("Passed test case %d", k) + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + r := &http.Request{ + Header: c.header, + PostForm: c.form, + Form: c.form, + Method: c.method, + } + c.mock() + ctx := NewContext() + fosite.TokenEndpointHandlers = c.handlers + ar, err := fosite.NewAccessRequest(ctx, r, new(DefaultSession)) + + if c.expectErr != nil { + assert.EqualError(t, err, c.expectErr.Error()) + } else { + require.NoError(t, err) + AssertObjectKeysEqual(t, c.expect, ar, "GrantTypes", "Client") + assert.NotNil(t, ar.GetRequestedAt()) + } + }) } } From 7ec8d19815d10913ef8cfd8ced9b9794f578dbf4 Mon Sep 17 00:00:00 2001 From: arekkas Date: Sat, 9 Dec 2017 20:55:42 +0100 Subject: [PATCH 22/35] Improves error debug messages across the project --- access_request_handler.go | 20 ++++++++-------- access_response_writer.go | 2 +- authorize_helper.go | 4 ++-- authorize_request_handler.go | 12 ++++++---- errors.go | 11 +++++++++ errors_test.go | 14 +++++++++++ handler.go | 4 ---- handler/oauth2/flow_authorize_code_auth.go | 8 +++---- handler/oauth2/flow_authorize_code_token.go | 24 +++++++++---------- handler/oauth2/flow_authorize_implicit.go | 10 ++++---- handler/oauth2/flow_client_credentials.go | 6 ++--- handler/oauth2/flow_refresh.go | 26 ++++++++++----------- handler/oauth2/flow_resource_owner.go | 14 +++++------ handler/oauth2/introspector.go | 7 +++--- handler/oauth2/strategy_hmacsha.go | 8 +++---- handler/oauth2/strategy_jwt.go | 22 ++++++++--------- handler/openid/flow_explicit_auth.go | 6 ++--- handler/openid/flow_explicit_token.go | 10 ++++---- handler/openid/flow_hybrid.go | 20 ++++++++-------- handler/openid/flow_implicit.go | 12 +++++----- handler/openid/flow_refresh_token.go | 8 +++---- introspect.go | 5 ++-- introspection_request_handler.go | 18 +++++++------- revoke_handler.go | 10 ++++---- token/jwt/jwt.go | 5 ++-- 25 files changed, 157 insertions(+), 129 deletions(-) create mode 100644 errors_test.go diff --git a/access_request_handler.go b/access_request_handler.go index d55d78b1..8a41b5fc 100644 --- a/access_request_handler.go +++ b/access_request_handler.go @@ -54,9 +54,9 @@ func (f *Fosite) NewAccessRequest(ctx context.Context, r *http.Request, session accessRequest := NewAccessRequest(session) if r.Method != "POST" { - return accessRequest, errors.Wrap(ErrInvalidRequest, "HTTP method is not POST") + return accessRequest, errors.WithStack(ErrInvalidRequest.WithDebug("HTTP method is not POST")) } else if err := r.ParseForm(); err != nil { - return accessRequest, errors.Wrap(ErrInvalidRequest, err.Error()) + return accessRequest, errors.WithStack(ErrInvalidRequest.WithDebug(err.Error())) } accessRequest.Form = r.PostForm @@ -67,7 +67,7 @@ func (f *Fosite) NewAccessRequest(ctx context.Context, r *http.Request, session accessRequest.SetRequestedScopes(removeEmpty(strings.Split(r.PostForm.Get("scope"), " "))) accessRequest.GrantTypes = removeEmpty(strings.Split(r.PostForm.Get("grant_type"), " ")) if len(accessRequest.GrantTypes) < 1 { - return accessRequest, errors.Wrap(ErrInvalidRequest, "No grant type given") + return accessRequest, errors.WithStack(ErrInvalidRequest.WithDebug("No grant type given")) } // Decode client_id and client_secret which should be in "application/x-www-form-urlencoded" format. @@ -78,13 +78,13 @@ func (f *Fosite) NewAccessRequest(ctx context.Context, r *http.Request, session client, err := f.Store.GetClient(ctx, clientID) if err != nil { - return accessRequest, errors.Wrap(ErrInvalidClient, err.Error()) + return accessRequest, errors.WithStack(ErrInvalidClient.WithDebug(err.Error())) } if !client.IsPublic() { // Enforce client authentication if err := f.Hasher.Compare(client.GetHashedSecret(), []byte(clientSecret)); err != nil { - return accessRequest, errors.Wrap(ErrInvalidClient, err.Error()) + return accessRequest, errors.WithStack(ErrInvalidClient.WithDebug(err.Error())) } } accessRequest.Client = client @@ -110,9 +110,9 @@ func clientCredentialsFromRequest(r *http.Request) (clientID, clientSecret strin if id, secret, ok := r.BasicAuth(); !ok { return clientCredentialsFromRequestBody(r) } else if clientID, err = url.QueryUnescape(id); err != nil { - return "", "", errors.Wrap(ErrInvalidRequest, `The client id in the HTTP authorization header could not be decoded from "application/x-www-form-urlencoded"`) + return "", "", errors.WithStack(ErrInvalidRequest.WithDebug(`The client id in the HTTP authorization header could not be decoded from "application/x-www-form-urlencoded"`)) } else if clientSecret, err = url.QueryUnescape(secret); err != nil { - return "", "", errors.Wrap(ErrInvalidRequest, `The client secret in the HTTP authorization header could not be decoded from "application/x-www-form-urlencoded"`) + return "", "", errors.WithStack(ErrInvalidRequest.WithDebug(`The client secret in the HTTP authorization header could not be decoded from "application/x-www-form-urlencoded"`)) } return clientID, clientSecret, nil @@ -123,13 +123,13 @@ func clientCredentialsFromRequestBody(r *http.Request) (clientID, clientSecret s clientSecret = r.PostForm.Get("client_secret") if clientID == "" { - return "", "", errors.Wrap(ErrInvalidRequest, "Client credentials missing or malformed in both HTTP Authorization header and HTTP POST body") + return "", "", errors.WithStack(ErrInvalidRequest.WithDebug("Client credentials missing or malformed in both HTTP Authorization header and HTTP POST body")) } if clientID, err = url.QueryUnescape(clientID); err != nil { - return "", "", errors.Wrap(ErrInvalidRequest, `The client id in the HTTP authorization header could not be decoded from "application/x-www-form-urlencoded"`) + return "", "", errors.WithStack(ErrInvalidRequest.WithDebug(`The client id in the HTTP authorization header could not be decoded from "application/x-www-form-urlencoded"`)) } else if clientSecret, err = url.QueryUnescape(clientSecret); err != nil { - return "", "", errors.Wrap(ErrInvalidRequest, `The client secret in the HTTP authorization header could not be decoded from "application/x-www-form-urlencoded"`) + return "", "", errors.WithStack(ErrInvalidRequest.WithDebug(`The client secret in the HTTP authorization header could not be decoded from "application/x-www-form-urlencoded"`)) } return clientID, clientSecret, nil diff --git a/access_response_writer.go b/access_response_writer.go index 8c1b8c04..c8d51fcc 100644 --- a/access_response_writer.go +++ b/access_response_writer.go @@ -33,7 +33,7 @@ func (f *Fosite) NewAccessResponse(ctx context.Context, requester AccessRequeste } if response.GetAccessToken() == "" || response.GetTokenType() == "" { - return nil, errors.Wrap(ErrServerError, "Access token or token type not set") + return nil, errors.WithStack(ErrServerError.WithDebug("Access token or token type not set")) } return response, nil diff --git a/authorize_helper.go b/authorize_helper.go index f1bf7d45..efab8caa 100644 --- a/authorize_helper.go +++ b/authorize_helper.go @@ -35,7 +35,7 @@ func GetRedirectURIFromRequestValues(values url.Values) (string, error) { // The endpoint URI MAY include an "application/x-www-form-urlencoded" formatted (per Appendix B) query component redirectURI, err := url.QueryUnescape(values.Get("redirect_uri")) if err != nil { - return "", errors.Wrap(ErrInvalidRequest, "redirect_uri parameter malformed or missing") + return "", errors.WithStack(ErrInvalidRequest.WithDebug("redirect_uri parameter malformed or missing")) } return redirectURI, nil } @@ -85,7 +85,7 @@ func MatchRedirectURIWithClientRedirectURIs(rawurl string, client Client) (*url. } } - return nil, errors.Wrap(ErrInvalidRequest, "redirect_uri parameter does not match with registered client redirect urls") + return nil, errors.WithStack(ErrInvalidRequest.WithDebug("redirect_uri parameter does not match with registered client redirect urls")) } // IsValidRedirectURI validates a redirect_uri as specified in: diff --git a/authorize_request_handler.go b/authorize_request_handler.go index faf6ba52..412b3b4e 100644 --- a/authorize_request_handler.go +++ b/authorize_request_handler.go @@ -20,6 +20,8 @@ import ( "context" + "fmt" + "github.com/pkg/errors" ) @@ -31,7 +33,7 @@ func (c *Fosite) NewAuthorizeRequest(ctx context.Context, r *http.Request) (Auth } if err := r.ParseForm(); err != nil { - return request, errors.Wrap(ErrInvalidRequest, err.Error()) + return request, errors.WithStack(ErrInvalidRequest.WithDebug(err.Error())) } request.Form = r.Form @@ -44,15 +46,15 @@ func (c *Fosite) NewAuthorizeRequest(ctx context.Context, r *http.Request) (Auth // Fetch redirect URI from request rawRedirURI, err := GetRedirectURIFromRequestValues(r.Form) if err != nil { - return request, errors.Wrap(ErrInvalidRequest, err.Error()) + return request, errors.WithStack(ErrInvalidRequest.WithDebug(err.Error())) } // Validate redirect uri redirectURI, err := MatchRedirectURIWithClientRedirectURIs(rawRedirURI, client) if err != nil { - return request, errors.Wrap(ErrInvalidRequest, err.Error()) + return request, errors.WithStack(ErrInvalidRequest.WithDebug(err.Error())) } else if !IsValidRedirectURI(redirectURI) { - return request, errors.Wrap(ErrInvalidRequest, "not a valid redirect uri") + return request, errors.WithStack(ErrInvalidRequest.WithDebug("not a valid redirect uri")) } request.RedirectURI = redirectURI @@ -72,7 +74,7 @@ func (c *Fosite) NewAuthorizeRequest(ctx context.Context, r *http.Request) (Auth state := r.Form.Get("state") if len(state) < MinParameterEntropy { // We're assuming that using less then 8 characters for the state can not be considered "unguessable" - return request, errors.Wrapf(ErrInvalidState, "state length must at least be %d characters long", MinParameterEntropy) + return request, errors.WithStack(ErrInvalidState.WithDebug(fmt.Sprintf("State length must at least be %d characters long", MinParameterEntropy))) } request.State = state diff --git a/errors.go b/errors.go index 96ee6a47..1853215c 100644 --- a/errors.go +++ b/errors.go @@ -22,6 +22,11 @@ import ( ) var ( + ErrUnknownRequest = &RFC6749Error{ + Name: errUnknownErrorName, + Description: "The handler is not responsible for this request", + Code: http.StatusInternalServerError, + } ErrRequestForbidden = &RFC6749Error{ Name: errRequestForbidden, Description: "The request is not allowed", @@ -229,3 +234,9 @@ func (e *RFC6749Error) Details() []map[string]interface{} { func (e *RFC6749Error) StatusCode() int { return e.Code } + +func (e *RFC6749Error) WithDebug(debug string) *RFC6749Error { + err := *e + e.Debug = debug + return &err +} diff --git a/errors_test.go b/errors_test.go new file mode 100644 index 00000000..29ccfb1c --- /dev/null +++ b/errors_test.go @@ -0,0 +1,14 @@ +package fosite + +import ( + "testing" + + "github.com/stretchr/testify/assert" +) + +func TestAddDebug(t *testing.T) { + err := ErrRevokationClientMismatch.WithDebug("debug") + assert.NotEqual(t, err, ErrRevokationClientMismatch) + assert.Empty(t, ErrRevokationClientMismatch.Debug) + assert.NotEmpty(t, err.Debug) +} diff --git a/handler.go b/handler.go index 4e7acaa4..4e224f36 100644 --- a/handler.go +++ b/handler.go @@ -16,12 +16,8 @@ package fosite import ( "context" - - "github.com/pkg/errors" ) -var ErrUnknownRequest = errors.New("The handler is not responsible for this request.") - type AuthorizeEndpointHandler interface { // HandleAuthorizeRequest handles an authorize endpoint request. To extend the handler's capabilities, the http request // is passed along, if further information retrieval is required. If the handler feels that he is not responsible for diff --git a/handler/oauth2/flow_authorize_code_auth.go b/handler/oauth2/flow_authorize_code_auth.go index 88357802..0f153651 100644 --- a/handler/oauth2/flow_authorize_code_auth.go +++ b/handler/oauth2/flow_authorize_code_auth.go @@ -55,13 +55,13 @@ func (c *AuthorizeExplicitGrantHandler) HandleAuthorizeEndpointRequest(ctx conte } if !fosite.IsRedirectURISecure(ar.GetRedirectURI()) { - return errors.Wrap(fosite.ErrInvalidRequest, "Redirect URL is using an insecure protocol, http is only allowed for hosts with suffix `localhost`, for example: http://myapp.localhost/") + return errors.WithStack(fosite.ErrInvalidRequest.WithDebug("Redirect URL is using an insecure protocol, http is only allowed for hosts with suffix `localhost`, for example: http://myapp.localhost/")) } client := ar.GetClient() for _, scope := range ar.GetRequestedScopes() { if !c.ScopeStrategy(client.GetScopes(), scope) { - return errors.Wrap(fosite.ErrInvalidScope, fmt.Sprintf("The client is not allowed to request scope %s", scope)) + return errors.WithStack(fosite.ErrInvalidScope.WithDebug(fmt.Sprintf("The client is not allowed to request scope %s", scope))) } } @@ -71,12 +71,12 @@ func (c *AuthorizeExplicitGrantHandler) HandleAuthorizeEndpointRequest(ctx conte func (c *AuthorizeExplicitGrantHandler) IssueAuthorizeCode(ctx context.Context, ar fosite.AuthorizeRequester, resp fosite.AuthorizeResponder) error { code, signature, err := c.AuthorizeCodeStrategy.GenerateAuthorizeCode(ctx, ar) if err != nil { - return errors.Wrap(fosite.ErrServerError, err.Error()) + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } ar.GetSession().SetExpiresAt(fosite.AuthorizeCode, time.Now().Add(c.AuthCodeLifespan)) if err := c.CoreStorage.CreateAuthorizeCodeSession(ctx, signature, ar); err != nil { - return errors.Wrap(fosite.ErrServerError, err.Error()) + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } resp.AddQuery("code", code) diff --git a/handler/oauth2/flow_authorize_code_token.go b/handler/oauth2/flow_authorize_code_token.go index 25b6896b..cc37fbb9 100644 --- a/handler/oauth2/flow_authorize_code_token.go +++ b/handler/oauth2/flow_authorize_code_token.go @@ -32,7 +32,7 @@ func (c *AuthorizeExplicitGrantHandler) HandleTokenEndpointRequest(ctx context.C } if !request.GetClient().GetGrantTypes().Has("authorization_code") { - return errors.Wrap(errors.WithStack(fosite.ErrInvalidGrant), "The client is not allowed to use grant type authorization_code") + return errors.WithStack(fosite.ErrInvalidGrant.WithDebug("The client is not allowed to use grant type authorization_code")) } code := request.GetRequestForm().Get("code") @@ -46,13 +46,13 @@ func (c *AuthorizeExplicitGrantHandler) HandleTokenEndpointRequest(ctx context.C return errors.WithStack(fosite.ErrInactiveCode) } else if err != nil { - return errors.Wrap(fosite.ErrServerError, err.Error()) + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } // The authorization server MUST verify that the authorization code is valid // This needs to happen after store retrieval for the session to be hydrated properly if err := c.AuthorizeCodeStrategy.ValidateAuthorizeCode(ctx, request, code); err != nil { - return errors.Wrap(fosite.ErrInactiveCode, err.Error()) + return errors.WithStack(fosite.ErrInactiveCode.WithDebug(err.Error())) } // Override scopes @@ -62,7 +62,7 @@ func (c *AuthorizeExplicitGrantHandler) HandleTokenEndpointRequest(ctx context.C // confidential client, or if the client is public, ensure that the // code was issued to "client_id" in the request, if authorizeRequest.GetClient().GetID() != request.GetClient().GetID() { - return errors.Wrap(errors.WithStack(fosite.ErrInactiveCode), "Client ID mismatch") + return errors.WithStack(fosite.ErrInactiveCode.WithDebug("Client ID mismatch")) } // ensure that the "redirect_uri" parameter is present if the @@ -71,7 +71,7 @@ func (c *AuthorizeExplicitGrantHandler) HandleTokenEndpointRequest(ctx context.C // their values are identical. forcedRedirectURI := authorizeRequest.GetRequestForm().Get("redirect_uri") if forcedRedirectURI != "" && forcedRedirectURI != request.GetRequestForm().Get("redirect_uri") { - return errors.Wrap(errors.WithStack(fosite.ErrInvalidRequest), "Redirect URI mismatch") + return errors.WithStack(fosite.ErrInvalidRequest.WithDebug("Redirect URI mismatch")) } // Checking of POST client_id skipped, because: @@ -96,10 +96,10 @@ func (c *AuthorizeExplicitGrantHandler) PopulateTokenEndpointResponse(ctx contex signature := c.AuthorizeCodeStrategy.AuthorizeCodeSignature(code) authorizeRequest, err := c.CoreStorage.GetAuthorizeCodeSession(ctx, signature, requester.GetSession()) if err != nil { - return errors.Wrap(errors.WithStack(fosite.ErrServerError), err.Error()) + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } else if err := c.AuthorizeCodeStrategy.ValidateAuthorizeCode(ctx, requester, code); err != nil { // This needs to happen after store retrieval for the session to be hydrated properly - return errors.Wrap(errors.WithStack(fosite.ErrInvalidRequest), err.Error()) + return errors.WithStack(fosite.ErrInvalidRequest.WithDebug(err.Error())) } for _, scope := range authorizeRequest.GetGrantedScopes() { @@ -108,24 +108,24 @@ func (c *AuthorizeExplicitGrantHandler) PopulateTokenEndpointResponse(ctx contex access, accessSignature, err := c.AccessTokenStrategy.GenerateAccessToken(ctx, requester) if err != nil { - return errors.Wrap(errors.WithStack(fosite.ErrServerError), err.Error()) + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } var refresh, refreshSignature string if authorizeRequest.GetGrantedScopes().Has("offline") { refresh, refreshSignature, err = c.RefreshTokenStrategy.GenerateRefreshToken(ctx, requester) if err != nil { - return errors.Wrap(errors.WithStack(fosite.ErrServerError), err.Error()) + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } } if err := c.CoreStorage.DeleteAuthorizeCodeSession(ctx, signature); err != nil { - return errors.Wrap(errors.WithStack(fosite.ErrServerError), err.Error()) + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } else if err := c.CoreStorage.CreateAccessTokenSession(ctx, accessSignature, requester); err != nil { - return errors.Wrap(errors.WithStack(fosite.ErrServerError), err.Error()) + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } else if refreshSignature != "" { if err := c.CoreStorage.CreateRefreshTokenSession(ctx, refreshSignature, requester); err != nil { - return errors.Wrap(errors.WithStack(fosite.ErrServerError), err.Error()) + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } } diff --git a/handler/oauth2/flow_authorize_implicit.go b/handler/oauth2/flow_authorize_implicit.go index ed608540..f9d5fda7 100644 --- a/handler/oauth2/flow_authorize_implicit.go +++ b/handler/oauth2/flow_authorize_implicit.go @@ -48,17 +48,17 @@ func (c *AuthorizeImplicitGrantTypeHandler) HandleAuthorizeEndpointRequest(ctx c } if !ar.GetClient().GetResponseTypes().Has("token") { - return errors.Wrap(fosite.ErrInvalidGrant, "The client is not allowed to use response type token") + return errors.WithStack(fosite.ErrInvalidGrant.WithDebug("The client is not allowed to use response type token")) } if !ar.GetClient().GetGrantTypes().Has("implicit") { - return errors.Wrap(fosite.ErrInvalidGrant, "The client is not allowed to use grant type implicit") + return errors.WithStack(fosite.ErrInvalidGrant.WithDebug("The client is not allowed to use grant type implicit")) } client := ar.GetClient() for _, scope := range ar.GetRequestedScopes() { if !c.ScopeStrategy(client.GetScopes(), scope) { - return errors.Wrap(fosite.ErrInvalidScope, fmt.Sprintf("The client is not allowed to request scope %s", scope)) + return errors.WithStack(fosite.ErrInvalidScope.WithDebug(fmt.Sprintf("The client is not allowed to request scope %s", scope))) } } @@ -74,11 +74,11 @@ func (c *AuthorizeImplicitGrantTypeHandler) IssueImplicitAccessToken(ctx context // Generate the code token, signature, err := c.AccessTokenStrategy.GenerateAccessToken(ctx, ar) if err != nil { - return errors.Wrap(fosite.ErrServerError, err.Error()) + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } if err := c.AccessTokenStorage.CreateAccessTokenSession(ctx, signature, ar); err != nil { - return errors.Wrap(fosite.ErrServerError, err.Error()) + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } resp.AddFragment("access_token", token) diff --git a/handler/oauth2/flow_client_credentials.go b/handler/oauth2/flow_client_credentials.go index 2da37d08..141ea87b 100644 --- a/handler/oauth2/flow_client_credentials.go +++ b/handler/oauth2/flow_client_credentials.go @@ -40,7 +40,7 @@ func (c *ClientCredentialsGrantHandler) HandleTokenEndpointRequest(_ context.Con client := request.GetClient() for _, scope := range request.GetRequestedScopes() { if !c.ScopeStrategy(client.GetScopes(), scope) { - return errors.Wrap(fosite.ErrInvalidScope, fmt.Sprintf("The client is not allowed to request scope %s", scope)) + return errors.WithStack(fosite.ErrInvalidScope.WithDebug(fmt.Sprintf("The client is not allowed to request scope %s", scope))) } } @@ -48,7 +48,7 @@ func (c *ClientCredentialsGrantHandler) HandleTokenEndpointRequest(_ context.Con // This requirement is already fulfilled because fosite requries all token requests to be authenticated as described // in https://tools.ietf.org/html/rfc6749#section-3.2.1 if client.IsPublic() { - return errors.Wrap(fosite.ErrInvalidGrant, "The client is public and thus not allowed to use grant type client_credentials") + return errors.WithStack(fosite.ErrInvalidGrant.WithDebug("The client is public and thus not allowed to use grant type client_credentials")) } // if the client is not public, he has already been authenticated by the access request handler. @@ -63,7 +63,7 @@ func (c *ClientCredentialsGrantHandler) PopulateTokenEndpointResponse(ctx contex } if !request.GetClient().GetGrantTypes().Has("client_credentials") { - return errors.Wrap(fosite.ErrInvalidGrant, "The client is not allowed to use grant type client_credentials") + return errors.WithStack(fosite.ErrInvalidGrant.WithDebug("The client is not allowed to use grant type client_credentials")) } return c.IssueAccessToken(ctx, request, response) diff --git a/handler/oauth2/flow_refresh.go b/handler/oauth2/flow_refresh.go index 531a4039..234c9410 100644 --- a/handler/oauth2/flow_refresh.go +++ b/handler/oauth2/flow_refresh.go @@ -40,7 +40,7 @@ func (c *RefreshTokenGrantHandler) HandleTokenEndpointRequest(ctx context.Contex } if !request.GetClient().GetGrantTypes().Has("refresh_token") { - return errors.Wrap(fosite.ErrInvalidGrant, "The client is not allowed to use grant type refresh_token") + return errors.WithStack(fosite.ErrInvalidGrant.WithDebug("The client is not allowed to use grant type refresh_token")) } refresh := request.GetRequestForm().Get("refresh_token") @@ -48,23 +48,23 @@ func (c *RefreshTokenGrantHandler) HandleTokenEndpointRequest(ctx context.Contex signature := c.RefreshTokenStrategy.RefreshTokenSignature(refresh) originalRequest, err := c.TokenRevocationStorage.GetRefreshTokenSession(ctx, signature, request.GetSession()) if errors.Cause(err) == fosite.ErrNotFound { - return errors.Wrap(fosite.ErrInvalidRequest, err.Error()) + return errors.WithStack(fosite.ErrInvalidRequest.WithDebug(err.Error())) } else if err != nil { - return errors.Wrap(fosite.ErrServerError, err.Error()) + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } else if err := c.RefreshTokenStrategy.ValidateRefreshToken(ctx, request, refresh); err != nil { // The authorization server MUST ... validate the refresh token. // This needs to happen after store retrieval for the session to be hydrated properly - return errors.Wrap(fosite.ErrInvalidRequest, err.Error()) + return errors.WithStack(fosite.ErrInvalidRequest.WithDebug(err.Error())) } if !originalRequest.GetGrantedScopes().Has("offline") { - return errors.Wrap(fosite.ErrScopeNotGranted, "The client is not allowed to use grant type refresh_token") + return errors.WithStack(fosite.ErrScopeNotGranted.WithDebug("The client is not allowed to use grant type refresh_token")) } // The authorization server MUST ... and ensure that the refresh token was issued to the authenticated client if originalRequest.GetClient().GetID() != request.GetClient().GetID() { - return errors.Wrap(fosite.ErrInvalidRequest, "Client ID mismatch") + return errors.WithStack(fosite.ErrInvalidRequest.WithDebug("Client ID mismatch")) } request.SetSession(originalRequest.GetSession().Clone()) @@ -85,25 +85,25 @@ func (c *RefreshTokenGrantHandler) PopulateTokenEndpointResponse(ctx context.Con accessToken, accessSignature, err := c.AccessTokenStrategy.GenerateAccessToken(ctx, requester) if err != nil { - return errors.Wrap(fosite.ErrServerError, err.Error()) + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } refreshToken, refreshSignature, err := c.RefreshTokenStrategy.GenerateRefreshToken(ctx, requester) if err != nil { - return errors.Wrap(fosite.ErrServerError, err.Error()) + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } signature := c.RefreshTokenStrategy.RefreshTokenSignature(requester.GetRequestForm().Get("refresh_token")) if ts, err := c.TokenRevocationStorage.GetRefreshTokenSession(ctx, signature, nil); err != nil { - return err + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } else if err := c.TokenRevocationStorage.RevokeAccessToken(ctx, ts.GetID()); err != nil { - return err + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } else if err := c.TokenRevocationStorage.RevokeRefreshToken(ctx, ts.GetID()); err != nil { - return err + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } else if err := c.TokenRevocationStorage.CreateAccessTokenSession(ctx, accessSignature, requester); err != nil { - return err + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } else if err := c.TokenRevocationStorage.CreateRefreshTokenSession(ctx, refreshSignature, requester); err != nil { - return err + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } responder.SetAccessToken(accessToken) diff --git a/handler/oauth2/flow_resource_owner.go b/handler/oauth2/flow_resource_owner.go index d54bb2b2..4847ac2a 100644 --- a/handler/oauth2/flow_resource_owner.go +++ b/handler/oauth2/flow_resource_owner.go @@ -43,23 +43,23 @@ func (c *ResourceOwnerPasswordCredentialsGrantHandler) HandleTokenEndpointReques } if !request.GetClient().GetGrantTypes().Has("password") { - return errors.Wrap(fosite.ErrInvalidGrant, "The client is not allowed to use grant type password") + return errors.WithStack(fosite.ErrInvalidGrant.WithDebug("The client is not allowed to use grant type password")) } username := request.GetRequestForm().Get("username") password := request.GetRequestForm().Get("password") if username == "" || password == "" { - return errors.Wrap(fosite.ErrInvalidRequest, "Username or password missing") + return errors.WithStack(fosite.ErrInvalidRequest.WithDebug("Username or password missing")) } else if err := c.ResourceOwnerPasswordCredentialsGrantStorage.Authenticate(ctx, username, password); errors.Cause(err) == fosite.ErrNotFound { - return errors.Wrap(fosite.ErrInvalidRequest, err.Error()) + return errors.WithStack(fosite.ErrInvalidRequest.WithDebug(err.Error())) } else if err != nil { - return errors.Wrap(fosite.ErrServerError, err.Error()) + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } client := request.GetClient() for _, scope := range request.GetRequestedScopes() { if !c.ScopeStrategy(client.GetScopes(), scope) { - return errors.Wrap(fosite.ErrInvalidScope, fmt.Sprintf("The client is not allowed to request scope %s", scope)) + return errors.WithStack(fosite.ErrInvalidScope.WithDebug(fmt.Sprintf("The client is not allowed to request scope %s", scope))) } } @@ -81,9 +81,9 @@ func (c *ResourceOwnerPasswordCredentialsGrantHandler) PopulateTokenEndpointResp var err error refresh, refreshSignature, err = c.RefreshTokenStrategy.GenerateRefreshToken(ctx, requester) if err != nil { - return errors.Wrap(fosite.ErrServerError, err.Error()) + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } else if err := c.ResourceOwnerPasswordCredentialsGrantStorage.CreateRefreshTokenSession(ctx, refreshSignature, requester); err != nil { - return errors.Wrap(fosite.ErrServerError, err.Error()) + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } } diff --git a/handler/oauth2/introspector.go b/handler/oauth2/introspector.go index d5485772..7b3a9463 100644 --- a/handler/oauth2/introspector.go +++ b/handler/oauth2/introspector.go @@ -19,6 +19,7 @@ import ( "github.com/ory/fosite" "github.com/pkg/errors" + "fmt" ) type CoreValidator struct { @@ -59,7 +60,7 @@ func matchScopes(ss fosite.ScopeStrategy, granted, scopes []string) error { } if !ss(granted, scope) { - return errors.Wrapf(fosite.ErrInvalidScope, "Scope %s was not granted", scope) + return errors.WithStack(fosite.ErrInvalidScope.WithDebug(fmt.Sprintf("Scope %s was not granted", scope))) } } @@ -70,7 +71,7 @@ func (c *CoreValidator) introspectAccessToken(ctx context.Context, token string, sig := c.CoreStrategy.AccessTokenSignature(token) or, err := c.CoreStorage.GetAccessTokenSession(ctx, sig, accessRequest.GetSession()) if err != nil { - return errors.Wrap(fosite.ErrRequestUnauthorized, err.Error()) + return errors.WithStack(fosite.ErrRequestUnauthorized.WithDebug(err.Error())) } else if err := c.CoreStrategy.ValidateAccessToken(ctx, or, token); err != nil { return err } @@ -88,7 +89,7 @@ func (c *CoreValidator) introspectRefreshToken(ctx context.Context, token string or, err := c.CoreStorage.GetRefreshTokenSession(ctx, sig, accessRequest.GetSession()) if err != nil { - return errors.Wrap(fosite.ErrRequestUnauthorized, err.Error()) + return errors.WithStack(fosite.ErrRequestUnauthorized.WithDebug(err.Error())) } else if err := c.CoreStrategy.ValidateRefreshToken(ctx, or, token); err != nil { return err } diff --git a/handler/oauth2/strategy_hmacsha.go b/handler/oauth2/strategy_hmacsha.go index 72584947..720a6528 100644 --- a/handler/oauth2/strategy_hmacsha.go +++ b/handler/oauth2/strategy_hmacsha.go @@ -48,10 +48,10 @@ func (h HMACSHAStrategy) GenerateAccessToken(_ context.Context, _ fosite.Request func (h HMACSHAStrategy) ValidateAccessToken(_ context.Context, r fosite.Requester, token string) (err error) { var exp = r.GetSession().GetExpiresAt(fosite.AccessToken) if exp.IsZero() && r.GetRequestedAt().Add(h.AccessTokenLifespan).Before(time.Now()) { - return errors.Wrap(fosite.ErrTokenExpired, fmt.Sprintf("Access token expired at %s", r.GetRequestedAt().Add(h.AccessTokenLifespan))) + return errors.WithStack(fosite.ErrTokenExpired.WithDebug(fmt.Sprintf("Access token expired at %s", r.GetRequestedAt().Add(h.AccessTokenLifespan)))) } if !exp.IsZero() && exp.Before(time.Now()) { - return errors.Wrap(fosite.ErrTokenExpired, fmt.Sprintf("Access token expired at %s", exp)) + return errors.WithStack(fosite.ErrTokenExpired.WithDebug(fmt.Sprintf("Access token expired at %s", exp))) } return h.Enigma.Validate(token) } @@ -71,10 +71,10 @@ func (h HMACSHAStrategy) GenerateAuthorizeCode(_ context.Context, _ fosite.Reque func (h HMACSHAStrategy) ValidateAuthorizeCode(_ context.Context, r fosite.Requester, token string) (err error) { var exp = r.GetSession().GetExpiresAt(fosite.AuthorizeCode) if exp.IsZero() && r.GetRequestedAt().Add(h.AuthorizeCodeLifespan).Before(time.Now()) { - return errors.Wrap(fosite.ErrTokenExpired, fmt.Sprintf("Authorize code expired at %s", r.GetRequestedAt().Add(h.AuthorizeCodeLifespan))) + return errors.WithStack(fosite.ErrTokenExpired.WithDebug(fmt.Sprintf("Authorize code expired at %s", r.GetRequestedAt().Add(h.AuthorizeCodeLifespan)))) } if !exp.IsZero() && exp.Before(time.Now()) { - return errors.Wrap(fosite.ErrTokenExpired, fmt.Sprintf("Authorize code expired at %s", exp)) + return errors.WithStack(fosite.ErrTokenExpired.WithDebug(fmt.Sprintf("Authorize code expired at %s", exp))) } return h.Enigma.Validate(token) diff --git a/handler/oauth2/strategy_jwt.go b/handler/oauth2/strategy_jwt.go index f008eb04..37edca1a 100644 --- a/handler/oauth2/strategy_jwt.go +++ b/handler/oauth2/strategy_jwt.go @@ -119,27 +119,27 @@ func (h *RS256JWTStrategy) validate(token string) (t *jwtx.Token, err error) { if e, ok := errors.Cause(err).(*jwtx.ValidationError); ok { switch e.Errors { case jwtx.ValidationErrorMalformed: - err = errors.Wrap(fosite.ErrInvalidTokenFormat, err.Error()) + err = errors.WithStack(fosite.ErrInvalidTokenFormat.WithDebug(err.Error())) case jwtx.ValidationErrorUnverifiable: - err = errors.Wrap(fosite.ErrTokenSignatureMismatch, err.Error()) + err = errors.WithStack(fosite.ErrTokenSignatureMismatch.WithDebug(err.Error())) case jwtx.ValidationErrorSignatureInvalid: - err = errors.Wrap(fosite.ErrTokenSignatureMismatch, err.Error()) + err = errors.WithStack(fosite.ErrTokenSignatureMismatch.WithDebug(err.Error())) case jwtx.ValidationErrorAudience: - err = errors.Wrap(fosite.ErrTokenClaim, err.Error()) + err = errors.WithStack(fosite.ErrTokenClaim.WithDebug(err.Error())) case jwtx.ValidationErrorExpired: - err = errors.Wrap(fosite.ErrTokenExpired, err.Error()) + err = errors.WithStack(fosite.ErrTokenExpired.WithDebug(err.Error())) case jwtx.ValidationErrorIssuedAt: - err = errors.Wrap(fosite.ErrTokenClaim, err.Error()) + err = errors.WithStack(fosite.ErrTokenClaim.WithDebug(err.Error())) case jwtx.ValidationErrorIssuer: - err = errors.Wrap(fosite.ErrTokenClaim, err.Error()) + err = errors.WithStack(fosite.ErrTokenClaim.WithDebug(err.Error())) case jwtx.ValidationErrorNotValidYet: - err = errors.Wrap(fosite.ErrTokenClaim, err.Error()) + err = errors.WithStack(fosite.ErrTokenClaim.WithDebug(err.Error())) case jwtx.ValidationErrorId: - err = errors.Wrap(fosite.ErrTokenClaim, err.Error()) + err = errors.WithStack(fosite.ErrTokenClaim.WithDebug(err.Error())) case jwtx.ValidationErrorClaimsInvalid: - err = errors.Wrap(fosite.ErrTokenClaim, err.Error()) + err = errors.WithStack(fosite.ErrTokenClaim.WithDebug(err.Error())) default: - err = errors.Wrap(fosite.ErrRequestUnauthorized, err.Error()) + err = errors.WithStack(fosite.ErrRequestUnauthorized.WithDebug(err.Error())) } } } diff --git a/handler/openid/flow_explicit_auth.go b/handler/openid/flow_explicit_auth.go index d31b99df..30b7c973 100644 --- a/handler/openid/flow_explicit_auth.go +++ b/handler/openid/flow_explicit_auth.go @@ -34,15 +34,15 @@ func (c *OpenIDConnectExplicitHandler) HandleAuthorizeEndpointRequest(ctx contex } if !ar.GetClient().GetResponseTypes().Has("id_token", "code") { - return errors.Wrap(fosite.ErrInvalidRequest, "The client is not allowed to use response type id_token and code") + return errors.WithStack(fosite.ErrInvalidRequest.WithDebug("The client is not allowed to use response type id_token and code")) } if len(resp.GetCode()) == 0 { - return errors.Wrap(fosite.ErrMisconfiguration, "Authorization code has not been issued yet") + return errors.WithStack(fosite.ErrMisconfiguration.WithDebug("Authorization code has not been issued yet")) } if err := c.OpenIDConnectRequestStorage.CreateOpenIDConnectSession(ctx, resp.GetCode(), ar); err != nil { - return errors.Wrap(fosite.ErrServerError, err.Error()) + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } // there is no need to check for https, because it has already been checked by core.explicit diff --git a/handler/openid/flow_explicit_token.go b/handler/openid/flow_explicit_token.go index 35b34450..7a6e46b7 100644 --- a/handler/openid/flow_explicit_token.go +++ b/handler/openid/flow_explicit_token.go @@ -32,21 +32,21 @@ func (c *OpenIDConnectExplicitHandler) PopulateTokenEndpointResponse(ctx context authorize, err := c.OpenIDConnectRequestStorage.GetOpenIDConnectSession(ctx, requester.GetRequestForm().Get("code"), requester) if errors.Cause(err) == ErrNoSessionFound { - return errors.Wrap(fosite.ErrUnknownRequest, err.Error()) + return errors.WithStack(fosite.ErrUnknownRequest.WithDebug(err.Error())) } else if err != nil { - return errors.Wrap(fosite.ErrServerError, err.Error()) + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } if !authorize.GetGrantedScopes().Has("openid") { - return errors.Wrap(fosite.ErrMisconfiguration, "The an openid connect session was found but the openid scope is missing in it") + return errors.WithStack(fosite.ErrMisconfiguration.WithDebug("The an openid connect session was found but the openid scope is missing in it")) } if !requester.GetClient().GetGrantTypes().Has("authorization_code") { - return errors.Wrap(fosite.ErrInvalidGrant, "The client is not allowed to use the authorization_code grant type") + return errors.WithStack(fosite.ErrInvalidGrant.WithDebug("The client is not allowed to use the authorization_code grant type")) } if !requester.GetClient().GetResponseTypes().Has("id_token") { - return errors.Wrap(fosite.ErrInvalidGrant, "The client is not allowed to use response type id_token") + return errors.WithStack(fosite.ErrInvalidGrant.WithDebug("The client is not allowed to use response type id_token")) } return c.IssueExplicitIDToken(ctx, authorize, responder) diff --git a/handler/openid/flow_hybrid.go b/handler/openid/flow_hybrid.go index 128bd3c8..cb858692 100644 --- a/handler/openid/flow_hybrid.go +++ b/handler/openid/flow_hybrid.go @@ -45,11 +45,11 @@ func (c *OpenIDConnectHybridHandler) HandleAuthorizeEndpointRequest(ctx context. } if ar.GetResponseTypes().Matches("token") && !ar.GetClient().GetResponseTypes().Has("token") { - return errors.Wrap(fosite.ErrInvalidGrant, "The client is not allowed to use the token response type") + return errors.WithStack(fosite.ErrInvalidGrant.WithDebug("The client is not allowed to use the token response type")) } else if ar.GetResponseTypes().Matches("code") && !ar.GetClient().GetResponseTypes().Has("code") { - return errors.Wrap(fosite.ErrInvalidGrant, "The client is not allowed to use the code response type") + return errors.WithStack(fosite.ErrInvalidGrant.WithDebug("The client is not allowed to use the code response type")) } else if ar.GetResponseTypes().Matches("id_token") && !ar.GetClient().GetResponseTypes().Has("id_token") { - return errors.Wrap(fosite.ErrInvalidGrant, "The client is not allowed to use the id_token response type") + return errors.WithStack(fosite.ErrInvalidGrant.WithDebug("The client is not allowed to use the id_token response type")) } sess, ok := ar.GetSession().(Session) @@ -60,21 +60,21 @@ func (c *OpenIDConnectHybridHandler) HandleAuthorizeEndpointRequest(ctx context. client := ar.GetClient() for _, scope := range ar.GetRequestedScopes() { if !c.ScopeStrategy(client.GetScopes(), scope) { - return errors.Wrap(fosite.ErrInvalidScope, fmt.Sprintf("The client is not allowed to request scope %s", scope)) + return errors.WithStack(fosite.ErrInvalidScope.WithDebug(fmt.Sprintf("The client is not allowed to request scope %s", scope))) } } claims := sess.IDTokenClaims() if ar.GetResponseTypes().Has("code") { if !ar.GetClient().GetGrantTypes().Has("authorization_code") { - return errors.Wrap(fosite.ErrInvalidGrant, "The client is not allowed to use the authorization_code grant type") + return errors.WithStack(fosite.ErrInvalidGrant.WithDebug("The client is not allowed to use the authorization_code grant type")) } code, signature, err := c.AuthorizeExplicitGrantHandler.AuthorizeCodeStrategy.GenerateAuthorizeCode(ctx, ar) if err != nil { - return errors.Wrap(fosite.ErrServerError, err.Error()) + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } else if err := c.AuthorizeExplicitGrantHandler.CoreStorage.CreateAuthorizeCodeSession(ctx, signature, ar); err != nil { - return errors.Wrap(fosite.ErrServerError, err.Error()) + return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } resp.AddFragment("code", code) @@ -89,9 +89,9 @@ func (c *OpenIDConnectHybridHandler) HandleAuthorizeEndpointRequest(ctx context. if ar.GetResponseTypes().Has("token") { if !ar.GetClient().GetGrantTypes().Has("implicit") { - return errors.Wrap(fosite.ErrInvalidGrant, "The client is not allowed to use the implicit grant type") + return errors.WithStack(fosite.ErrInvalidGrant.WithDebug("The client is not allowed to use the implicit grant type")) } else if err := c.AuthorizeImplicitGrantTypeHandler.IssueImplicitAccessToken(ctx, ar, resp); err != nil { - return errors.Wrap(err, err.Error()) + return errors.WithStack(err) } ar.SetResponseTypeHandled("token") @@ -112,7 +112,7 @@ func (c *OpenIDConnectHybridHandler) HandleAuthorizeEndpointRequest(ctx context. } if err := c.IDTokenHandleHelper.IssueImplicitIDToken(ctx, ar, resp); err != nil { - return errors.Wrap(err, err.Error()) + return errors.WithStack(err) } ar.SetResponseTypeHandled("id_token") diff --git a/handler/openid/flow_implicit.go b/handler/openid/flow_implicit.go index 3fd4833b..2fe9ca72 100644 --- a/handler/openid/flow_implicit.go +++ b/handler/openid/flow_implicit.go @@ -43,19 +43,19 @@ func (c *OpenIDConnectImplicitHandler) HandleAuthorizeEndpointRequest(ctx contex } if !ar.GetClient().GetGrantTypes().Has("implicit") { - return errors.Wrap(fosite.ErrInvalidGrant, "The client is not allowed to use implicit grant type") + return errors.WithStack(fosite.ErrInvalidGrant.WithDebug("The client is not allowed to use implicit grant type")) } if ar.GetResponseTypes().Exact("id_token") && !ar.GetClient().GetResponseTypes().Has("id_token") { - return errors.Wrap(fosite.ErrInvalidGrant, "The client is not allowed to use response type id_token") + return errors.WithStack(fosite.ErrInvalidGrant.WithDebug("The client is not allowed to use response type id_token")) } else if ar.GetResponseTypes().Matches("token", "id_token") && !ar.GetClient().GetResponseTypes().Has("token", "id_token") { - return errors.Wrap(fosite.ErrInvalidGrant, "The client is not allowed to use response type token and id_token") + return errors.WithStack(fosite.ErrInvalidGrant.WithDebug("The client is not allowed to use response type token and id_token")) } client := ar.GetClient() for _, scope := range ar.GetRequestedScopes() { if !c.ScopeStrategy(client.GetScopes(), scope) { - return errors.Wrap(fosite.ErrInvalidScope, fmt.Sprintf("The client is not allowed to request scope %s", scope)) + return errors.WithStack(fosite.ErrInvalidScope.WithDebug(fmt.Sprintf("The client is not allowed to request scope %s", scope))) } } @@ -67,7 +67,7 @@ func (c *OpenIDConnectImplicitHandler) HandleAuthorizeEndpointRequest(ctx contex claims := sess.IDTokenClaims() if ar.GetResponseTypes().Has("token") { if err := c.AuthorizeImplicitGrantTypeHandler.IssueImplicitAccessToken(ctx, ar, resp); err != nil { - return errors.Wrap(err, err.Error()) + return errors.WithStack(err) } ar.SetResponseTypeHandled("token") @@ -82,7 +82,7 @@ func (c *OpenIDConnectImplicitHandler) HandleAuthorizeEndpointRequest(ctx contex } if err := c.IssueImplicitIDToken(ctx, ar, resp); err != nil { - return errors.Wrap(err, err.Error()) + return errors.WithStack(err) } // there is no need to check for https, because implicit flow does not require https diff --git a/handler/openid/flow_refresh_token.go b/handler/openid/flow_refresh_token.go index b66379c3..02b5fd38 100644 --- a/handler/openid/flow_refresh_token.go +++ b/handler/openid/flow_refresh_token.go @@ -36,11 +36,11 @@ func (c *OpenIDConnectRefreshHandler) HandleTokenEndpointRequest(ctx context.Con } if !request.GetClient().GetGrantTypes().Has("refresh_token") { - return errors.Wrap(fosite.ErrInvalidGrant, "The client is not allowed to use the authorization_code grant type") + return errors.WithStack(fosite.ErrInvalidGrant.WithDebug("The client is not allowed to use the authorization_code grant type")) } if !request.GetClient().GetResponseTypes().Has("id_token") { - return errors.Wrap(fosite.ErrUnknownRequest, "The client is not allowed to use response type id_token") + return errors.WithStack(fosite.ErrUnknownRequest.WithDebug("The client is not allowed to use response type id_token")) } sess, ok := request.GetSession().(Session) @@ -63,11 +63,11 @@ func (c *OpenIDConnectRefreshHandler) PopulateTokenEndpointResponse(ctx context. } if !requester.GetClient().GetGrantTypes().Has("refresh_token") { - return errors.Wrap(fosite.ErrInvalidGrant, "The client is not allowed to use the authorization_code grant type") + return errors.WithStack(fosite.ErrInvalidGrant.WithDebug("The client is not allowed to use the authorization_code grant type")) } if !requester.GetClient().GetResponseTypes().Has("id_token") { - return errors.Wrap(errors.WithStack(fosite.ErrUnknownRequest), "The client is not allowed to use response type id_token") + return errors.WithStack(fosite.ErrUnknownRequest.WithDebug("The client is not allowed to use response type id_token")) } return c.IssueExplicitIDToken(ctx, requester, responder) diff --git a/introspect.go b/introspect.go index d8f1fe3a..440a78fb 100644 --- a/introspect.go +++ b/introspect.go @@ -55,14 +55,15 @@ func (f *Fosite) IntrospectToken(ctx context.Context, token string, tokenType To if err := errors.Cause(validator.IntrospectToken(ctx, token, tokenType, ar, scopes)); err == ErrUnknownRequest { // Nothing to do } else if err != nil { - return nil, errors.Wrap(err, "A validator returned an error") + rfcerr := ErrorToRFC6749Error(err) + return nil, errors.WithStack(rfcerr.WithDebug("A validator returned an error")) } else { found = true } } if !found { - return nil, errors.Wrap(ErrRequestUnauthorized, "No validator felt responsible for validating the token") + return nil, errors.WithStack(ErrRequestUnauthorized.WithDebug("No validator felt responsible for validating the token")) } return ar, nil diff --git a/introspection_request_handler.go b/introspection_request_handler.go index eadc50c9..a6bd0731 100644 --- a/introspection_request_handler.go +++ b/introspection_request_handler.go @@ -19,6 +19,8 @@ import ( "net/http" "strings" + "fmt" + "github.com/pkg/errors" ) @@ -103,9 +105,9 @@ import ( // token=mF_9.B5f-4.1JqM&token_type_hint=access_token func (f *Fosite) NewIntrospectionRequest(ctx context.Context, r *http.Request, session Session) (IntrospectionResponder, error) { if r.Method != "POST" { - return &IntrospectionResponse{Active: false}, errors.Wrap(ErrInvalidRequest, "HTTP method is not POST") + return &IntrospectionResponse{Active: false}, errors.WithStack(ErrInvalidRequest.WithDebug("HTTP method is not POST")) } else if err := r.ParseForm(); err != nil { - return &IntrospectionResponse{Active: false}, errors.Wrap(ErrInvalidRequest, err.Error()) + return &IntrospectionResponse{Active: false}, errors.WithStack(ErrInvalidRequest.WithDebug(err.Error())) } token := r.PostForm.Get("token") @@ -113,32 +115,32 @@ func (f *Fosite) NewIntrospectionRequest(ctx context.Context, r *http.Request, s scope := r.PostForm.Get("scope") if clientToken := AccessTokenFromRequest(r); clientToken != "" { if token == clientToken { - return &IntrospectionResponse{Active: false}, errors.Wrap(ErrRequestUnauthorized, "Bearer and introspection token are identical") + return &IntrospectionResponse{Active: false}, errors.WithStack(ErrRequestUnauthorized.WithDebug("Bearer and introspection token are identical")) } if _, err := f.IntrospectToken(ctx, clientToken, AccessToken, session.Clone()); err != nil { - return &IntrospectionResponse{Active: false}, errors.Wrap(ErrRequestUnauthorized, "HTTP Authorization header missing, malformed or credentials used are invalid") + return &IntrospectionResponse{Active: false}, errors.WithStack(ErrRequestUnauthorized.WithDebug("HTTP Authorization header missing.WithDebug(malformed or credentials used are invalid")) } } else { clientID, clientSecret, ok := r.BasicAuth() if !ok { - return &IntrospectionResponse{Active: false}, errors.Wrap(ErrRequestUnauthorized, "HTTP Authorization header missing, malformed or credentials used are invalid") + return &IntrospectionResponse{Active: false}, errors.WithStack(ErrRequestUnauthorized.WithDebug("HTTP Authorization header missing.WithDebug(malformed or credentials used are invalid")) } client, err := f.Store.GetClient(ctx, clientID) if err != nil { - return &IntrospectionResponse{Active: false}, errors.Wrap(ErrRequestUnauthorized, "HTTP Authorization header missing, malformed or credentials used are invalid") + return &IntrospectionResponse{Active: false}, errors.WithStack(ErrRequestUnauthorized.WithDebug("HTTP Authorization header missing.WithDebug(malformed or credentials used are invalid")) } // Enforce client authentication if err := f.Hasher.Compare(client.GetHashedSecret(), []byte(clientSecret)); err != nil { - return &IntrospectionResponse{Active: false}, errors.Wrap(ErrRequestUnauthorized, "HTTP Authorization header missing, malformed or credentials used are invalid") + return &IntrospectionResponse{Active: false}, errors.WithStack(ErrRequestUnauthorized.WithDebug("HTTP Authorization header missing.WithDebug(malformed or credentials used are invalid")) } } ar, err := f.IntrospectToken(ctx, token, TokenType(tokenType), session, strings.Split(scope, " ")...) if err != nil { - return &IntrospectionResponse{Active: false}, errors.Wrapf(ErrInactiveToken, "Validator returned error %s", err.Error()) + return &IntrospectionResponse{Active: false}, errors.WithStack(ErrInactiveToken.WithDebug(fmt.Sprintf("Validator returned error %s", err.Error()))) } return &IntrospectionResponse{ diff --git a/revoke_handler.go b/revoke_handler.go index c611ad58..0bf51ddc 100644 --- a/revoke_handler.go +++ b/revoke_handler.go @@ -43,25 +43,25 @@ import ( // server and does not influence the revocation response. func (f *Fosite) NewRevocationRequest(ctx context.Context, r *http.Request) error { if r.Method != "POST" { - return errors.Wrap(ErrInvalidRequest, "HTTP method is not POST") + return errors.WithStack(ErrInvalidRequest.WithDebug("HTTP method is not POST")) } else if err := r.ParseForm(); err != nil { - return errors.Wrap(ErrInvalidRequest, err.Error()) + return errors.WithStack(ErrInvalidRequest.WithDebug(err.Error())) } clientID, clientSecret, ok := r.BasicAuth() if !ok { - return errors.Wrap(ErrInvalidRequest, "HTTP Authorization header missing or invalid") + return errors.WithStack(ErrInvalidRequest.WithDebug("HTTP Authorization header missing or invalid")) } client, err := f.Store.GetClient(ctx, clientID) if err != nil { - return errors.Wrap(ErrInvalidClient, err.Error()) + return errors.WithStack(ErrInvalidClient.WithDebug(err.Error())) } // Enforce client authentication for confidential clients if !client.IsPublic() { if err := f.Hasher.Compare(client.GetHashedSecret(), []byte(clientSecret)); err != nil { - return errors.Wrap(ErrInvalidClient, err.Error()) + return errors.WithStack(ErrInvalidClient.WithDebug(err.Error())) } } diff --git a/token/jwt/jwt.go b/token/jwt/jwt.go index 4a6a7beb..0175facc 100644 --- a/token/jwt/jwt.go +++ b/token/jwt/jwt.go @@ -23,6 +23,7 @@ import ( "strings" "github.com/dgrijalva/jwt-go" + "github.com/ory/fosite" "github.com/pkg/errors" ) @@ -73,9 +74,9 @@ func (j *RS256JWTStrategy) Decode(token string) (*jwt.Token, error) { }) if err != nil { - return nil, errors.Wrap(err, "Couldn't parse token") + return nil, errors.WithStack(fosite.ErrorToRFC6749Error(err).WithDebug("Couldn't parse token")) } else if !parsedToken.Valid { - return nil, errors.Errorf("Token is invalid") + return nil, errors.WithStack(fosite.ErrInactiveToken) } return parsedToken, err From 59fc47bbeb8093ab3652149ef6789a4e1564e1d8 Mon Sep 17 00:00:00 2001 From: arekkas Date: Sat, 9 Dec 2017 22:48:36 +0100 Subject: [PATCH 23/35] Resolves test issues and reverts auth code revokation patch --- access_request_handler.go | 2 +- access_response_writer.go | 3 +- access_response_writer_test.go | 21 ++++-- authorize_request_handler_test.go | 35 +++++----- compose/compose_oauth2.go | 16 ++--- errors.go | 4 +- handler/oauth2/flow_authorize_code_auth.go | 10 +-- handler/oauth2/flow_authorize_code_token.go | 21 ++++-- .../oauth2/flow_authorize_code_token_test.go | 69 +++++++++++-------- .../oauth2/flow_authorize_implicit_test.go | 17 +++-- .../oauth2/flow_client_credentials_test.go | 31 ++++++--- handler/oauth2/flow_resource_owner_test.go | 42 +++++++---- handler/oauth2/introspector.go | 3 +- handler/oauth2/introspector_jwt_test.go | 28 ++++---- handler/oauth2/introspector_test.go | 17 +++-- handler/oauth2/revocation_test.go | 19 +++-- handler/oauth2/strategy_jwt_test.go | 1 + handler/openid/flow_explicit_auth_test.go | 18 +++-- handler/openid/flow_explicit_token.go | 2 +- handler/openid/flow_explicit_token_test.go | 19 +++-- handler/openid/flow_hybrid_test.go | 29 ++++---- handler/openid/flow_implicit_test.go | 23 ++++--- integration/revoke_token_test.go | 6 +- introspect.go | 6 +- introspect_test.go | 17 +++-- introspection_request_handler_test.go | 21 ++++-- revoke_handler.go | 13 ++-- revoke_handler_test.go | 35 ++++++---- token/jwt/jwt.go | 2 +- 29 files changed, 333 insertions(+), 197 deletions(-) diff --git a/access_request_handler.go b/access_request_handler.go index 8a41b5fc..c0eeda37 100644 --- a/access_request_handler.go +++ b/access_request_handler.go @@ -93,7 +93,7 @@ func (f *Fosite) NewAccessRequest(ctx context.Context, r *http.Request, session for _, loader := range f.TokenEndpointHandlers { if err := loader.HandleTokenEndpointRequest(ctx, accessRequest); err == nil { found = true - } else if errors.Cause(err) == ErrUnknownRequest { + } else if errors.Cause(err).Error() == ErrUnknownRequest.Error() { // do nothing } else if err != nil { return accessRequest, err diff --git a/access_response_writer.go b/access_response_writer.go index c8d51fcc..e190c207 100644 --- a/access_response_writer.go +++ b/access_response_writer.go @@ -26,7 +26,8 @@ func (f *Fosite) NewAccessResponse(ctx context.Context, requester AccessRequeste response := NewAccessResponse() for _, tk = range f.TokenEndpointHandlers { - if err = tk.PopulateTokenEndpointResponse(ctx, requester, response); errors.Cause(err) == ErrUnknownRequest { + if err = tk.PopulateTokenEndpointResponse(ctx, requester, response); err == nil { + } else if errors.Cause(err).Error() == ErrUnknownRequest.Error() { } else if err != nil { return nil, err } diff --git a/access_response_writer_test.go b/access_response_writer_test.go index 38e89200..f37d3c6b 100644 --- a/access_response_writer_test.go +++ b/access_response_writer_test.go @@ -19,11 +19,14 @@ import ( "context" + "fmt" + "github.com/golang/mock/gomock" . "github.com/ory/fosite" "github.com/ory/fosite/internal" "github.com/pkg/errors" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestNewAccessResponse(t *testing.T) { @@ -81,11 +84,17 @@ func TestNewAccessResponse(t *testing.T) { }, }, } { - f.TokenEndpointHandlers = c.handlers - c.mock() - ar, err := f.NewAccessResponse(nil, nil) - assert.True(t, errors.Cause(err) == c.expectErr, "%d", k) - assert.Equal(t, ar, c.expect) - t.Logf("Passed test case %d", k) + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + f.TokenEndpointHandlers = c.handlers + c.mock() + ar, err := f.NewAccessResponse(nil, nil) + + if c.expectErr != nil { + assert.EqualError(t, errors.Cause(err), c.expectErr.Error()) + } else { + require.NoError(t, err) + assert.Equal(t, ar, c.expect) + } + }) } } diff --git a/authorize_request_handler_test.go b/authorize_request_handler_test.go index 3a6b61ac..0580120a 100644 --- a/authorize_request_handler_test.go +++ b/authorize_request_handler_test.go @@ -21,11 +21,14 @@ import ( "context" + "fmt" + "github.com/golang/mock/gomock" . "github.com/ory/fosite" . "github.com/ory/fosite/internal" "github.com/pkg/errors" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) // Should pass @@ -171,23 +174,23 @@ func TestNewAuthorizeRequest(t *testing.T) { }, }, } { - t.Logf("Joining test case %d", k) - c.mock() - if c.r == nil { - c.r = &http.Request{Header: http.Header{}} - if c.query != nil { - c.r.URL = &url.URL{RawQuery: c.query.Encode()} + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + c.mock() + if c.r == nil { + c.r = &http.Request{Header: http.Header{}} + if c.query != nil { + c.r.URL = &url.URL{RawQuery: c.query.Encode()} + } } - } - ar, err := c.conf.NewAuthorizeRequest(context.Background(), c.r) - assert.Equal(t, c.expectedError == nil, err == nil, "%d: %s\n%s", k, c.desc, err) - if c.expectedError != nil { - assert.Equal(t, errors.Cause(err), c.expectedError, "%d: %s\n%s", k, c.desc, err) - } else { - AssertObjectKeysEqual(t, c.expect, ar, "ResponseTypes", "Scopes", "Client", "RedirectURI", "State") - assert.NotNil(t, ar.GetRequestedAt()) - } - t.Logf("Passed test case %d", k) + ar, err := c.conf.NewAuthorizeRequest(context.Background(), c.r) + if c.expectedError != nil { + assert.EqualError(t, errors.Cause(err), c.expectedError.Error()) + } else { + require.NoError(t, err) + AssertObjectKeysEqual(t, c.expect, ar, "ResponseTypes", "Scopes", "Client", "RedirectURI", "State") + assert.NotNil(t, ar.GetRequestedAt()) + } + }) } } diff --git a/compose/compose_oauth2.go b/compose/compose_oauth2.go index 79b7ae70..7a09c021 100644 --- a/compose/compose_oauth2.go +++ b/compose/compose_oauth2.go @@ -22,14 +22,14 @@ import ( // an access token, refresh token and authorize code validator. func OAuth2AuthorizeExplicitFactory(config *Config, storage interface{}, strategy interface{}) interface{} { return &oauth2.AuthorizeExplicitGrantHandler{ - AccessTokenStrategy: strategy.(oauth2.AccessTokenStrategy), - RefreshTokenStrategy: strategy.(oauth2.RefreshTokenStrategy), - AuthorizeCodeStrategy: strategy.(oauth2.AuthorizeCodeStrategy), - CoreStorage: storage.(oauth2.CoreStorage), - AuthCodeLifespan: config.GetAuthorizeCodeLifespan(), - AccessTokenLifespan: config.GetAccessTokenLifespan(), - ScopeStrategy: config.GetScopeStrategy(), - TokenRevocationStorage: storage.(oauth2.TokenRevocationStorage), + AccessTokenStrategy: strategy.(oauth2.AccessTokenStrategy), + RefreshTokenStrategy: strategy.(oauth2.RefreshTokenStrategy), + AuthorizeCodeStrategy: strategy.(oauth2.AuthorizeCodeStrategy), + CoreStorage: storage.(oauth2.CoreStorage), + AuthCodeLifespan: config.GetAuthorizeCodeLifespan(), + AccessTokenLifespan: config.GetAccessTokenLifespan(), + ScopeStrategy: config.GetScopeStrategy(), + //TokenRevocationStorage: storage.(oauth2.TokenRevocationStorage), } } diff --git a/errors.go b/errors.go index 1853215c..181a0493 100644 --- a/errors.go +++ b/errors.go @@ -148,7 +148,7 @@ var ( Hint: "Token validation failed.", Code: http.StatusUnauthorized, } - ErrInactiveCode = &RFC6749Error{ + ErrInactiveAuthorizationCode = &RFC6749Error{ Name: errAuthorizaionCodeInactiveName, Description: "Authorization code is inactive because it is malformed, expired or otherwise invalid", Hint: "Authorization code validation failed.", @@ -237,6 +237,6 @@ func (e *RFC6749Error) StatusCode() int { func (e *RFC6749Error) WithDebug(debug string) *RFC6749Error { err := *e - e.Debug = debug + err.Debug = debug return &err } diff --git a/handler/oauth2/flow_authorize_code_auth.go b/handler/oauth2/flow_authorize_code_auth.go index 0f153651..837eee36 100644 --- a/handler/oauth2/flow_authorize_code_auth.go +++ b/handler/oauth2/flow_authorize_code_auth.go @@ -29,11 +29,11 @@ import ( // AuthorizeExplicitGrantTypeHandler is a response handler for the Authorize Code grant using the explicit grant type // as defined in https://tools.ietf.org/html/rfc6749#section-4.1 type AuthorizeExplicitGrantHandler struct { - AccessTokenStrategy AccessTokenStrategy - RefreshTokenStrategy RefreshTokenStrategy - AuthorizeCodeStrategy AuthorizeCodeStrategy - CoreStorage CoreStorage - TokenRevocationStorage TokenRevocationStorage + AccessTokenStrategy AccessTokenStrategy + RefreshTokenStrategy RefreshTokenStrategy + AuthorizeCodeStrategy AuthorizeCodeStrategy + CoreStorage CoreStorage + //TokenRevocationStorage TokenRevocationStorage // AuthCodeLifespan defines the lifetime of an authorize code. AuthCodeLifespan time.Duration diff --git a/handler/oauth2/flow_authorize_code_token.go b/handler/oauth2/flow_authorize_code_token.go index cc37fbb9..d5096a0b 100644 --- a/handler/oauth2/flow_authorize_code_token.go +++ b/handler/oauth2/flow_authorize_code_token.go @@ -38,13 +38,20 @@ func (c *AuthorizeExplicitGrantHandler) HandleTokenEndpointRequest(ctx context.C code := request.GetRequestForm().Get("code") signature := c.AuthorizeCodeStrategy.AuthorizeCodeSignature(code) authorizeRequest, err := c.CoreStorage.GetAuthorizeCodeSession(ctx, signature, request.GetSession()) - if errors.Cause(err) == fosite.ErrNotFound { + if err != nil && errors.Cause(err).Error() == fosite.ErrNotFound.Error() { // If an authorize code is used twice (which is likely the case here), we should try and invalidate any previously // issued access and refresh tokens. - c.TokenRevocationStorage.RevokeAccessToken(ctx, authorizeRequest.GetID()) - c.TokenRevocationStorage.RevokeRefreshToken(ctx, authorizeRequest.GetID()) - - return errors.WithStack(fosite.ErrInactiveCode) + // reqID := authorizeRequest.GetID() + // + var debug string + // if revErr := c.TokenRevocationStorage.RevokeAccessToken(ctx, reqID); revErr != nil { + // debug += revErr.Error() + "\n" + // } + // if revErr := c.TokenRevocationStorage.RevokeRefreshToken(ctx, reqID); revErr != nil { + // debug += revErr.Error() + "\n" + // } + + return errors.WithStack(fosite.ErrInactiveAuthorizationCode.WithDebug(debug)) } else if err != nil { return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } @@ -52,7 +59,7 @@ func (c *AuthorizeExplicitGrantHandler) HandleTokenEndpointRequest(ctx context.C // The authorization server MUST verify that the authorization code is valid // This needs to happen after store retrieval for the session to be hydrated properly if err := c.AuthorizeCodeStrategy.ValidateAuthorizeCode(ctx, request, code); err != nil { - return errors.WithStack(fosite.ErrInactiveCode.WithDebug(err.Error())) + return errors.WithStack(fosite.ErrInactiveAuthorizationCode.WithDebug(err.Error())) } // Override scopes @@ -62,7 +69,7 @@ func (c *AuthorizeExplicitGrantHandler) HandleTokenEndpointRequest(ctx context.C // confidential client, or if the client is public, ensure that the // code was issued to "client_id" in the request, if authorizeRequest.GetClient().GetID() != request.GetClient().GetID() { - return errors.WithStack(fosite.ErrInactiveCode.WithDebug("Client ID mismatch")) + return errors.WithStack(fosite.ErrInvalidRequest.WithDebug("Client ID mismatch")) } // ensure that the "redirect_uri" parameter is present if the diff --git a/handler/oauth2/flow_authorize_code_token_test.go b/handler/oauth2/flow_authorize_code_token_test.go index 23826db4..05f9eeb8 100644 --- a/handler/oauth2/flow_authorize_code_token_test.go +++ b/handler/oauth2/flow_authorize_code_token_test.go @@ -24,6 +24,10 @@ import ( //"github.com/ory/fosite/internal" "time" + "context" + + "fmt" + "github.com/ory/fosite/storage" "github.com/pkg/errors" "github.com/stretchr/testify/assert" @@ -38,13 +42,13 @@ func TestAuthorizeCode_PopulateTokenEndpointResponse(t *testing.T) { store := storage.NewMemoryStore() h := AuthorizeExplicitGrantHandler{ - CoreStorage: store, - AuthorizeCodeStrategy: strategy, - AccessTokenStrategy: strategy, - RefreshTokenStrategy: strategy, - ScopeStrategy: fosite.HierarchicScopeStrategy, - AccessTokenLifespan: time.Minute, - TokenRevocationStorage: store, + CoreStorage: store, + AuthorizeCodeStrategy: strategy, + AccessTokenStrategy: strategy, + RefreshTokenStrategy: strategy, + ScopeStrategy: fosite.HierarchicScopeStrategy, + AccessTokenLifespan: time.Minute, + //TokenRevocationStorage: store, } for _, c := range []struct { areq *fosite.AccessRequest @@ -163,8 +167,10 @@ func TestAuthorizeCode_HandleTokenEndpointRequest(t *testing.T) { CoreStorage: store, AuthorizeCodeStrategy: hmacshaStrategy, ScopeStrategy: fosite.HierarchicScopeStrategy, + //TokenRevocationStorage: store, + AuthCodeLifespan: time.Minute, } - for _, c := range []struct { + for i, c := range []struct { areq *fosite.AccessRequest authreq *fosite.AuthorizeRequest description string @@ -182,19 +188,21 @@ func TestAuthorizeCode_HandleTokenEndpointRequest(t *testing.T) { areq: &fosite.AccessRequest{ GrantTypes: fosite.Arguments{"authorization_code"}, Request: fosite.Request{ - Client: &fosite.DefaultClient{ID: "foo"}, - Session: &fosite.DefaultSession{}, + Client: &fosite.DefaultClient{ID: "foo", GrantTypes: []string{""}}, + Session: &fosite.DefaultSession{}, + RequestedAt: time.Now(), }, }, description: "should fail because client is not granted this grant type", - expectErr: fosite.ErrInvalidRequest, + expectErr: fosite.ErrInvalidGrant, }, { areq: &fosite.AccessRequest{ GrantTypes: fosite.Arguments{"authorization_code"}, Request: fosite.Request{ - Client: &fosite.DefaultClient{GrantTypes: []string{"authorization_code"}}, - Session: &fosite.DefaultSession{}, + Client: &fosite.DefaultClient{GrantTypes: []string{"authorization_code"}}, + Session: &fosite.DefaultSession{}, + RequestedAt: time.Now(), }, }, description: "should fail because authcode could not be retrieved (1)", @@ -203,26 +211,28 @@ func TestAuthorizeCode_HandleTokenEndpointRequest(t *testing.T) { require.NoError(t, err) areq.Form = url.Values{"code": {token}} }, - expectErr: fosite.ErrInvalidRequest, + expectErr: fosite.ErrInactiveAuthorizationCode, }, { areq: &fosite.AccessRequest{ GrantTypes: fosite.Arguments{"authorization_code"}, Request: fosite.Request{ - Form: url.Values{"code": {"foo.bar"}}, - Client: &fosite.DefaultClient{GrantTypes: []string{"authorization_code"}}, - Session: &fosite.DefaultSession{}, + Form: url.Values{"code": {"foo.bar"}}, + Client: &fosite.DefaultClient{GrantTypes: []string{"authorization_code"}}, + Session: &fosite.DefaultSession{}, + RequestedAt: time.Now(), }, }, description: "should fail because authcode validation failed", - expectErr: fosite.ErrInvalidRequest, + expectErr: fosite.ErrInactiveAuthorizationCode, }, { areq: &fosite.AccessRequest{ GrantTypes: fosite.Arguments{"authorization_code"}, Request: fosite.Request{ - Client: &fosite.DefaultClient{ID: "foo", GrantTypes: []string{"authorization_code"}}, - Session: &fosite.DefaultSession{}, + Client: &fosite.DefaultClient{ID: "foo", GrantTypes: []string{"authorization_code"}}, + Session: &fosite.DefaultSession{}, + RequestedAt: time.Now(), }, }, authreq: &fosite.AuthorizeRequest{ @@ -245,8 +255,9 @@ func TestAuthorizeCode_HandleTokenEndpointRequest(t *testing.T) { areq: &fosite.AccessRequest{ GrantTypes: fosite.Arguments{"authorization_code"}, Request: fosite.Request{ - Client: &fosite.DefaultClient{ID: "foo", GrantTypes: []string{"authorization_code"}}, - Session: &fosite.DefaultSession{}, + Client: &fosite.DefaultClient{ID: "foo", GrantTypes: []string{"authorization_code"}}, + Session: &fosite.DefaultSession{}, + RequestedAt: time.Now(), }, }, authreq: &fosite.AuthorizeRequest{ @@ -273,7 +284,7 @@ func TestAuthorizeCode_HandleTokenEndpointRequest(t *testing.T) { Client: &fosite.DefaultClient{ID: "foo", GrantTypes: []string{"authorization_code"}}, Form: url.Values{"redirect_uri": []string{"request-redir"}}, Session: &fosite.DefaultSession{}, - RequestedAt: time.Now().Add(time.Hour), + RequestedAt: time.Now(), }, }, authreq: &fosite.AuthorizeRequest{ @@ -281,7 +292,7 @@ func TestAuthorizeCode_HandleTokenEndpointRequest(t *testing.T) { Client: &fosite.DefaultClient{ID: "foo", GrantTypes: []string{"authorization_code"}}, Session: &fosite.DefaultSession{}, Scopes: fosite.Arguments{"a", "b"}, - RequestedAt: time.Now().Add(time.Hour), + RequestedAt: time.Now(), }, }, description: "should pass", @@ -294,16 +305,18 @@ func TestAuthorizeCode_HandleTokenEndpointRequest(t *testing.T) { }, }, } { - t.Run("case="+c.description, func(t *testing.T) { + t.Run(fmt.Sprintf("case=%d/description=%s", i, c.description), func(t *testing.T) { if c.setup != nil { c.setup(t, c.areq, c.authreq) } - err := h.HandleTokenEndpointRequest(nil, c.areq) + t.Logf("Processing %+v", c.areq.Client) + + err := h.HandleTokenEndpointRequest(context.Background(), c.areq) if c.expectErr != nil { - require.EqualError(t, errors.Cause(err), c.expectErr.Error(), "%v", err) + require.EqualError(t, errors.Cause(err), c.expectErr.Error()) } else { - require.NoError(t, err, "%v", err) + require.NoError(t, err) } }) } diff --git a/handler/oauth2/flow_authorize_implicit_test.go b/handler/oauth2/flow_authorize_implicit_test.go index 42c6f7ba..b494f717 100644 --- a/handler/oauth2/flow_authorize_implicit_test.go +++ b/handler/oauth2/flow_authorize_implicit_test.go @@ -18,11 +18,13 @@ import ( "testing" "time" + "fmt" + "github.com/golang/mock/gomock" "github.com/ory/fosite" "github.com/ory/fosite/internal" "github.com/pkg/errors" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestAuthorizeImplicit_EndpointHandler(t *testing.T) { @@ -89,9 +91,14 @@ func TestAuthorizeImplicit_EndpointHandler(t *testing.T) { expectErr: nil, }, } { - c.setup() - err := h.HandleAuthorizeEndpointRequest(nil, areq, aresp) - assert.True(t, errors.Cause(err) == c.expectErr, "(%d) %s\n%s\n%s", k, c.description, err, c.expectErr) - t.Logf("Passed test case %d", k) + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + c.setup() + err := h.HandleAuthorizeEndpointRequest(nil, areq, aresp) + if c.expectErr != nil { + require.EqualError(t, err, c.expectErr.Error()) + } else { + require.NoError(t, err) + } + }) } } diff --git a/handler/oauth2/flow_client_credentials_test.go b/handler/oauth2/flow_client_credentials_test.go index cf5d4c1a..fe68e915 100644 --- a/handler/oauth2/flow_client_credentials_test.go +++ b/handler/oauth2/flow_client_credentials_test.go @@ -19,11 +19,12 @@ import ( "testing" "time" + "fmt" + "github.com/golang/mock/gomock" "github.com/ory/fosite" "github.com/ory/fosite/internal" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestClientCredentials_HandleTokenEndpointRequest(t *testing.T) { @@ -67,10 +68,15 @@ func TestClientCredentials_HandleTokenEndpointRequest(t *testing.T) { }, }, } { - c.mock() - err := h.HandleTokenEndpointRequest(nil, areq) - assert.True(t, errors.Cause(err) == c.expectErr, "(%d) %s\n%s\n%s", k, c.description, err, c.expectErr) - t.Logf("Passed test case %d", k) + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + c.mock() + err := h.HandleTokenEndpointRequest(nil, areq) + if c.expectErr != nil { + require.EqualError(t, err, c.expectErr.Error()) + } else { + require.NoError(t, err) + } + }) } } @@ -122,9 +128,14 @@ func TestClientCredentials_PopulateTokenEndpointResponse(t *testing.T) { }, }, } { - c.mock() - err := h.PopulateTokenEndpointResponse(nil, areq, aresp) - assert.True(t, errors.Cause(err) == c.expectErr, "(%d) %s\n%s\n%s", k, c.description, err, c.expectErr) - t.Logf("Passed test case %d", k) + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + c.mock() + err := h.PopulateTokenEndpointResponse(nil, areq, aresp) + if c.expectErr != nil { + require.EqualError(t, err, c.expectErr.Error()) + } else { + require.NoError(t, err) + } + }) } } diff --git a/handler/oauth2/flow_resource_owner_test.go b/handler/oauth2/flow_resource_owner_test.go index 614f4056..6df5e3c6 100644 --- a/handler/oauth2/flow_resource_owner_test.go +++ b/handler/oauth2/flow_resource_owner_test.go @@ -19,11 +19,14 @@ import ( "testing" "time" + "fmt" + "github.com/golang/mock/gomock" "github.com/ory/fosite" "github.com/ory/fosite/internal" "github.com/pkg/errors" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestResourceOwnerFlow_HandleTokenEndpointRequest(t *testing.T) { @@ -84,13 +87,19 @@ func TestResourceOwnerFlow_HandleTokenEndpointRequest(t *testing.T) { }, }, } { - c.setup() - err := h.HandleTokenEndpointRequest(nil, areq) - assert.True(t, errors.Cause(err) == c.expectErr, "(%d) %s\n%s\n%s", k, c.description, err, c.expectErr) - t.Logf("Passed test case %d", k) - if c.check != nil { - c.check(areq) - } + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + c.setup() + err := h.HandleTokenEndpointRequest(nil, areq) + + if c.expectErr != nil { + require.EqualError(t, err, c.expectErr.Error()) + } else { + require.NoError(t, err) + if c.check != nil { + c.check(areq) + } + } + }) } } @@ -155,12 +164,17 @@ func TestResourceOwnerFlow_PopulateTokenEndpointResponse(t *testing.T) { }, }, } { - c.setup() - err := h.PopulateTokenEndpointResponse(nil, areq, aresp) - assert.True(t, errors.Cause(err) == c.expectErr, "(%d) %s\n%s\n%s", k, c.description, err, c.expectErr) - if c.expect != nil { - c.expect() - } - t.Logf("Passed test case %d", k) + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + c.setup() + err := h.PopulateTokenEndpointResponse(nil, areq, aresp) + if c.expectErr != nil { + require.EqualError(t, err, c.expectErr.Error()) + } else { + require.NoError(t, err) + if c.expect != nil { + c.expect() + } + } + }) } } diff --git a/handler/oauth2/introspector.go b/handler/oauth2/introspector.go index 7b3a9463..cefd0034 100644 --- a/handler/oauth2/introspector.go +++ b/handler/oauth2/introspector.go @@ -17,9 +17,10 @@ package oauth2 import ( "context" + "fmt" + "github.com/ory/fosite" "github.com/pkg/errors" - "fmt" ) type CoreValidator struct { diff --git a/handler/oauth2/introspector_jwt_test.go b/handler/oauth2/introspector_jwt_test.go index 2bd544e6..0f2ea24a 100644 --- a/handler/oauth2/introspector_jwt_test.go +++ b/handler/oauth2/introspector_jwt_test.go @@ -19,11 +19,13 @@ import ( "strings" "testing" + "fmt" + "github.com/ory/fosite" "github.com/ory/fosite/internal" "github.com/ory/fosite/token/jwt" - "github.com/pkg/errors" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestIntrospectJWT(t *testing.T) { @@ -101,19 +103,21 @@ func TestIntrospectJWT(t *testing.T) { }, }, } { - if c.scopes == nil { - c.scopes = []string{} - } - areq := fosite.NewAccessRequest(nil) - err := v.IntrospectToken(nil, c.token(), fosite.AccessToken, areq, c.scopes) - - assert.True(t, errors.Cause(err) == c.expectErr, "(%d) %s\n%s\n%s", k, c.description, err, c.expectErr) + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + if c.scopes == nil { + c.scopes = []string{} + } - if err == nil { - assert.Equal(t, "peter", areq.Session.GetSubject()) - } + areq := fosite.NewAccessRequest(nil) + err := v.IntrospectToken(nil, c.token(), fosite.AccessToken, areq, c.scopes) - t.Logf("Passed test case %d", k) + if c.expectErr != nil { + require.EqualError(t, err, c.expectErr.Error()) + } else { + require.NoError(t, err) + assert.Equal(t, "peter", areq.Session.GetSubject()) + } + }) } } diff --git a/handler/oauth2/introspector_test.go b/handler/oauth2/introspector_test.go index c3fdd3f6..5d468aab 100644 --- a/handler/oauth2/introspector_test.go +++ b/handler/oauth2/introspector_test.go @@ -15,6 +15,7 @@ package oauth2 import ( + "fmt" "net/http" "testing" @@ -22,7 +23,7 @@ import ( "github.com/ory/fosite" "github.com/ory/fosite/internal" "github.com/pkg/errors" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestIntrospectToken(t *testing.T) { @@ -90,9 +91,15 @@ func TestIntrospectToken(t *testing.T) { }, }, } { - c.setup() - err := v.IntrospectToken(nil, fosite.AccessTokenFromRequest(httpreq), fosite.AccessToken, areq, []string{}) - assert.True(t, errors.Cause(err) == c.expectErr, "(%d) %s\n%s\n%s", k, c.description, err, c.expectErr) - t.Logf("Passed test case %d", k) + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + c.setup() + err := v.IntrospectToken(nil, fosite.AccessTokenFromRequest(httpreq), fosite.AccessToken, areq, []string{}) + + if c.expectErr != nil { + require.EqualError(t, err, c.expectErr.Error()) + } else { + require.NoError(t, err) + } + }) } } diff --git a/handler/oauth2/revocation_test.go b/handler/oauth2/revocation_test.go index ce8ce941..9d6e653d 100644 --- a/handler/oauth2/revocation_test.go +++ b/handler/oauth2/revocation_test.go @@ -17,11 +17,12 @@ package oauth2 import ( "testing" + "fmt" + "github.com/golang/mock/gomock" "github.com/ory/fosite" "github.com/ory/fosite/internal" - "github.com/pkg/errors" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestRevokeToken(t *testing.T) { @@ -154,9 +155,15 @@ func TestRevokeToken(t *testing.T) { }, }, } { - c.mock() - err := h.RevokeToken(nil, token, tokenType, c.client) - assert.True(t, errors.Cause(err) == c.expectErr, "(%d) %s\n%s\n%s", k, c.description, err, c.expectErr) - t.Logf("Passed test case %d", k) + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + c.mock() + err := h.RevokeToken(nil, token, tokenType, c.client) + + if c.expectErr != nil { + require.EqualError(t, err, c.expectErr.Error()) + } else { + require.NoError(t, err) + } + }) } } diff --git a/handler/oauth2/strategy_jwt_test.go b/handler/oauth2/strategy_jwt_test.go index 4c94b9da..7fcaefcd 100644 --- a/handler/oauth2/strategy_jwt_test.go +++ b/handler/oauth2/strategy_jwt_test.go @@ -75,6 +75,7 @@ var jwtExpiredCase = func(tokenType fosite.TokenType) *fosite.Request { Audience: "group0", IssuedAt: time.Now(), NotBefore: time.Now(), + ExpiresAt: time.Now().Add(-time.Minute), Extra: make(map[string]interface{}), }, JWTHeader: &jwt.Headers{ diff --git a/handler/openid/flow_explicit_auth_test.go b/handler/openid/flow_explicit_auth_test.go index 3d3616f2..65733b0b 100644 --- a/handler/openid/flow_explicit_auth_test.go +++ b/handler/openid/flow_explicit_auth_test.go @@ -17,12 +17,14 @@ package openid import ( "testing" + "fmt" + "github.com/golang/mock/gomock" "github.com/ory/fosite" "github.com/ory/fosite/internal" "github.com/ory/fosite/token/jwt" "github.com/pkg/errors" - "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) var j = &DefaultStrategy{ @@ -90,9 +92,15 @@ func TestExplicit_HandleAuthorizeEndpointRequest(t *testing.T) { }, }, } { - c.setup() - err := h.HandleAuthorizeEndpointRequest(nil, areq, aresp) - assert.True(t, errors.Cause(err) == c.expectErr, "(%d) %s\n%s\n%s", k, c.description, err, c.expectErr) - t.Logf("Passed test case %d", k) + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + c.setup() + err := h.HandleAuthorizeEndpointRequest(nil, areq, aresp) + + if c.expectErr != nil { + require.EqualError(t, err, c.expectErr.Error()) + } else { + require.NoError(t, err) + } + }) } } diff --git a/handler/openid/flow_explicit_token.go b/handler/openid/flow_explicit_token.go index 7a6e46b7..9aee4145 100644 --- a/handler/openid/flow_explicit_token.go +++ b/handler/openid/flow_explicit_token.go @@ -22,7 +22,7 @@ import ( ) func (c *OpenIDConnectExplicitHandler) HandleTokenEndpointRequest(ctx context.Context, request fosite.AccessRequester) error { - return fosite.ErrUnknownRequest + return errors.WithStack(fosite.ErrUnknownRequest) } func (c *OpenIDConnectExplicitHandler) PopulateTokenEndpointResponse(ctx context.Context, requester fosite.AccessRequester, responder fosite.AccessResponder) error { diff --git a/handler/openid/flow_explicit_token_test.go b/handler/openid/flow_explicit_token_test.go index 966e86a2..79ad52ed 100644 --- a/handler/openid/flow_explicit_token_test.go +++ b/handler/openid/flow_explicit_token_test.go @@ -17,12 +17,15 @@ package openid import ( "testing" + "fmt" + "github.com/golang/mock/gomock" "github.com/ory/fosite" "github.com/ory/fosite/internal" "github.com/ory/fosite/token/jwt" "github.com/pkg/errors" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestHandleTokenEndpointRequest(t *testing.T) { @@ -31,7 +34,7 @@ func TestHandleTokenEndpointRequest(t *testing.T) { areq.Client = &fosite.DefaultClient{ ResponseTypes: fosite.Arguments{"id_token"}, } - assert.True(t, errors.Cause(h.HandleTokenEndpointRequest(nil, areq)) == fosite.ErrUnknownRequest) + assert.EqualError(t, h.HandleTokenEndpointRequest(nil, areq), fosite.ErrUnknownRequest.Error()) } func TestExplicit_PopulateTokenEndpointResponse(t *testing.T) { @@ -104,9 +107,15 @@ func TestExplicit_PopulateTokenEndpointResponse(t *testing.T) { }, }, } { - c.setup() - err := h.PopulateTokenEndpointResponse(nil, areq, aresp) - assert.True(t, errors.Cause(err) == c.expectErr, "(%d) %s\n%s\n%s", k, c.description, err, c.expectErr) - t.Logf("Passed test case %d", k) + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + c.setup() + err := h.PopulateTokenEndpointResponse(nil, areq, aresp) + + if c.expectErr != nil { + require.EqualError(t, err, c.expectErr.Error()) + } else { + require.NoError(t, err) + } + }) } } diff --git a/handler/openid/flow_hybrid_test.go b/handler/openid/flow_hybrid_test.go index 645b955b..c5350a76 100644 --- a/handler/openid/flow_hybrid_test.go +++ b/handler/openid/flow_hybrid_test.go @@ -18,6 +18,8 @@ import ( "testing" "time" + "fmt" + "github.com/golang/mock/gomock" "github.com/ory/fosite" "github.com/ory/fosite/handler/oauth2" @@ -25,8 +27,8 @@ import ( "github.com/ory/fosite/storage" "github.com/ory/fosite/token/hmac" "github.com/ory/fosite/token/jwt" - "github.com/pkg/errors" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) var idStrategy = &DefaultStrategy{ @@ -166,18 +168,19 @@ func TestHybrid_HandleAuthorizeEndpointRequest(t *testing.T) { }, }, } { - c.setup() - err := h.HandleAuthorizeEndpointRequest(nil, areq, aresp) - condition := errors.Cause(err) == c.expectErr - assert.True(t, condition, "(%d) %s\n%s\n%s", k, c.description, err, c.expectErr) - if condition { - t.Logf("Passed test case %d", k) - } else { - t.Logf("Failed test case %d", k) - } + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + c.setup() + err := h.HandleAuthorizeEndpointRequest(nil, areq, aresp) + + if c.expectErr != nil { + require.EqualError(t, err, c.expectErr.Error()) + } else { + require.NoError(t, err) + } - if c.check != nil { - c.check() - } + if c.check != nil { + c.check() + } + }) } } diff --git a/handler/openid/flow_implicit_test.go b/handler/openid/flow_implicit_test.go index 739c912b..0395185f 100644 --- a/handler/openid/flow_implicit_test.go +++ b/handler/openid/flow_implicit_test.go @@ -18,12 +18,13 @@ import ( "testing" "time" + "fmt" + "github.com/golang/mock/gomock" "github.com/ory/fosite" "github.com/ory/fosite/handler/oauth2" "github.com/ory/fosite/storage" "github.com/ory/fosite/token/jwt" - "github.com/pkg/errors" "github.com/stretchr/testify/assert" ) @@ -162,12 +163,18 @@ func TestImplicit_HandleAuthorizeEndpointRequest(t *testing.T) { }, }, } { - c.setup() - err := h.HandleAuthorizeEndpointRequest(nil, areq, aresp) - assert.True(t, errors.Cause(err) == c.expectErr, "(%d) %s\n%s\n%s", k, c.description, err, c.expectErr) - t.Logf("Passed test case %d", k) - if c.check != nil { - c.check() - } + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + c.setup() + err := h.HandleAuthorizeEndpointRequest(nil, areq, aresp) + + if c.expectErr != nil { + assert.EqualError(t, err, c.expectErr.Error()) + } else { + assert.NoError(t, err) + if c.check != nil { + c.check() + } + } + }) } } diff --git a/integration/revoke_token_test.go b/integration/revoke_token_test.go index b7e4692a..3b7eb89a 100644 --- a/integration/revoke_token_test.go +++ b/integration/revoke_token_test.go @@ -43,20 +43,20 @@ func runRevokeTokenTest(t *testing.T, strategy oauth2.AccessTokenStrategy) { oauthClient := newOAuth2AppClient(ts) token, err := oauthClient.Token(goauth.NoContext) - assert.NoError(t, err) + require.NoError(t, err) resp, _, errs := gorequest.New().Post(ts.URL+"/revoke"). SetBasicAuth(oauthClient.ClientID, oauthClient.ClientSecret). Type("form"). SendStruct(map[string]string{"token": "asdf"}).End() - assert.Len(t, errs, 0) + require.Len(t, errs, 0) assert.Equal(t, 200, resp.StatusCode) resp, _, errs = gorequest.New().Post(ts.URL+"/revoke"). SetBasicAuth(oauthClient.ClientID, oauthClient.ClientSecret). Type("form"). SendStruct(map[string]string{"token": token.AccessToken}).End() - assert.Len(t, errs, 0) + require.Len(t, errs, 0) assert.Equal(t, 200, resp.StatusCode) hres, _, errs := gorequest.New().Get(ts.URL+"/info"). diff --git a/introspect.go b/introspect.go index 440a78fb..97cbac8f 100644 --- a/introspect.go +++ b/introspect.go @@ -52,13 +52,13 @@ func (f *Fosite) IntrospectToken(ctx context.Context, token string, tokenType To ar := NewAccessRequest(session) for _, validator := range f.TokenIntrospectionHandlers { - if err := errors.Cause(validator.IntrospectToken(ctx, token, tokenType, ar, scopes)); err == ErrUnknownRequest { + if err := errors.Cause(validator.IntrospectToken(ctx, token, tokenType, ar, scopes)); err == nil { + found = true + } else if err.Error() == ErrUnknownRequest.Error() { // Nothing to do } else if err != nil { rfcerr := ErrorToRFC6749Error(err) return nil, errors.WithStack(rfcerr.WithDebug("A validator returned an error")) - } else { - found = true } } diff --git a/introspect_test.go b/introspect_test.go index ce2e2651..d4abec50 100644 --- a/introspect_test.go +++ b/introspect_test.go @@ -20,13 +20,15 @@ import ( "context" + "fmt" + "github.com/golang/mock/gomock" . "github.com/ory/fosite" "github.com/ory/fosite/compose" "github.com/ory/fosite/internal" "github.com/ory/fosite/storage" - "github.com/pkg/errors" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestAccessTokenFromRequestNoToken(t *testing.T) { @@ -110,9 +112,14 @@ func TestIntrospect(t *testing.T) { }, }, } { - c.setup() - _, err := f.IntrospectToken(nil, AccessTokenFromRequest(req), AccessToken, nil, c.scopes...) - assert.True(t, errors.Cause(err) == c.expectErr, "(%d) %s\n%s\n%s", k, c.description, err, c.expectErr) - t.Logf("Passed test case %d", k) + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + c.setup() + _, err := f.IntrospectToken(nil, AccessTokenFromRequest(req), AccessToken, nil, c.scopes...) + if c.expectErr != nil { + assert.EqualError(t, err, c.expectErr.Error()) + } else { + require.NoError(t, err) + } + }) } } diff --git a/introspection_request_handler_test.go b/introspection_request_handler_test.go index 7ffe889d..6bb8e5b6 100644 --- a/introspection_request_handler_test.go +++ b/introspection_request_handler_test.go @@ -19,6 +19,8 @@ import ( "net/url" "testing" + "fmt" + "github.com/golang/mock/gomock" "github.com/ory/fosite" . "github.com/ory/fosite" @@ -27,6 +29,7 @@ import ( "github.com/ory/fosite/storage" "github.com/pkg/errors" "github.com/stretchr/testify/assert" + "github.com/stretchr/testify/require" ) func TestIntrospectionResponse(t *testing.T) { @@ -102,12 +105,16 @@ func TestNewIntrospectionRequest(t *testing.T) { isActive: true, }, } { - c.setup() - res, err := f.NewIntrospectionRequest(nil, httpreq, &DefaultSession{}) - assert.True(t, errors.Cause(err) == c.expectErr, "(%d) %s\n%s\n%s", k, c.description, err, c.expectErr) - if res != nil { - assert.Equal(t, c.isActive, res.IsActive()) - } - t.Logf("Passed test case %d", k) + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + c.setup() + res, err := f.NewIntrospectionRequest(nil, httpreq, &DefaultSession{}) + + if c.expectErr != nil { + assert.EqualError(t, err, c.expectErr.Error()) + } else { + require.NoError(t, err) + assert.Equal(t, c.isActive, res.IsActive()) + } + }) } } diff --git a/revoke_handler.go b/revoke_handler.go index 0bf51ddc..6f5dc55f 100644 --- a/revoke_handler.go +++ b/revoke_handler.go @@ -72,7 +72,7 @@ func (f *Fosite) NewRevocationRequest(ctx context.Context, r *http.Request) erro for _, loader := range f.RevocationHandlers { if err := loader.RevokeToken(ctx, token, tokenTypeHint, client); err == nil { found = true - } else if errors.Cause(err) == ErrUnknownRequest { + } else if errors.Cause(err).Error() == ErrUnknownRequest.Error() { // do nothing } else if err != nil { return err @@ -98,10 +98,15 @@ func (f *Fosite) NewRevocationRequest(ctx context.Context, r *http.Request) erro // purpose of the revocation request, invalidating the particular token, // is already achieved. func (f *Fosite) WriteRevocationResponse(rw http.ResponseWriter, err error) { - switch errors.Cause(err) { - case ErrInvalidRequest: + if err == nil { + rw.WriteHeader(http.StatusOK) + return + } + + switch errors.Cause(err).Error() { + case ErrInvalidRequest.Error(): fallthrough - case ErrInvalidClient: + case ErrInvalidClient.Error(): rw.Header().Set("Content-Type", "application/json;charset=UTF-8") js, err := json.Marshal(ErrInvalidClient) diff --git a/revoke_handler_test.go b/revoke_handler_test.go index 697366b4..13fd1e52 100644 --- a/revoke_handler_test.go +++ b/revoke_handler_test.go @@ -19,6 +19,8 @@ import ( "net/url" "testing" + "fmt" + "github.com/golang/mock/gomock" . "github.com/ory/fosite" "github.com/ory/fosite/internal" @@ -187,20 +189,23 @@ func TestNewRevocationRequest(t *testing.T) { handlers: RevocationHandlers{handler}, }, } { - r := &http.Request{ - Header: c.header, - PostForm: c.form, - Form: c.form, - Method: c.method, - } - c.mock() - ctx := NewContext() - fosite.RevocationHandlers = c.handlers - err := fosite.NewRevocationRequest(ctx, r) - assert.True(t, errors.Cause(err) == c.expectErr, "%d\nwant: %s \ngot: %s", k, c.expectErr, err) - if err != nil { - t.Logf("Error occured: %v", err) - } - t.Logf("Passed test case %d", k) + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + r := &http.Request{ + Header: c.header, + PostForm: c.form, + Form: c.form, + Method: c.method, + } + c.mock() + ctx := NewContext() + fosite.RevocationHandlers = c.handlers + err := fosite.NewRevocationRequest(ctx, r) + + if c.expectErr != nil { + assert.EqualError(t, err, c.expectErr.Error()) + } else { + assert.NoError(t, err) + } + }) } } diff --git a/token/jwt/jwt.go b/token/jwt/jwt.go index 0175facc..1399ebc2 100644 --- a/token/jwt/jwt.go +++ b/token/jwt/jwt.go @@ -74,7 +74,7 @@ func (j *RS256JWTStrategy) Decode(token string) (*jwt.Token, error) { }) if err != nil { - return nil, errors.WithStack(fosite.ErrorToRFC6749Error(err).WithDebug("Couldn't parse token")) + return nil, errors.WithStack(err) } else if !parsedToken.Valid { return nil, errors.WithStack(fosite.ErrInactiveToken) } From 9fc25a86c4d8609aafa382e5eab32d3d087ec9d8 Mon Sep 17 00:00:00 2001 From: arekkas Date: Sat, 9 Dec 2017 22:59:45 +0100 Subject: [PATCH 24/35] docs: Updates history.md --- HISTORY.md | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/HISTORY.md b/HISTORY.md index 8400a420..b5609700 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -35,6 +35,20 @@ bumps (`0.1.0` -> `0.2.0`). +## 0.14.0 + +This release focuses on improving compatibility with OpenID Connect Certification and better error context. + +* Error handling is improved by explicitly adding debug information (e.g. "Token invalid because it was not found +in the database") to the error object. Previously, the original error was prepended which caused weird formatting issues. +* Allows client credentials in POST body at the `/oauth2/token` endpoint. Please note that this method is not recommended +to be used, unless the client making the request is unable to use HTTP Basic Authorization. +* Allows public clients (without secret) to access the `/oauth2/token` endpoint which was previously only possible by adding an arbitrary +secret. + +This release has no breaking changes to the external API but due to the nature of the changes, it is released +as a new major version. + ## 0.13.0 ### Breaking changes From 831f56a9e6774b1e80c13cd301583edea6378245 Mon Sep 17 00:00:00 2001 From: arekkas Date: Sat, 9 Dec 2017 23:02:06 +0100 Subject: [PATCH 25/35] Improves test coverage report by removing internal package from it --- .travis.yml | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/.travis.yml b/.travis.yml index 30d55f32..a9563467 100644 --- a/.travis.yml +++ b/.travis.yml @@ -14,9 +14,12 @@ before_install: install: - dep ensure - - go get github.com/mattn/goveralls golang.org/x/tools/cmd/cover github.com/pierrre/gotestcover github.com/ory/go-acc github.com/bradfitz/goimports + - go get github.com/mattn/goveralls golang.org/x/tools/cmd/cover github.com/pierrre/gotestcover github.com/bradfitz/goimports script: - - ./scripts/test-format.sh - - go-acc -o coverage.txt ./... - - goveralls -coverprofile="coverage.txt" + - touch ./coverage.tmp + - | + echo 'mode: atomic' > coverage.txt + - | + go list ./... | grep -v /vendor | grep -v /internal | xargs -n1 -I{} sh -c 'go test -race -covermode=atomic -coverprofile=coverage.tmp -coverpkg $(go list ./... | grep -v /vendor | grep -v /internal | tr "\n" ",") {} && tail -n +2 coverage.tmp >> coverage.txt || exit 255' && rm coverage.tmp + - goveralls -coverprofile="coverage.txt" \ No newline at end of file From 87c37c3d6929b1edd2ab52a28d51ed1890628f51 Mon Sep 17 00:00:00 2001 From: arekkas Date: Sat, 9 Dec 2017 23:07:19 +0100 Subject: [PATCH 26/35] Upgrades history.md --- HISTORY.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index b5609700..e7f9c1dc 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -5,8 +5,12 @@ bumps (`0.1.0` -> `0.2.0`). -- [0.12.0](#0120) +- [0.15.0](#0150) +- [0.14.0](#0140) +- [0.13.0](#0130) - [Breaking changes](#breaking-changes) +- [0.12.0](#0120) + - [Breaking changes](#breaking-changes-1) - [Improved cryptographic methods](#improved-cryptographic-methods) - [0.11.0](#0110) - [Non-breaking changes](#non-breaking-changes) @@ -22,7 +26,7 @@ bumps (`0.1.0` -> `0.2.0`). - [0.10.0](#0100) - [0.9.0](#090) - [0.8.0](#080) - - [Breaking changes](#breaking-changes-1) + - [Breaking changes](#breaking-changes-2) - [`ClientManager`](#clientmanager) - [`OAuth2Provider`](#oauth2provider) - [0.7.0](#070) @@ -35,7 +39,7 @@ bumps (`0.1.0` -> `0.2.0`). -## 0.14.0 +## 0.15.0 This release focuses on improving compatibility with OpenID Connect Certification and better error context. @@ -49,6 +53,10 @@ secret. This release has no breaking changes to the external API but due to the nature of the changes, it is released as a new major version. +## 0.14.0 + +Improves error contexts. A breaking code changes to the public API was reverted with 0.14.1. + ## 0.13.0 ### Breaking changes From b87ca49b9418b99f492077f8ba78bf00e6c29180 Mon Sep 17 00:00:00 2001 From: arekkas Date: Sun, 10 Dec 2017 16:35:15 +0100 Subject: [PATCH 27/35] token/jwt: Adds ability to specify acr value natively in id token payload --- token/jwt/claims_id_token.go | 25 +++++++++++++++---------- token/jwt/claims_id_token_test.go | 2 ++ 2 files changed, 17 insertions(+), 10 deletions(-) diff --git a/token/jwt/claims_id_token.go b/token/jwt/claims_id_token.go index 0ccb2254..d9d5649a 100644 --- a/token/jwt/claims_id_token.go +++ b/token/jwt/claims_id_token.go @@ -22,16 +22,17 @@ import ( // IDTokenClaims represent the claims used in open id connect requests type IDTokenClaims struct { - Issuer string - Subject string - Audience string - Nonce string - ExpiresAt time.Time - IssuedAt time.Time - AuthTime time.Time - AccessTokenHash string - CodeHash string - Extra map[string]interface{} + Issuer string + Subject string + Audience string + Nonce string + ExpiresAt time.Time + IssuedAt time.Time + AuthTime time.Time + AccessTokenHash string + AuthenticationContextClassReference string + CodeHash string + Extra map[string]interface{} } // ToMap will transform the headers to a map structure @@ -54,6 +55,10 @@ func (c *IDTokenClaims) ToMap() map[string]interface{} { ret["auth_time"] = c.AuthTime.Unix() } + if len(c.AuthenticationContextClassReference) > 0 { + ret["acr"] = c.AuthenticationContextClassReference + } + ret["iat"] = float64(c.IssuedAt.Unix()) ret["exp"] = float64(c.ExpiresAt.Unix()) return ret diff --git a/token/jwt/claims_id_token_test.go b/token/jwt/claims_id_token_test.go index 8d796949..ee235327 100644 --- a/token/jwt/claims_id_token_test.go +++ b/token/jwt/claims_id_token_test.go @@ -31,6 +31,7 @@ var idTokenClaims = &IDTokenClaims{ AuthTime: time.Now(), AccessTokenHash: "foobar", CodeHash: "barfoo", + AuthenticationContextClassReference: "acr", Extra: map[string]interface{}{ "foo": "bar", "baz": "bar", @@ -57,5 +58,6 @@ func TestIDTokenClaimsToMap(t *testing.T) { "at_hash": idTokenClaims.AccessTokenHash, "c_hash": idTokenClaims.CodeHash, "auth_time": idTokenClaims.AuthTime.Unix(), + "acr": idTokenClaims.AuthenticationContextClassReference, }, idTokenClaims.ToMap()) } From 4c7e4e5512061e9add22cc246882c78d2b06599c Mon Sep 17 00:00:00 2001 From: arekkas Date: Sun, 10 Dec 2017 17:51:08 +0100 Subject: [PATCH 28/35] Forces use of UTC time zone everywhere --- authorize_request_test.go | 2 +- handler/oauth2/flow_authorize_code_auth.go | 2 +- .../oauth2/flow_authorize_code_auth_test.go | 4 ++-- handler/oauth2/flow_authorize_code_token.go | 4 ++-- .../oauth2/flow_authorize_code_token_test.go | 20 +++++++++---------- handler/oauth2/flow_authorize_implicit.go | 4 ++-- handler/oauth2/flow_client_credentials.go | 2 +- handler/oauth2/flow_refresh.go | 4 ++-- handler/oauth2/flow_refresh_test.go | 4 ++-- handler/oauth2/flow_resource_owner.go | 2 +- handler/oauth2/helper.go | 2 +- handler/oauth2/helper_test.go | 2 +- handler/oauth2/strategy_hmacsha.go | 8 ++++---- handler/oauth2/strategy_hmacsha_test.go | 8 ++++---- handler/oauth2/strategy_jwt.go | 2 +- handler/oauth2/strategy_jwt_test.go | 14 ++++++------- handler/openid/strategy_jwt.go | 10 +++++----- handler/openid/strategy_jwt_test.go | 4 ++-- integration/authorize_implicit_grant_test.go | 2 +- integration/oidc_implicit_hybrid_test.go | 2 +- request.go | 2 +- request_test.go | 6 +++--- session.go | 2 +- token/jwt/claims.go | 4 ++-- token/jwt/claims_id_token_test.go | 10 +++++----- token/jwt/claims_jwt.go | 12 +++++------ token/jwt/claims_jwt_test.go | 18 ++++++++--------- token/jwt/claims_test.go | 2 +- token/jwt/jwt_test.go | 6 +++--- 29 files changed, 82 insertions(+), 82 deletions(-) diff --git a/authorize_request_test.go b/authorize_request_test.go index 95ce4895..c848c0f8 100644 --- a/authorize_request_test.go +++ b/authorize_request_test.go @@ -91,7 +91,7 @@ func TestAuthorizeRequest(t *testing.T) { ar: &AuthorizeRequest{ Request: Request{ Client: &DefaultClient{RedirectURIs: []string{"https://foobar.com/cb"}}, - RequestedAt: time.Now(), + RequestedAt: time.Now().UTC(), Scopes: []string{"foo", "bar"}, }, RedirectURI: urlparse("https://foobar.com/cb"), diff --git a/handler/oauth2/flow_authorize_code_auth.go b/handler/oauth2/flow_authorize_code_auth.go index 837eee36..1be33bbe 100644 --- a/handler/oauth2/flow_authorize_code_auth.go +++ b/handler/oauth2/flow_authorize_code_auth.go @@ -74,7 +74,7 @@ func (c *AuthorizeExplicitGrantHandler) IssueAuthorizeCode(ctx context.Context, return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } - ar.GetSession().SetExpiresAt(fosite.AuthorizeCode, time.Now().Add(c.AuthCodeLifespan)) + ar.GetSession().SetExpiresAt(fosite.AuthorizeCode, time.Now().UTC().Add(c.AuthCodeLifespan)) if err := c.CoreStorage.CreateAuthorizeCodeSession(ctx, signature, ar); err != nil { return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } diff --git a/handler/oauth2/flow_authorize_code_auth_test.go b/handler/oauth2/flow_authorize_code_auth_test.go index fea442a0..1cf95bae 100644 --- a/handler/oauth2/flow_authorize_code_auth_test.go +++ b/handler/oauth2/flow_authorize_code_auth_test.go @@ -88,9 +88,9 @@ func TestAuthorizeCode_HandleAuthorizeEndpointRequest(t *testing.T) { }, GrantedScopes: fosite.Arguments{"a", "b"}, Session: &fosite.DefaultSession{ - ExpiresAt: map[fosite.TokenType]time.Time{fosite.AccessToken: time.Now().Add(time.Hour)}, + ExpiresAt: map[fosite.TokenType]time.Time{fosite.AccessToken: time.Now().UTC().Add(time.Hour)}, }, - RequestedAt: time.Now(), + RequestedAt: time.Now().UTC(), }, State: "superstate", RedirectURI: parseUrl("https://asdf.de/cb"), diff --git a/handler/oauth2/flow_authorize_code_token.go b/handler/oauth2/flow_authorize_code_token.go index d5096a0b..05537f5e 100644 --- a/handler/oauth2/flow_authorize_code_token.go +++ b/handler/oauth2/flow_authorize_code_token.go @@ -87,7 +87,7 @@ func (c *AuthorizeExplicitGrantHandler) HandleTokenEndpointRequest(ctx context.C // client MUST authenticate with the authorization server as described // in Section 3.2.1. request.SetSession(authorizeRequest.GetSession()) - request.GetSession().SetExpiresAt(fosite.AccessToken, time.Now().Add(c.AccessTokenLifespan)) + request.GetSession().SetExpiresAt(fosite.AccessToken, time.Now().UTC().Add(c.AccessTokenLifespan)) request.SetID(authorizeRequest.GetID()) return nil } @@ -138,7 +138,7 @@ func (c *AuthorizeExplicitGrantHandler) PopulateTokenEndpointResponse(ctx contex responder.SetAccessToken(access) responder.SetTokenType("bearer") - responder.SetExpiresIn(getExpiresIn(requester, fosite.AccessToken, c.AccessTokenLifespan, time.Now())) + responder.SetExpiresIn(getExpiresIn(requester, fosite.AccessToken, c.AccessTokenLifespan, time.Now().UTC())) responder.SetScopes(requester.GetGrantedScopes()) if refresh != "" { responder.SetExtra("refresh_token", refresh) diff --git a/handler/oauth2/flow_authorize_code_token_test.go b/handler/oauth2/flow_authorize_code_token_test.go index 05f9eeb8..6524ab15 100644 --- a/handler/oauth2/flow_authorize_code_token_test.go +++ b/handler/oauth2/flow_authorize_code_token_test.go @@ -73,7 +73,7 @@ func TestAuthorizeCode_PopulateTokenEndpointResponse(t *testing.T) { GrantTypes: fosite.Arguments{"authorization_code"}, }, Session: &fosite.DefaultSession{}, - RequestedAt: time.Now(), + RequestedAt: time.Now().UTC(), }, }, description: "should fail because authcode not found", @@ -93,7 +93,7 @@ func TestAuthorizeCode_PopulateTokenEndpointResponse(t *testing.T) { GrantTypes: fosite.Arguments{"authorization_code"}, }, Session: &fosite.DefaultSession{}, - RequestedAt: time.Now(), + RequestedAt: time.Now().UTC(), }, }, description: "should fail because validation failed", @@ -112,7 +112,7 @@ func TestAuthorizeCode_PopulateTokenEndpointResponse(t *testing.T) { }, GrantedScopes: fosite.Arguments{"foo", "offline"}, Session: &fosite.DefaultSession{}, - RequestedAt: time.Now(), + RequestedAt: time.Now().UTC(), }, }, setup: func(t *testing.T, areq *fosite.AccessRequest) { @@ -190,7 +190,7 @@ func TestAuthorizeCode_HandleTokenEndpointRequest(t *testing.T) { Request: fosite.Request{ Client: &fosite.DefaultClient{ID: "foo", GrantTypes: []string{""}}, Session: &fosite.DefaultSession{}, - RequestedAt: time.Now(), + RequestedAt: time.Now().UTC(), }, }, description: "should fail because client is not granted this grant type", @@ -202,7 +202,7 @@ func TestAuthorizeCode_HandleTokenEndpointRequest(t *testing.T) { Request: fosite.Request{ Client: &fosite.DefaultClient{GrantTypes: []string{"authorization_code"}}, Session: &fosite.DefaultSession{}, - RequestedAt: time.Now(), + RequestedAt: time.Now().UTC(), }, }, description: "should fail because authcode could not be retrieved (1)", @@ -220,7 +220,7 @@ func TestAuthorizeCode_HandleTokenEndpointRequest(t *testing.T) { Form: url.Values{"code": {"foo.bar"}}, Client: &fosite.DefaultClient{GrantTypes: []string{"authorization_code"}}, Session: &fosite.DefaultSession{}, - RequestedAt: time.Now(), + RequestedAt: time.Now().UTC(), }, }, description: "should fail because authcode validation failed", @@ -232,7 +232,7 @@ func TestAuthorizeCode_HandleTokenEndpointRequest(t *testing.T) { Request: fosite.Request{ Client: &fosite.DefaultClient{ID: "foo", GrantTypes: []string{"authorization_code"}}, Session: &fosite.DefaultSession{}, - RequestedAt: time.Now(), + RequestedAt: time.Now().UTC(), }, }, authreq: &fosite.AuthorizeRequest{ @@ -257,7 +257,7 @@ func TestAuthorizeCode_HandleTokenEndpointRequest(t *testing.T) { Request: fosite.Request{ Client: &fosite.DefaultClient{ID: "foo", GrantTypes: []string{"authorization_code"}}, Session: &fosite.DefaultSession{}, - RequestedAt: time.Now(), + RequestedAt: time.Now().UTC(), }, }, authreq: &fosite.AuthorizeRequest{ @@ -284,7 +284,7 @@ func TestAuthorizeCode_HandleTokenEndpointRequest(t *testing.T) { Client: &fosite.DefaultClient{ID: "foo", GrantTypes: []string{"authorization_code"}}, Form: url.Values{"redirect_uri": []string{"request-redir"}}, Session: &fosite.DefaultSession{}, - RequestedAt: time.Now(), + RequestedAt: time.Now().UTC(), }, }, authreq: &fosite.AuthorizeRequest{ @@ -292,7 +292,7 @@ func TestAuthorizeCode_HandleTokenEndpointRequest(t *testing.T) { Client: &fosite.DefaultClient{ID: "foo", GrantTypes: []string{"authorization_code"}}, Session: &fosite.DefaultSession{}, Scopes: fosite.Arguments{"a", "b"}, - RequestedAt: time.Now(), + RequestedAt: time.Now().UTC(), }, }, description: "should pass", diff --git a/handler/oauth2/flow_authorize_implicit.go b/handler/oauth2/flow_authorize_implicit.go index f9d5fda7..38f884d5 100644 --- a/handler/oauth2/flow_authorize_implicit.go +++ b/handler/oauth2/flow_authorize_implicit.go @@ -69,7 +69,7 @@ func (c *AuthorizeImplicitGrantTypeHandler) HandleAuthorizeEndpointRequest(ctx c } func (c *AuthorizeImplicitGrantTypeHandler) IssueImplicitAccessToken(ctx context.Context, ar fosite.AuthorizeRequester, resp fosite.AuthorizeResponder) error { - ar.GetSession().SetExpiresAt(fosite.AccessToken, time.Now().Add(c.AccessTokenLifespan)) + ar.GetSession().SetExpiresAt(fosite.AccessToken, time.Now().UTC().Add(c.AccessTokenLifespan)) // Generate the code token, signature, err := c.AccessTokenStrategy.GenerateAccessToken(ctx, ar) @@ -82,7 +82,7 @@ func (c *AuthorizeImplicitGrantTypeHandler) IssueImplicitAccessToken(ctx context } resp.AddFragment("access_token", token) - resp.AddFragment("expires_in", strconv.FormatInt(int64(getExpiresIn(ar, fosite.AccessToken, c.AccessTokenLifespan, time.Now())/time.Second), 10)) + resp.AddFragment("expires_in", strconv.FormatInt(int64(getExpiresIn(ar, fosite.AccessToken, c.AccessTokenLifespan, time.Now().UTC())/time.Second), 10)) resp.AddFragment("token_type", "bearer") resp.AddFragment("state", ar.GetState()) resp.AddFragment("scope", strings.Join(ar.GetGrantedScopes(), " ")) diff --git a/handler/oauth2/flow_client_credentials.go b/handler/oauth2/flow_client_credentials.go index 141ea87b..43d72496 100644 --- a/handler/oauth2/flow_client_credentials.go +++ b/handler/oauth2/flow_client_credentials.go @@ -52,7 +52,7 @@ func (c *ClientCredentialsGrantHandler) HandleTokenEndpointRequest(_ context.Con } // if the client is not public, he has already been authenticated by the access request handler. - request.GetSession().SetExpiresAt(fosite.AccessToken, time.Now().Add(c.AccessTokenLifespan)) + request.GetSession().SetExpiresAt(fosite.AccessToken, time.Now().UTC().Add(c.AccessTokenLifespan)) return nil } diff --git a/handler/oauth2/flow_refresh.go b/handler/oauth2/flow_refresh.go index 234c9410..276fa328 100644 --- a/handler/oauth2/flow_refresh.go +++ b/handler/oauth2/flow_refresh.go @@ -73,7 +73,7 @@ func (c *RefreshTokenGrantHandler) HandleTokenEndpointRequest(ctx context.Contex request.GrantScope(scope) } - request.GetSession().SetExpiresAt(fosite.AccessToken, time.Now().Add(c.AccessTokenLifespan)) + request.GetSession().SetExpiresAt(fosite.AccessToken, time.Now().UTC().Add(c.AccessTokenLifespan)) return nil } @@ -108,7 +108,7 @@ func (c *RefreshTokenGrantHandler) PopulateTokenEndpointResponse(ctx context.Con responder.SetAccessToken(accessToken) responder.SetTokenType("bearer") - responder.SetExpiresIn(getExpiresIn(requester, fosite.AccessToken, c.AccessTokenLifespan, time.Now())) + responder.SetExpiresIn(getExpiresIn(requester, fosite.AccessToken, c.AccessTokenLifespan, time.Now().UTC())) responder.SetScopes(requester.GetGrantedScopes()) responder.SetExtra("refresh_token", refreshToken) return nil diff --git a/handler/oauth2/flow_refresh_test.go b/handler/oauth2/flow_refresh_test.go index eca6d3a8..4e0fa701 100644 --- a/handler/oauth2/flow_refresh_test.go +++ b/handler/oauth2/flow_refresh_test.go @@ -117,13 +117,13 @@ func TestRefreshFlow_HandleTokenEndpointRequest(t *testing.T) { Scopes: fosite.Arguments{"foo", "bar"}, Session: sess, Form: url.Values{"foo": []string{"bar"}}, - RequestedAt: time.Now().Add(-time.Hour).Round(time.Hour), + RequestedAt: time.Now().UTC().Add(-time.Hour).Round(time.Hour), }) require.NoError(t, err) }, expect: func(t *testing.T) { assert.NotEqual(t, sess, areq.Session) - assert.NotEqual(t, time.Now().Add(-time.Hour).Round(time.Hour), areq.RequestedAt) + assert.NotEqual(t, time.Now().UTC().Add(-time.Hour).Round(time.Hour), areq.RequestedAt) assert.Equal(t, fosite.Arguments{"foo", "offline"}, areq.GrantedScopes) assert.Equal(t, fosite.Arguments{"foo", "bar"}, areq.Scopes) assert.NotEqual(t, url.Values{"foo": []string{"bar"}}, areq.Form) diff --git a/handler/oauth2/flow_resource_owner.go b/handler/oauth2/flow_resource_owner.go index 4847ac2a..86f892b7 100644 --- a/handler/oauth2/flow_resource_owner.go +++ b/handler/oauth2/flow_resource_owner.go @@ -66,7 +66,7 @@ func (c *ResourceOwnerPasswordCredentialsGrantHandler) HandleTokenEndpointReques // Credentials must not be passed around, potentially leaking to the database! delete(request.GetRequestForm(), "password") - request.GetSession().SetExpiresAt(fosite.AccessToken, time.Now().Add(c.AccessTokenLifespan)) + request.GetSession().SetExpiresAt(fosite.AccessToken, time.Now().UTC().Add(c.AccessTokenLifespan)) return nil } diff --git a/handler/oauth2/helper.go b/handler/oauth2/helper.go index 73cc8a26..85af6162 100644 --- a/handler/oauth2/helper.go +++ b/handler/oauth2/helper.go @@ -38,7 +38,7 @@ func (h *HandleHelper) IssueAccessToken(ctx context.Context, requester fosite.Ac responder.SetAccessToken(token) responder.SetTokenType("bearer") - responder.SetExpiresIn(getExpiresIn(requester, fosite.AccessToken, h.AccessTokenLifespan, time.Now())) + responder.SetExpiresIn(getExpiresIn(requester, fosite.AccessToken, h.AccessTokenLifespan, time.Now().UTC())) responder.SetScopes(requester.GetGrantedScopes()) return nil } diff --git a/handler/oauth2/helper_test.go b/handler/oauth2/helper_test.go index d59ae375..e3771287 100644 --- a/handler/oauth2/helper_test.go +++ b/handler/oauth2/helper_test.go @@ -27,7 +27,7 @@ import ( ) func TestGetExpiresIn(t *testing.T) { - now := time.Now() + now := time.Now().UTC() r := fosite.NewAccessRequest(&fosite.DefaultSession{ ExpiresAt: map[fosite.TokenType]time.Time{ fosite.AccessToken: now.Add(time.Hour), diff --git a/handler/oauth2/strategy_hmacsha.go b/handler/oauth2/strategy_hmacsha.go index 720a6528..1898d5cb 100644 --- a/handler/oauth2/strategy_hmacsha.go +++ b/handler/oauth2/strategy_hmacsha.go @@ -47,10 +47,10 @@ func (h HMACSHAStrategy) GenerateAccessToken(_ context.Context, _ fosite.Request func (h HMACSHAStrategy) ValidateAccessToken(_ context.Context, r fosite.Requester, token string) (err error) { var exp = r.GetSession().GetExpiresAt(fosite.AccessToken) - if exp.IsZero() && r.GetRequestedAt().Add(h.AccessTokenLifespan).Before(time.Now()) { + if exp.IsZero() && r.GetRequestedAt().Add(h.AccessTokenLifespan).Before(time.Now().UTC()) { return errors.WithStack(fosite.ErrTokenExpired.WithDebug(fmt.Sprintf("Access token expired at %s", r.GetRequestedAt().Add(h.AccessTokenLifespan)))) } - if !exp.IsZero() && exp.Before(time.Now()) { + if !exp.IsZero() && exp.Before(time.Now().UTC()) { return errors.WithStack(fosite.ErrTokenExpired.WithDebug(fmt.Sprintf("Access token expired at %s", exp))) } return h.Enigma.Validate(token) @@ -70,10 +70,10 @@ func (h HMACSHAStrategy) GenerateAuthorizeCode(_ context.Context, _ fosite.Reque func (h HMACSHAStrategy) ValidateAuthorizeCode(_ context.Context, r fosite.Requester, token string) (err error) { var exp = r.GetSession().GetExpiresAt(fosite.AuthorizeCode) - if exp.IsZero() && r.GetRequestedAt().Add(h.AuthorizeCodeLifespan).Before(time.Now()) { + if exp.IsZero() && r.GetRequestedAt().Add(h.AuthorizeCodeLifespan).Before(time.Now().UTC()) { return errors.WithStack(fosite.ErrTokenExpired.WithDebug(fmt.Sprintf("Authorize code expired at %s", r.GetRequestedAt().Add(h.AuthorizeCodeLifespan)))) } - if !exp.IsZero() && exp.Before(time.Now()) { + if !exp.IsZero() && exp.Before(time.Now().UTC()) { return errors.WithStack(fosite.ErrTokenExpired.WithDebug(fmt.Sprintf("Authorize code expired at %s", exp))) } diff --git a/handler/oauth2/strategy_hmacsha_test.go b/handler/oauth2/strategy_hmacsha_test.go index 3119f63a..5856919a 100644 --- a/handler/oauth2/strategy_hmacsha_test.go +++ b/handler/oauth2/strategy_hmacsha_test.go @@ -38,8 +38,8 @@ var hmacExpiredCase = fosite.Request{ }, Session: &fosite.DefaultSession{ ExpiresAt: map[fosite.TokenType]time.Time{ - fosite.AccessToken: time.Now().Add(-time.Hour), - fosite.AuthorizeCode: time.Now().Add(-time.Hour), + fosite.AccessToken: time.Now().UTC().Add(-time.Hour), + fosite.AuthorizeCode: time.Now().UTC().Add(-time.Hour), }, }, } @@ -50,8 +50,8 @@ var hmacValidCase = fosite.Request{ }, Session: &fosite.DefaultSession{ ExpiresAt: map[fosite.TokenType]time.Time{ - fosite.AccessToken: time.Now().Add(time.Hour), - fosite.AuthorizeCode: time.Now().Add(time.Hour), + fosite.AccessToken: time.Now().UTC().Add(time.Hour), + fosite.AuthorizeCode: time.Now().UTC().Add(time.Hour), }, }, } diff --git a/handler/oauth2/strategy_jwt.go b/handler/oauth2/strategy_jwt.go index 37edca1a..f3e6cae1 100644 --- a/handler/oauth2/strategy_jwt.go +++ b/handler/oauth2/strategy_jwt.go @@ -157,7 +157,7 @@ func (h *RS256JWTStrategy) generate(tokenType fosite.TokenType, requester fosite claims.ExpiresAt = jwtSession.GetExpiresAt(tokenType) if claims.IssuedAt.IsZero() { - claims.IssuedAt = time.Now() + claims.IssuedAt = time.Now().UTC() } if claims.Issuer == "" { diff --git a/handler/oauth2/strategy_jwt_test.go b/handler/oauth2/strategy_jwt_test.go index 7fcaefcd..c41b592b 100644 --- a/handler/oauth2/strategy_jwt_test.go +++ b/handler/oauth2/strategy_jwt_test.go @@ -46,15 +46,15 @@ var jwtValidCase = func(tokenType fosite.TokenType) *fosite.Request { Issuer: "fosite", Subject: "peter", Audience: "group0", - IssuedAt: time.Now(), - NotBefore: time.Now(), + IssuedAt: time.Now().UTC(), + NotBefore: time.Now().UTC(), Extra: make(map[string]interface{}), }, JWTHeader: &jwt.Headers{ Extra: make(map[string]interface{}), }, ExpiresAt: map[fosite.TokenType]time.Time{ - tokenType: time.Now().Add(time.Hour), + tokenType: time.Now().UTC().Add(time.Hour), }, }, } @@ -73,16 +73,16 @@ var jwtExpiredCase = func(tokenType fosite.TokenType) *fosite.Request { Issuer: "fosite", Subject: "peter", Audience: "group0", - IssuedAt: time.Now(), - NotBefore: time.Now(), - ExpiresAt: time.Now().Add(-time.Minute), + IssuedAt: time.Now().UTC(), + NotBefore: time.Now().UTC(), + ExpiresAt: time.Now().UTC().Add(-time.Minute), Extra: make(map[string]interface{}), }, JWTHeader: &jwt.Headers{ Extra: make(map[string]interface{}), }, ExpiresAt: map[fosite.TokenType]time.Time{ - tokenType: time.Now().Add(-time.Hour), + tokenType: time.Now().UTC().Add(-time.Hour), }, }, } diff --git a/handler/openid/strategy_jwt.go b/handler/openid/strategy_jwt.go index 25cc6da1..fcb2fb1f 100644 --- a/handler/openid/strategy_jwt.go +++ b/handler/openid/strategy_jwt.go @@ -123,7 +123,7 @@ func (h DefaultStrategy) GenerateIDToken(_ context.Context, requester fosite.Req } claims := sess.IDTokenClaims() - if requester.GetRequestForm().Get("max_age") != "" && (claims.AuthTime.IsZero() || claims.AuthTime.After(time.Now())) { + if requester.GetRequestForm().Get("max_age") != "" && (claims.AuthTime.IsZero() || claims.AuthTime.After(time.Now().UTC())) { return "", errors.New("Failed to generate id token because authentication time claim is required when max_age is set and can not be in the future") } @@ -132,15 +132,15 @@ func (h DefaultStrategy) GenerateIDToken(_ context.Context, requester fosite.Req } if claims.ExpiresAt.IsZero() { - claims.ExpiresAt = time.Now().Add(h.Expiry) + claims.ExpiresAt = time.Now().UTC().Add(h.Expiry) } - if claims.ExpiresAt.Before(time.Now()) { + if claims.ExpiresAt.Before(time.Now().UTC()) { return "", errors.New("Failed to generate id token because expiry claim can not be in the past") } if claims.AuthTime.IsZero() { - claims.AuthTime = time.Now() + claims.AuthTime = time.Now().UTC() } if claims.Issuer == "" { @@ -159,7 +159,7 @@ func (h DefaultStrategy) GenerateIDToken(_ context.Context, requester fosite.Req claims.Nonce = nonce claims.Audience = requester.GetClient().GetID() - claims.IssuedAt = time.Now() + claims.IssuedAt = time.Now().UTC() token, _, err = h.RS256JWTStrategy.Generate(claims.ToMapClaims(), sess.IDTokenHeaders()) return token, err diff --git a/handler/openid/strategy_jwt_test.go b/handler/openid/strategy_jwt_test.go index d234004d..2877e5aa 100644 --- a/handler/openid/strategy_jwt_test.go +++ b/handler/openid/strategy_jwt_test.go @@ -46,7 +46,7 @@ func TestJWTStrategy_GenerateIDToken(t *testing.T) { req = fosite.NewAccessRequest(&DefaultSession{ Claims: &jwt.IDTokenClaims{ Subject: "peter", - AuthTime: time.Now(), + AuthTime: time.Now().UTC(), }, Headers: &jwt.Headers{}, }) @@ -60,7 +60,7 @@ func TestJWTStrategy_GenerateIDToken(t *testing.T) { req = fosite.NewAccessRequest(&DefaultSession{ Claims: &jwt.IDTokenClaims{ Subject: "peter", - ExpiresAt: time.Now().Add(-time.Hour), + ExpiresAt: time.Now().UTC().Add(-time.Hour), }, Headers: &jwt.Headers{}, }) diff --git a/integration/authorize_implicit_grant_test.go b/integration/authorize_implicit_grant_test.go index 04b8e994..19bbd40b 100644 --- a/integration/authorize_implicit_grant_test.go +++ b/integration/authorize_implicit_grant_test.go @@ -86,7 +86,7 @@ func runTestAuthorizeImplicitGrant(t *testing.T, strategy interface{}) { AccessToken: fragment.Get("access_token"), TokenType: fragment.Get("token_type"), RefreshToken: fragment.Get("refresh_token"), - Expiry: time.Now().Add(time.Duration(expires) * time.Second), + Expiry: time.Now().UTC().Add(time.Duration(expires) * time.Second), } httpClient := oauthClient.Client(goauth.NoContext, token) diff --git a/integration/oidc_implicit_hybrid_test.go b/integration/oidc_implicit_hybrid_test.go index df1ad75d..4fe66926 100644 --- a/integration/oidc_implicit_hybrid_test.go +++ b/integration/oidc_implicit_hybrid_test.go @@ -157,7 +157,7 @@ func TestOIDCImplicitFlow(t *testing.T) { AccessToken: fragment.Get("access_token"), TokenType: fragment.Get("token_type"), RefreshToken: fragment.Get("refresh_token"), - Expiry: time.Now().Add(time.Duration(expires) * time.Second), + Expiry: time.Now().UTC().Add(time.Duration(expires) * time.Second), } httpClient := oauthClient.Client(oauth2.NoContext, token) diff --git a/request.go b/request.go index b9e6cd68..d76d2d70 100644 --- a/request.go +++ b/request.go @@ -38,7 +38,7 @@ func NewRequest() *Request { Scopes: Arguments{}, GrantedScopes: Arguments{}, Form: url.Values{}, - RequestedAt: time.Now(), + RequestedAt: time.Now().UTC(), } } diff --git a/request_test.go b/request_test.go index f3bae9fc..e061f944 100644 --- a/request_test.go +++ b/request_test.go @@ -25,7 +25,7 @@ import ( func TestRequest(t *testing.T) { r := &Request{ - RequestedAt: time.Now(), + RequestedAt: time.Now().UTC(), Client: &DefaultClient{}, Scopes: Arguments{}, GrantedScopes: []string{}, @@ -43,7 +43,7 @@ func TestRequest(t *testing.T) { func TestMergeRequest(t *testing.T) { a := &Request{ - RequestedAt: time.Now(), + RequestedAt: time.Now().UTC(), Client: &DefaultClient{ID: "123"}, Scopes: Arguments{"asdff"}, GrantedScopes: []string{"asdf"}, @@ -51,7 +51,7 @@ func TestMergeRequest(t *testing.T) { Session: new(DefaultSession), } b := &Request{ - RequestedAt: time.Now(), + RequestedAt: time.Now().UTC(), Client: &DefaultClient{}, Scopes: Arguments{}, GrantedScopes: []string{}, diff --git a/session.go b/session.go index 85501237..1ff5a170 100644 --- a/session.go +++ b/session.go @@ -25,7 +25,7 @@ import ( type Session interface { // SetExpiresAt sets the expiration time of a token. // - // session.SetExpiresAt(fosite.AccessToken, time.Now().Add(time.Hour)) + // session.SetExpiresAt(fosite.AccessToken, time.Now().UTC().Add(time.Hour)) SetExpiresAt(key TokenType, exp time.Time) // SetExpiresAt returns expiration time of a token if set, or time.IsZero() if not. diff --git a/token/jwt/claims.go b/token/jwt/claims.go index 746a25e4..bb4d3797 100644 --- a/token/jwt/claims.go +++ b/token/jwt/claims.go @@ -49,9 +49,9 @@ func ToTime(i interface{}) time.Time { } if t, ok := i.(int64); ok { - return time.Unix(t, 0) + return time.Unix(t, 0).UTC() } else if t, ok := i.(float64); ok { - return time.Unix(int64(t), 0) + return time.Unix(int64(t), 0).UTC() } else if t, ok := i.(time.Time); ok { return t } diff --git a/token/jwt/claims_id_token_test.go b/token/jwt/claims_id_token_test.go index ee235327..e95319da 100644 --- a/token/jwt/claims_id_token_test.go +++ b/token/jwt/claims_id_token_test.go @@ -24,11 +24,11 @@ import ( var idTokenClaims = &IDTokenClaims{ Subject: "peter", - IssuedAt: time.Now().Round(time.Second), + IssuedAt: time.Now().UTC().Round(time.Second), Issuer: "fosite", Audience: "tests", - ExpiresAt: time.Now().Add(time.Hour).Round(time.Second), - AuthTime: time.Now(), + ExpiresAt: time.Now().UTC().Add(time.Hour).Round(time.Second), + AuthTime: time.Now().UTC(), AccessTokenHash: "foobar", CodeHash: "barfoo", AuthenticationContextClassReference: "acr", @@ -39,9 +39,9 @@ var idTokenClaims = &IDTokenClaims{ } func TestIDTokenAssert(t *testing.T) { - assert.Nil(t, (&IDTokenClaims{ExpiresAt: time.Now().Add(time.Hour)}). + assert.Nil(t, (&IDTokenClaims{ExpiresAt: time.Now().UTC().Add(time.Hour)}). ToMapClaims().Valid()) - assert.NotNil(t, (&IDTokenClaims{ExpiresAt: time.Now().Add(-time.Hour)}). + assert.NotNil(t, (&IDTokenClaims{ExpiresAt: time.Now().UTC().Add(-time.Hour)}). ToMapClaims().Valid()) } diff --git a/token/jwt/claims_jwt.go b/token/jwt/claims_jwt.go index 1e0a2dfe..d30a2c32 100644 --- a/token/jwt/claims_jwt.go +++ b/token/jwt/claims_jwt.go @@ -88,23 +88,23 @@ func (c *JWTClaims) FromMap(m map[string]interface{}) { case "iat": switch v.(type) { case float64: - c.IssuedAt = time.Unix(int64(v.(float64)), 0) + c.IssuedAt = time.Unix(int64(v.(float64)), 0).UTC() case int64: - c.IssuedAt = time.Unix(v.(int64), 0) + c.IssuedAt = time.Unix(v.(int64), 0).UTC() } case "nbf": switch v.(type) { case float64: - c.NotBefore = time.Unix(int64(v.(float64)), 0) + c.NotBefore = time.Unix(int64(v.(float64)), 0).UTC() case int64: - c.NotBefore = time.Unix(v.(int64), 0) + c.NotBefore = time.Unix(v.(int64), 0).UTC() } case "exp": switch v.(type) { case float64: - c.ExpiresAt = time.Unix(int64(v.(float64)), 0) + c.ExpiresAt = time.Unix(int64(v.(float64)), 0).UTC() case int64: - c.ExpiresAt = time.Unix(v.(int64), 0) + c.ExpiresAt = time.Unix(v.(int64), 0).UTC() } case "scp": switch v.(type) { diff --git a/token/jwt/claims_jwt_test.go b/token/jwt/claims_jwt_test.go index 2b9b2307..3d168fe4 100644 --- a/token/jwt/claims_jwt_test.go +++ b/token/jwt/claims_jwt_test.go @@ -24,11 +24,11 @@ import ( var jwtClaims = &JWTClaims{ Subject: "peter", - IssuedAt: time.Now().Round(time.Second), + IssuedAt: time.Now().UTC().Round(time.Second), Issuer: "fosite", - NotBefore: time.Now().Round(time.Second), + NotBefore: time.Now().UTC().Round(time.Second), Audience: "tests", - ExpiresAt: time.Now().Add(time.Hour).Round(time.Second), + ExpiresAt: time.Now().UTC().Add(time.Hour).Round(time.Second), JTI: "abcdef", Scope: []string{"email", "offline"}, Extra: map[string]interface{}{ @@ -60,16 +60,16 @@ func TestClaimsToMapSetsID(t *testing.T) { } func TestAssert(t *testing.T) { - assert.Nil(t, (&JWTClaims{ExpiresAt: time.Now().Add(time.Hour)}). + assert.Nil(t, (&JWTClaims{ExpiresAt: time.Now().UTC().Add(time.Hour)}). ToMapClaims().Valid()) - assert.NotNil(t, (&JWTClaims{ExpiresAt: time.Now().Add(-2 * time.Hour)}). + assert.NotNil(t, (&JWTClaims{ExpiresAt: time.Now().UTC().Add(-2 * time.Hour)}). ToMapClaims().Valid()) - assert.NotNil(t, (&JWTClaims{NotBefore: time.Now().Add(time.Hour)}). + assert.NotNil(t, (&JWTClaims{NotBefore: time.Now().UTC().Add(time.Hour)}). ToMapClaims().Valid()) - assert.NotNil(t, (&JWTClaims{NotBefore: time.Now().Add(-time.Hour)}). + assert.NotNil(t, (&JWTClaims{NotBefore: time.Now().UTC().Add(-time.Hour)}). ToMapClaims().Valid()) - assert.Nil(t, (&JWTClaims{ExpiresAt: time.Now().Add(time.Hour), - NotBefore: time.Now().Add(-time.Hour)}).ToMapClaims().Valid()) + assert.Nil(t, (&JWTClaims{ExpiresAt: time.Now().UTC().Add(time.Hour), + NotBefore: time.Now().UTC().Add(-time.Hour)}).ToMapClaims().Valid()) } func TestClaimsToMap(t *testing.T) { diff --git a/token/jwt/claims_test.go b/token/jwt/claims_test.go index 17e381bf..304a480f 100644 --- a/token/jwt/claims_test.go +++ b/token/jwt/claims_test.go @@ -32,7 +32,7 @@ func TestToTime(t *testing.T) { assert.Equal(t, time.Time{}, ToTime(nil)) assert.Equal(t, time.Time{}, ToTime("1234")) - now := time.Now().Round(time.Second) + now := time.Now().UTC().Round(time.Second) assert.Equal(t, now, ToTime(now)) assert.Equal(t, now, ToTime(now.Unix())) assert.Equal(t, now, ToTime(float64(now.Unix()))) diff --git a/token/jwt/jwt_test.go b/token/jwt/jwt_test.go index 69b61afc..29658d0b 100644 --- a/token/jwt/jwt_test.go +++ b/token/jwt/jwt_test.go @@ -70,7 +70,7 @@ func TestAssign(t *testing.T) { func TestGenerateJWT(t *testing.T) { claims := &JWTClaims{ - ExpiresAt: time.Now().Add(time.Hour), + ExpiresAt: time.Now().UTC().Add(time.Hour), } j := RS256JWTStrategy{ @@ -97,7 +97,7 @@ func TestGenerateJWT(t *testing.T) { // Lets validate the exp claim claims = &JWTClaims{ - ExpiresAt: time.Now().Add(-time.Hour), + ExpiresAt: time.Now().UTC().Add(-time.Hour), } token, sig, err = j.Generate(claims.ToMapClaims(), header) require.NoError(t, err) @@ -109,7 +109,7 @@ func TestGenerateJWT(t *testing.T) { // Lets validate the nbf claim claims = &JWTClaims{ - NotBefore: time.Now().Add(time.Hour), + NotBefore: time.Now().UTC().Add(time.Hour), } token, sig, err = j.Generate(claims.ToMapClaims(), header) require.NoError(t, err) From 97fbeb333e353d5d7d7d2368f51899262338ce62 Mon Sep 17 00:00:00 2001 From: arekkas Date: Sun, 10 Dec 2017 22:00:28 +0100 Subject: [PATCH 29/35] Adds ability to catch non-conform OIDC authorizations Fosite is now capable of detecting authorization flows that are not conformant with the OpenID Connect spec. --- errors.go | 18 +++ handler/openid/strategy_jwt.go | 68 +++++++++- handler/openid/strategy_jwt_test.go | 164 +++++++++++++++++++++-- integration/oidc_explicit_test.go | 128 +++++++++++++++--- integration/oidc_implicit_hybrid_test.go | 1 - token/jwt/claims_id_token.go | 6 + token/jwt/claims_id_token_test.go | 6 +- 7 files changed, 354 insertions(+), 37 deletions(-) diff --git a/errors.go b/errors.go index 181a0493..eb5aab2f 100644 --- a/errors.go +++ b/errors.go @@ -159,9 +159,27 @@ var ( Description: "Token was not issued to the client making the revokation request", Code: http.StatusBadRequest, } + ErrLoginRequired = &RFC6749Error{ + Name: errLoginRequired, + Description: "The Authorization Server requires End-User authentication", + Code: http.StatusBadRequest, + } + ErrInteractionRequired = &RFC6749Error{ + Description: "The Authorization Server requires End-User interaction of some form to proceed", + Name: errInteractionRequired, + Code: http.StatusBadRequest, + } + ErrConsentRequired = &RFC6749Error{ + Description: "The Authorization Server requires End-User consent", + Name: errConsentRequired, + Code: http.StatusBadRequest, + } ) const ( + errConsentRequired = "consent_required" + errInteractionRequired = "interaction_required" + errLoginRequired = "login_required" errRequestUnauthorizedName = "request_unauthorized" errRequestForbidden = "request_forbidden" errInvalidRequestName = "invalid_request" diff --git a/handler/openid/strategy_jwt.go b/handler/openid/strategy_jwt.go index fcb2fb1f..4f0806ea 100644 --- a/handler/openid/strategy_jwt.go +++ b/handler/openid/strategy_jwt.go @@ -18,6 +18,10 @@ import ( "context" "time" + "fmt" + "strconv" + + jwtgo "github.com/dgrijalva/jwt-go" "github.com/mohae/deepcopy" "github.com/ory/fosite" "github.com/ory/fosite/token/jwt" @@ -45,7 +49,9 @@ type DefaultSession struct { func NewDefaultSession() *DefaultSession { return &DefaultSession{ - Claims: &jwt.IDTokenClaims{}, + Claims: &jwt.IDTokenClaims{ + RequestedAt: time.Now().UTC(), + }, Headers: &jwt.Headers{}, } } @@ -123,14 +129,66 @@ func (h DefaultStrategy) GenerateIDToken(_ context.Context, requester fosite.Req } claims := sess.IDTokenClaims() - if requester.GetRequestForm().Get("max_age") != "" && (claims.AuthTime.IsZero() || claims.AuthTime.After(time.Now().UTC())) { - return "", errors.New("Failed to generate id token because authentication time claim is required when max_age is set and can not be in the future") - } - if claims.Subject == "" { return "", errors.New("Failed to generate id token because subject is an empty string") } + if requester.GetRequestForm().Get("grant_type") != "refresh_token" { + maxAge, err := strconv.ParseInt(requester.GetRequestForm().Get("max_age"), 10, 64) + if err != nil { + maxAge = 0 + } + + if maxAge > 0 { + if claims.AuthTime.IsZero() || claims.AuthTime.After(time.Now()) { + return "", errors.New("Failed to generate id token because authentication time claim is required when max_age is set and can not be in the future") + } else if claims.AuthTime.Add(time.Second * time.Duration(maxAge)).Before(time.Now()) { + return "", errors.WithStack(fosite.ErrLoginRequired.WithDebug("Failed to generate id token because authentication time does not satisfy max_age time")) + } + } + + prompt := requester.GetRequestForm().Get("prompt") + if prompt != "" { + if claims.AuthTime.IsZero() || claims.AuthTime.After(time.Now()) { + return "", errors.New("Unable to determine validity of prompt parameter because auth_time is missing in id token claims") + } + } + + switch prompt { + case "none": + if claims.AuthTime.After(claims.RequestedAt) { + return "", errors.WithStack(fosite.ErrLoginRequired.WithDebug("Failed to generate id token because prompt was set to \"none\" but auth_time happened after the authorization request was registered, indicating that the user was logged in during this request which is not allowed")) + } + break + case "login": + if claims.AuthTime.Before(claims.RequestedAt) { + return "", errors.WithStack(fosite.ErrLoginRequired.WithDebug("Failed to generate id token because prompt was set to \"login\" but auth_time happened before the authorization request was registered, indicating that the user was not re-authenticated which is forbidden")) + } + break + } + + // If acr_values was requested but no acr value was provided in the ID token, fall back to level 0 which means least + // confidence in authentication. + if requester.GetRequestForm().Get("acr_values") != "" && claims.AuthenticationContextClassReference == "" { + claims.AuthenticationContextClassReference = "0" + } + + if tokenHintString := requester.GetRequestForm().Get("id_token_hint"); tokenHintString != "" { + tokenHint, err := h.RS256JWTStrategy.Decode(tokenHintString) + if err != nil { + return "", errors.WithStack(fosite.ErrInvalidRequest.WithDebug(fmt.Sprintf("Unable to decode id token from id_token_hint parameter because %s", err.Error()))) + } + + if hintClaims, ok := tokenHint.Claims.(jwtgo.MapClaims); !ok { + return "", errors.WithStack(fosite.ErrInvalidRequest.WithDebug("Unable to decode id token from id_token_hint to *jwt.StandardClaims")) + } else if hintSub, _ := hintClaims["sub"].(string); hintSub == "" { + return "", errors.WithStack(fosite.ErrInvalidRequest.WithDebug("Provided id token from id_token_hint does not have a subject")) + } else if hintSub != claims.Subject { + return "", errors.WithStack(fosite.ErrLoginRequired.WithDebug(fmt.Sprintf("Subject from authorization mismatches id token subject from id_token_hint"))) + } + } + } + if claims.ExpiresAt.IsZero() { claims.ExpiresAt = time.Now().UTC().Add(h.Expiry) } diff --git a/handler/openid/strategy_jwt_test.go b/handler/openid/strategy_jwt_test.go index 2877e5aa..afe20809 100644 --- a/handler/openid/strategy_jwt_test.go +++ b/handler/openid/strategy_jwt_test.go @@ -18,6 +18,8 @@ import ( "testing" "time" + "fmt" + "github.com/ory/fosite" "github.com/ory/fosite/token/jwt" "github.com/stretchr/testify/assert" @@ -26,8 +28,9 @@ import ( func TestJWTStrategy_GenerateIDToken(t *testing.T) { var req *fosite.AccessRequest for k, c := range []struct { - setup func() - expectErr bool + description string + setup func() + expectErr bool }{ { setup: func() { @@ -102,12 +105,157 @@ func TestJWTStrategy_GenerateIDToken(t *testing.T) { }, expectErr: false, }, + { + description: "should pass because max_age was requested and auth_time happened after initial request time", + setup: func() { + req = fosite.NewAccessRequest(&DefaultSession{ + Claims: &jwt.IDTokenClaims{ + Subject: "peter", + AuthTime: time.Now().UTC(), + }, + Headers: &jwt.Headers{}, + }) + req.Form.Set("max_age", "60") + }, + expectErr: false, + }, + { + description: "should fail because max_age was requested and auth_time has expired", + setup: func() { + req = fosite.NewAccessRequest(&DefaultSession{ + Claims: &jwt.IDTokenClaims{ + Subject: "peter", + AuthTime: time.Now().Add(-time.Hour).UTC(), + }, + Headers: &jwt.Headers{}, + }) + req.Form.Set("max_age", "60") + }, + expectErr: true, + }, + { + description: "should fail because prompt=none was requested and auth_time indicates fresh login", + setup: func() { + req = fosite.NewAccessRequest(&DefaultSession{ + Claims: &jwt.IDTokenClaims{ + Subject: "peter", + AuthTime: time.Now().UTC(), + RequestedAt: time.Now().Add(-time.Minute), + }, + Headers: &jwt.Headers{}, + }) + req.Form.Set("prompt", "none") + }, + expectErr: true, + }, + { + description: "should pass because prompt=none was requested and auth_time indicates fresh login but grant type is refresh_token", + setup: func() { + req = fosite.NewAccessRequest(&DefaultSession{ + Claims: &jwt.IDTokenClaims{ + Subject: "peter", + AuthTime: time.Now().UTC(), + RequestedAt: time.Now().Add(-time.Minute), + }, + Headers: &jwt.Headers{}, + }) + req.Form.Set("prompt", "none") + req.Form.Set("grant_type", "refresh_token") + }, + expectErr: false, + }, + { + description: "should pass because prompt=none was requested and auth_time indicates old login", + setup: func() { + req = fosite.NewAccessRequest(&DefaultSession{ + Claims: &jwt.IDTokenClaims{ + Subject: "peter", + AuthTime: time.Now().Add(-time.Hour).UTC(), + RequestedAt: time.Now().Add(-time.Minute), + }, + Headers: &jwt.Headers{}, + }) + req.Form.Set("prompt", "none") + }, + expectErr: false, + }, + { + description: "should pass because prompt=login was requested and auth_time indicates fresh login", + setup: func() { + req = fosite.NewAccessRequest(&DefaultSession{ + Claims: &jwt.IDTokenClaims{ + Subject: "peter", + AuthTime: time.Now().UTC(), + RequestedAt: time.Now().Add(-time.Minute), + }, + Headers: &jwt.Headers{}, + }) + req.Form.Set("prompt", "login") + }, + expectErr: false, + }, + { + description: "should fail because prompt=login was requested and auth_time indicates old login", + setup: func() { + req = fosite.NewAccessRequest(&DefaultSession{ + Claims: &jwt.IDTokenClaims{ + Subject: "peter", + AuthTime: time.Now().Add(-time.Hour).UTC(), + RequestedAt: time.Now().Add(-time.Minute), + }, + Headers: &jwt.Headers{}, + }) + req.Form.Set("prompt", "login") + }, + expectErr: true, + }, + { + description: "should pass because id_token_hint subject matches subject from claims", + setup: func() { + req = fosite.NewAccessRequest(&DefaultSession{ + Claims: &jwt.IDTokenClaims{ + Subject: "peter", + AuthTime: time.Now().Add(-time.Hour).UTC(), + RequestedAt: time.Now().Add(-time.Minute), + }, + Headers: &jwt.Headers{}, + }) + token, _ := j.GenerateIDToken(nil, fosite.NewAccessRequest(&DefaultSession{ + Claims: &jwt.IDTokenClaims{ + Subject: "peter", + }, + Headers: &jwt.Headers{}, + })) + req.Form.Set("id_token_hint", token) + }, + expectErr: false, + }, + { + description: "should fail because id_token_hint subject does not match subject from claims", + setup: func() { + req = fosite.NewAccessRequest(&DefaultSession{ + Claims: &jwt.IDTokenClaims{ + Subject: "peter", + AuthTime: time.Now().Add(-time.Hour).UTC(), + RequestedAt: time.Now().Add(-time.Minute), + }, + Headers: &jwt.Headers{}, + }) + token, _ := j.GenerateIDToken(nil, fosite.NewAccessRequest(&DefaultSession{ + Claims: &jwt.IDTokenClaims{Subject: "alice"}, Headers: &jwt.Headers{}, + })) + req.Form.Set("id_token_hint", token) + }, + expectErr: true, + }, } { - c.setup() - token, err := j.GenerateIDToken(nil, req) - assert.Equal(t, c.expectErr, err != nil, "%d: %s", k, err) - if !c.expectErr { - assert.NotEmpty(t, token) - } + t.Run(fmt.Sprintf("case=%d/description=%s", k, c.description), func(t *testing.T) { + c.setup() + token, err := j.GenerateIDToken(nil, req) + assert.Equal(t, c.expectErr, err != nil, "%d: %s", k, err) + if !c.expectErr { + assert.NotEmpty(t, token) + } + }) } } diff --git a/integration/oidc_explicit_test.go b/integration/oidc_explicit_test.go index 94fb8ad1..70fed210 100644 --- a/integration/oidc_explicit_test.go +++ b/integration/oidc_explicit_test.go @@ -20,58 +20,144 @@ import ( "fmt" + "io/ioutil" + "strings" + "time" + "github.com/ory/fosite/compose" "github.com/ory/fosite/handler/openid" "github.com/ory/fosite/internal" "github.com/ory/fosite/token/jwt" + "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" "golang.org/x/oauth2" ) -func TestOpenIDConnectExplicitFlow(t *testing.T) { - session := &defaultSession{ +func newIDSession(j *jwt.IDTokenClaims) *defaultSession { + return &defaultSession{ DefaultSession: &openid.DefaultSession{ - Claims: &jwt.IDTokenClaims{ - Subject: "peter", - }, + Claims: j, Headers: &jwt.Headers{}, }, } - f := compose.ComposeAllEnabled(new(compose.Config), fositeStore, []byte("some-secret-thats-random-some-secret-thats-random-"), internal.MustRSAKey()) - ts := mockServer(t, f, session) +} - defer ts.Close() - oauthClient := newOAuth2Client(ts) - fositeStore.Clients["my-client"].RedirectURIs[0] = ts.URL + "/callback" +func TestOpenIDConnectExplicitFlow(t *testing.T) { + f := compose.ComposeAllEnabled(new(compose.Config), fositeStore, []byte("some-secret-thats-random-some-secret-thats-random-"), internal.MustRSAKey()) - var state string for k, c := range []struct { description string - setup func() + setup func(oauthClient *oauth2.Config) string authStatusCode int + authCodeURL string + session *defaultSession + expectAuthErr string + expectTokenErr string }{ { + session: newIDSession(&jwt.IDTokenClaims{Subject: "peter"}), description: "should pass", - setup: func() { - state = "12345678901234567890" + setup: func(oauthClient *oauth2.Config) string { + oauthClient.Scopes = []string{"openid"} + return oauthClient.AuthCodeURL("12345678901234567890") + "&nonce=11234123" + }, + authStatusCode: http.StatusOK, + }, + { + session: newIDSession(&jwt.IDTokenClaims{Subject: "peter"}), + description: "should fail because nonce is not long enough", + setup: func(oauthClient *oauth2.Config) string { oauthClient.Scopes = []string{"openid"} + return oauthClient.AuthCodeURL("12345678901234567890") + "&nonce=1" + }, + authStatusCode: http.StatusOK, + expectTokenErr: "insufficient_entropy", + }, + { + session: newIDSession(&jwt.IDTokenClaims{Subject: "peter"}), + description: "should fail because state is not long enough", + setup: func(oauthClient *oauth2.Config) string { + oauthClient.Scopes = []string{"openid"} + return oauthClient.AuthCodeURL("123") + "&nonce=1234567890" + }, + expectAuthErr: "invalid_state", + authStatusCode: http.StatusNotAcceptable, // code from internal test callback handler when error occurs + }, + { + session: newIDSession(&jwt.IDTokenClaims{ + Subject: "peter", + RequestedAt: time.Now().UTC(), + AuthTime: time.Now().Add(time.Second).UTC(), + }), + description: "should pass", + setup: func(oauthClient *oauth2.Config) string { + oauthClient.Scopes = []string{"openid"} + return oauthClient.AuthCodeURL("12345678901234567890") + "&nonce=1234567890&prompt=login" + }, + authStatusCode: http.StatusOK, + }, + { + session: newIDSession(&jwt.IDTokenClaims{ + Subject: "peter", + RequestedAt: time.Now().UTC(), + AuthTime: time.Now().Add(-time.Minute).UTC(), + }), + description: "should fail because authentication was in the past", + setup: func(oauthClient *oauth2.Config) string { + oauthClient.Scopes = []string{"openid"} + return oauthClient.AuthCodeURL("12345678901234567890") + "&nonce=1234567890&prompt=login" + }, + authStatusCode: http.StatusOK, + expectTokenErr: "login_required", + }, + { + session: newIDSession(&jwt.IDTokenClaims{ + Subject: "peter", + RequestedAt: time.Now().UTC(), + AuthTime: time.Now().Add(-time.Minute).UTC(), + }), + description: "should pass because authorization was in the past and no login was required", + setup: func(oauthClient *oauth2.Config) string { + oauthClient.Scopes = []string{"openid"} + return oauthClient.AuthCodeURL("12345678901234567890") + "&nonce=1234567890&prompt=none" }, authStatusCode: http.StatusOK, }, } { t.Run(fmt.Sprintf("case=%d/description=%s", k, c.description), func(t *testing.T) { - c.setup() + ts := mockServer(t, f, c.session) + defer ts.Close() + + oauthClient := newOAuth2Client(ts) + fositeStore.Clients["my-client"].RedirectURIs[0] = ts.URL + "/callback" - resp, err := http.Get(oauthClient.AuthCodeURL(state) + "&nonce=1234567890") + resp, err := http.Get(c.setup(oauthClient)) require.NoError(t, err) - require.Equal(t, c.authStatusCode, resp.StatusCode) + defer resp.Body.Close() + + body, _ := ioutil.ReadAll(resp.Body) + require.Equal(t, c.authStatusCode, resp.StatusCode, "Got response: %s", body) + if resp.StatusCode >= 400 { + assert.Equal(t, c.expectAuthErr, strings.Replace(string(body), "error: ", "", 1)) + } + + if c.expectAuthErr != "" { + assert.Empty(t, resp.Request.URL.Query().Get("code")) + } if resp.StatusCode == http.StatusOK { + time.Sleep(time.Second) + token, err := oauthClient.Exchange(oauth2.NoContext, resp.Request.URL.Query().Get("code")) - fmt.Printf("after exchange: %s\n\n", fositeStore.AuthorizeCodes) - require.NoError(t, err) - require.NotEmpty(t, token.AccessToken) - require.NotEmpty(t, token.Extra("id_token")) + + if c.expectTokenErr != "" { + assert.Error(t, err) + assert.True(t, strings.Contains(err.Error(), c.expectTokenErr), err.Error()) + } else { + require.NoError(t, err) + assert.NotEmpty(t, token.AccessToken) + assert.NotEmpty(t, token.Extra("id_token")) + } } }) } diff --git a/integration/oidc_implicit_hybrid_test.go b/integration/oidc_implicit_hybrid_test.go index 4fe66926..ee861a79 100644 --- a/integration/oidc_implicit_hybrid_test.go +++ b/integration/oidc_implicit_hybrid_test.go @@ -80,7 +80,6 @@ func TestOIDCImplicitFlow(t *testing.T) { hasToken: true, hasIdToken: true, }, - { responseType: "token%20id_token%20code", diff --git a/token/jwt/claims_id_token.go b/token/jwt/claims_id_token.go index d9d5649a..13fffc62 100644 --- a/token/jwt/claims_id_token.go +++ b/token/jwt/claims_id_token.go @@ -28,6 +28,7 @@ type IDTokenClaims struct { Nonce string ExpiresAt time.Time IssuedAt time.Time + RequestedAt time.Time AuthTime time.Time AccessTokenHash string AuthenticationContextClassReference string @@ -55,12 +56,17 @@ func (c *IDTokenClaims) ToMap() map[string]interface{} { ret["auth_time"] = c.AuthTime.Unix() } + if !c.RequestedAt.IsZero() { + ret["auth_time"] = c.RequestedAt.Unix() + } + if len(c.AuthenticationContextClassReference) > 0 { ret["acr"] = c.AuthenticationContextClassReference } ret["iat"] = float64(c.IssuedAt.Unix()) ret["exp"] = float64(c.ExpiresAt.Unix()) + ret["rat"] = float64(c.RequestedAt.Unix()) return ret } diff --git a/token/jwt/claims_id_token_test.go b/token/jwt/claims_id_token_test.go index e95319da..5a9516d2 100644 --- a/token/jwt/claims_id_token_test.go +++ b/token/jwt/claims_id_token_test.go @@ -29,6 +29,7 @@ var idTokenClaims = &IDTokenClaims{ Audience: "tests", ExpiresAt: time.Now().UTC().Add(time.Hour).Round(time.Second), AuthTime: time.Now().UTC(), + RequestedAt: time.Now().UTC(), AccessTokenHash: "foobar", CodeHash: "barfoo", AuthenticationContextClassReference: "acr", @@ -39,9 +40,9 @@ var idTokenClaims = &IDTokenClaims{ } func TestIDTokenAssert(t *testing.T) { - assert.Nil(t, (&IDTokenClaims{ExpiresAt: time.Now().UTC().Add(time.Hour)}). + assert.NoError(t, (&IDTokenClaims{ExpiresAt: time.Now().UTC().Add(time.Hour)}). ToMapClaims().Valid()) - assert.NotNil(t, (&IDTokenClaims{ExpiresAt: time.Now().UTC().Add(-time.Hour)}). + assert.Error(t, (&IDTokenClaims{ExpiresAt: time.Now().UTC().Add(-time.Hour)}). ToMapClaims().Valid()) } @@ -49,6 +50,7 @@ func TestIDTokenClaimsToMap(t *testing.T) { assert.Equal(t, map[string]interface{}{ "sub": idTokenClaims.Subject, "iat": float64(idTokenClaims.IssuedAt.Unix()), + "rat": float64(idTokenClaims.RequestedAt.Unix()), "iss": idTokenClaims.Issuer, "aud": idTokenClaims.Audience, "nonce": idTokenClaims.Nonce, From c85b32d355a183dac3e46e50aac8b2c344cbd2d7 Mon Sep 17 00:00:00 2001 From: arekkas Date: Sun, 17 Dec 2017 18:46:38 +0100 Subject: [PATCH 30/35] Resolves overriding auth_time with wrong value --- token/jwt/claims_id_token.go | 4 ---- 1 file changed, 4 deletions(-) diff --git a/token/jwt/claims_id_token.go b/token/jwt/claims_id_token.go index 13fffc62..6f325050 100644 --- a/token/jwt/claims_id_token.go +++ b/token/jwt/claims_id_token.go @@ -56,10 +56,6 @@ func (c *IDTokenClaims) ToMap() map[string]interface{} { ret["auth_time"] = c.AuthTime.Unix() } - if !c.RequestedAt.IsZero() { - ret["auth_time"] = c.RequestedAt.Unix() - } - if len(c.AuthenticationContextClassReference) > 0 { ret["acr"] = c.AuthenticationContextClassReference } From 6831f7543000b3704879e52d8c9a4555653b4bd5 Mon Sep 17 00:00:00 2001 From: arekkas Date: Sun, 17 Dec 2017 21:16:46 +0100 Subject: [PATCH 31/35] Improves http error codes --- errors.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/errors.go b/errors.go index eb5aab2f..3ea3e0ae 100644 --- a/errors.go +++ b/errors.go @@ -25,7 +25,7 @@ var ( ErrUnknownRequest = &RFC6749Error{ Name: errUnknownErrorName, Description: "The handler is not responsible for this request", - Code: http.StatusInternalServerError, + Code: http.StatusBadRequest, } ErrRequestForbidden = &RFC6749Error{ Name: errRequestForbidden, @@ -43,7 +43,7 @@ var ( Name: errUnauthorizedClientName, Description: "The client is not authorized to request a token using this method", Hint: "Make sure that client id and secret are correctly specified and that the client exists.", - Code: http.StatusUnauthorized, + Code: http.StatusBadRequest, } ErrAccessDenied = &RFC6749Error{ Name: errAccessDeniedName, @@ -84,7 +84,7 @@ var ( ErrInvalidClient = &RFC6749Error{ Name: errInvalidClientName, Description: "Client authentication failed (e.g., unknown client, no client authentication included, or unsupported authentication method)", - Code: http.StatusForbidden, + Code: http.StatusUnauthorized, } ErrInvalidState = &RFC6749Error{ Name: errInvalidStateName, @@ -152,7 +152,7 @@ var ( Name: errAuthorizaionCodeInactiveName, Description: "Authorization code is inactive because it is malformed, expired or otherwise invalid", Hint: "Authorization code validation failed.", - Code: http.StatusForbidden, + Code: http.StatusBadRequest, } ErrRevokationClientMismatch = &RFC6749Error{ Name: errRevokationClientMismatchName, From 95d5f580c939eea0e6e93cdb4bae4cdbf5082869 Mon Sep 17 00:00:00 2001 From: arekkas Date: Sun, 17 Dec 2017 21:34:32 +0100 Subject: [PATCH 32/35] Returns the correct error on duplicate auth code use --- errors.go | 6 ------ handler/oauth2/flow_authorize_code_token.go | 4 ++-- handler/oauth2/flow_authorize_code_token_test.go | 4 ++-- 3 files changed, 4 insertions(+), 10 deletions(-) diff --git a/errors.go b/errors.go index 3ea3e0ae..70e24e62 100644 --- a/errors.go +++ b/errors.go @@ -148,12 +148,6 @@ var ( Hint: "Token validation failed.", Code: http.StatusUnauthorized, } - ErrInactiveAuthorizationCode = &RFC6749Error{ - Name: errAuthorizaionCodeInactiveName, - Description: "Authorization code is inactive because it is malformed, expired or otherwise invalid", - Hint: "Authorization code validation failed.", - Code: http.StatusBadRequest, - } ErrRevokationClientMismatch = &RFC6749Error{ Name: errRevokationClientMismatchName, Description: "Token was not issued to the client making the revokation request", diff --git a/handler/oauth2/flow_authorize_code_token.go b/handler/oauth2/flow_authorize_code_token.go index 05537f5e..b1bba94d 100644 --- a/handler/oauth2/flow_authorize_code_token.go +++ b/handler/oauth2/flow_authorize_code_token.go @@ -51,7 +51,7 @@ func (c *AuthorizeExplicitGrantHandler) HandleTokenEndpointRequest(ctx context.C // debug += revErr.Error() + "\n" // } - return errors.WithStack(fosite.ErrInactiveAuthorizationCode.WithDebug(debug)) + return errors.WithStack(fosite.ErrInvalidGrant.WithDebug(debug)) } else if err != nil { return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) } @@ -59,7 +59,7 @@ func (c *AuthorizeExplicitGrantHandler) HandleTokenEndpointRequest(ctx context.C // The authorization server MUST verify that the authorization code is valid // This needs to happen after store retrieval for the session to be hydrated properly if err := c.AuthorizeCodeStrategy.ValidateAuthorizeCode(ctx, request, code); err != nil { - return errors.WithStack(fosite.ErrInactiveAuthorizationCode.WithDebug(err.Error())) + return errors.WithStack(fosite.ErrInvalidGrant.WithDebug(err.Error())) } // Override scopes diff --git a/handler/oauth2/flow_authorize_code_token_test.go b/handler/oauth2/flow_authorize_code_token_test.go index 6524ab15..4a223027 100644 --- a/handler/oauth2/flow_authorize_code_token_test.go +++ b/handler/oauth2/flow_authorize_code_token_test.go @@ -211,7 +211,7 @@ func TestAuthorizeCode_HandleTokenEndpointRequest(t *testing.T) { require.NoError(t, err) areq.Form = url.Values{"code": {token}} }, - expectErr: fosite.ErrInactiveAuthorizationCode, + expectErr: fosite.ErrInvalidGrant, }, { areq: &fosite.AccessRequest{ @@ -224,7 +224,7 @@ func TestAuthorizeCode_HandleTokenEndpointRequest(t *testing.T) { }, }, description: "should fail because authcode validation failed", - expectErr: fosite.ErrInactiveAuthorizationCode, + expectErr: fosite.ErrInvalidGrant, }, { areq: &fosite.AccessRequest{ From 2aa8e70bb88aa6bafde8d4ea949c5d514c6f568e Mon Sep 17 00:00:00 2001 From: arekkas Date: Thu, 21 Dec 2017 16:33:08 +0100 Subject: [PATCH 33/35] handler/oauth2: Adds offline_access alias for refresh flow --- arguments.go | 10 ++++++++ arguments_test.go | 27 +++++++++++++++++++++ handler/oauth2/flow_authorize_code_token.go | 2 +- handler/oauth2/flow_refresh.go | 2 +- handler/oauth2/flow_resource_owner.go | 2 +- 5 files changed, 40 insertions(+), 3 deletions(-) diff --git a/arguments.go b/arguments.go index 64a2893b..9fb48c18 100644 --- a/arguments.go +++ b/arguments.go @@ -40,6 +40,16 @@ func (r Arguments) Has(items ...string) bool { return true } +func (r Arguments) HasOneOf(items ...string) bool { + for _, item := range items { + if StringInSlice(item, r) { + return true + } + } + + return false +} + func (r Arguments) Exact(name string) bool { return name == strings.Join(r, " ") } diff --git a/arguments_test.go b/arguments_test.go index 2956d00c..dbec3cfd 100644 --- a/arguments_test.go +++ b/arguments_test.go @@ -160,3 +160,30 @@ func TestArgumentsMatches(t *testing.T) { t.Logf("Passed test case %d", k) } } + +func TestArgumentsOneOf(t *testing.T) { + for k, c := range []struct { + args Arguments + oneOf []string + expect bool + }{ + { + args: Arguments{"baz", "bar"}, + oneOf: []string{"foo", "bar"}, + expect: true, + }, + { + args: Arguments{"foo", "baz"}, + oneOf: []string{"foo", "bar"}, + expect: true, + }, + { + args: Arguments{"baz"}, + oneOf: []string{"foo", "bar"}, + expect: false, + }, + } { + assert.Equal(t, c.expect, c.args.HasOneOf(c.oneOf...), "%d", k) + t.Logf("Passed test case %d", k) + } +} diff --git a/handler/oauth2/flow_authorize_code_token.go b/handler/oauth2/flow_authorize_code_token.go index b1bba94d..d8c59426 100644 --- a/handler/oauth2/flow_authorize_code_token.go +++ b/handler/oauth2/flow_authorize_code_token.go @@ -119,7 +119,7 @@ func (c *AuthorizeExplicitGrantHandler) PopulateTokenEndpointResponse(ctx contex } var refresh, refreshSignature string - if authorizeRequest.GetGrantedScopes().Has("offline") { + if authorizeRequest.GetGrantedScopes().HasOneOf("offline", "offline_access") { refresh, refreshSignature, err = c.RefreshTokenStrategy.GenerateRefreshToken(ctx, requester) if err != nil { return errors.WithStack(fosite.ErrServerError.WithDebug(err.Error())) diff --git a/handler/oauth2/flow_refresh.go b/handler/oauth2/flow_refresh.go index 276fa328..b49d3f13 100644 --- a/handler/oauth2/flow_refresh.go +++ b/handler/oauth2/flow_refresh.go @@ -57,7 +57,7 @@ func (c *RefreshTokenGrantHandler) HandleTokenEndpointRequest(ctx context.Contex return errors.WithStack(fosite.ErrInvalidRequest.WithDebug(err.Error())) } - if !originalRequest.GetGrantedScopes().Has("offline") { + if !originalRequest.GetGrantedScopes().HasOneOf("offline", "offline_access") { return errors.WithStack(fosite.ErrScopeNotGranted.WithDebug("The client is not allowed to use grant type refresh_token")) } diff --git a/handler/oauth2/flow_resource_owner.go b/handler/oauth2/flow_resource_owner.go index 86f892b7..4b5f9a48 100644 --- a/handler/oauth2/flow_resource_owner.go +++ b/handler/oauth2/flow_resource_owner.go @@ -77,7 +77,7 @@ func (c *ResourceOwnerPasswordCredentialsGrantHandler) PopulateTokenEndpointResp } var refresh, refreshSignature string - if requester.GetGrantedScopes().Has("offline") { + if requester.GetGrantedScopes().HasOneOf("offline", "offline_access") { var err error refresh, refreshSignature, err = c.RefreshTokenStrategy.GenerateRefreshToken(ctx, requester) if err != nil { From 7216c4f2711c79cf3d8a2c75ad7da4f54103988f Mon Sep 17 00:00:00 2001 From: Aeneas Date: Sat, 23 Dec 2017 15:56:29 +0100 Subject: [PATCH 34/35] Adds ability to forward hints and debug messages to clients (#242) --- HISTORY.md | 11 +++ access_error.go | 8 +- access_error_test.go | 54 ++++++++----- authorize_error.go | 11 +++ authorize_error_test.go | 130 ++++++++++++++++++++----------- errors.go | 6 +- fosite.go | 5 ++ introspection_response_writer.go | 2 +- 8 files changed, 158 insertions(+), 69 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index e7f9c1dc..8fd3df9b 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -39,6 +39,17 @@ bumps (`0.1.0` -> `0.2.0`). +## 0.16.0 + +This patch introduces `SendDebugMessagesToClients` to the Fosite struct which enables/disables sending debug information to +clients. Debug information may contain sensitive information as it forwards error messages from, for example, storage +implementations. For this reason, `RevealDebugPayloads` defaults to false. Keep in mind that the information may be +very helpful when specific OAuth 2.0 requests fail and we generally recommend displaying debug information. + +Additionally, error keys for JSON changed which caused a new minor version, speicifically +[`statusCode` was changed to `status_code`](https://github.com/ory/fosite/pull/242/files#diff-dd25e0e0a594c3f3592c1c717039b85eR221). + + ## 0.15.0 This release focuses on improving compatibility with OpenID Connect Certification and better error context. diff --git a/access_error.go b/access_error.go index 09ce8c4b..f54b7c63 100644 --- a/access_error.go +++ b/access_error.go @@ -21,13 +21,17 @@ import ( ) func (c *Fosite) WriteAccessError(rw http.ResponseWriter, _ AccessRequester, err error) { - writeJsonError(rw, err) + c.writeJsonError(rw, err) } -func writeJsonError(rw http.ResponseWriter, err error) { +func (c *Fosite) writeJsonError(rw http.ResponseWriter, err error) { rw.Header().Set("Content-Type", "application/json;charset=UTF-8") rfcerr := ErrorToRFC6749Error(err) + if !c.SendDebugMessagesToClients { + rfcerr.Debug = "" + } + js, err := json.Marshal(rfcerr) if err != nil { http.Error(rw, fmt.Sprintf(`{"error": "%s"}`, err.Error()), http.StatusInternalServerError) diff --git a/access_error_test.go b/access_error_test.go index 90b47623..79840b2e 100644 --- a/access_error_test.go +++ b/access_error_test.go @@ -20,6 +20,8 @@ import ( "net/http/httptest" "testing" + "fmt" + "github.com/golang/mock/gomock" . "github.com/ory/fosite" . "github.com/ory/fosite/internal" @@ -47,29 +49,43 @@ func TestWriteAccessError_RFC6749(t *testing.T) { f := &Fosite{} for k, c := range []struct { - err *RFC6749Error - code string + err *RFC6749Error + code string + debug bool }{ - {ErrInvalidRequest, "invalid_request"}, - {ErrInvalidClient, "invalid_client"}, - {ErrInvalidGrant, "invalid_grant"}, - {ErrInvalidScope, "invalid_scope"}, - {ErrUnauthorizedClient, "unauthorized_client"}, - {ErrUnsupportedGrantType, "unsupported_grant_type"}, + {ErrInvalidRequest.WithDebug("some-debug"), "invalid_request", false}, + {ErrInvalidClient.WithDebug("some-debug"), "invalid_client", false}, + {ErrInvalidGrant.WithDebug("some-debug"), "invalid_grant", false}, + {ErrInvalidScope.WithDebug("some-debug"), "invalid_scope", false}, + {ErrUnauthorizedClient.WithDebug("some-debug"), "unauthorized_client", false}, + {ErrUnsupportedGrantType.WithDebug("some-debug"), "unsupported_grant_type", false}, } { - rw := httptest.NewRecorder() - f.WriteAccessError(rw, nil, c.err) + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + f.SendDebugMessagesToClients = c.debug + + rw := httptest.NewRecorder() + f.WriteAccessError(rw, nil, c.err) + + var params struct { + Error string `json:"error"` // specified by RFC, required + Description string `json:"error_description"` // specified by RFC, optional + Debug string `json:"error_debug"` + Hint string `json:"error_hint"` + } - var params struct { - Error string `json:"error"` // specified by RFC, required - Description string `json:"error_description"` // specified by RFC, optional - } + require.NotNil(t, rw.Body) + err := json.NewDecoder(rw.Body).Decode(¶ms) + require.NoError(t, err) - require.NotNil(t, rw.Body, "(%d) %s: nil body", k, c.code) - err := json.NewDecoder(rw.Body).Decode(¶ms) - require.NoError(t, err, "(%d) %s", k, c.code) + assert.Equal(t, c.code, params.Error) + assert.Equal(t, c.err.Description, params.Description) + assert.Equal(t, c.err.Hint, params.Hint) - assert.Equal(t, c.code, params.Error, "(%d) %s: error", k, c.code) - assert.Equal(t, c.err.Description, params.Description, "(%d) %s: description", k, c.code) + if !c.debug { + assert.Empty(t, params.Debug) + } else { + assert.Equal(t, "some-debug", params.Debug) + } + }) } } diff --git a/authorize_error.go b/authorize_error.go index eaa41d48..5cca4a23 100644 --- a/authorize_error.go +++ b/authorize_error.go @@ -23,6 +23,10 @@ import ( func (c *Fosite) WriteAuthorizeError(rw http.ResponseWriter, ar AuthorizeRequester, err error) { rfcerr := ErrorToRFC6749Error(err) if !ar.IsRedirectURIValid() { + if !c.SendDebugMessagesToClients { + rfcerr.Debug = "" + } + js, err := json.MarshalIndent(rfcerr, "", "\t") if err != nil { http.Error(rw, err.Error(), http.StatusInternalServerError) @@ -40,6 +44,13 @@ func (c *Fosite) WriteAuthorizeError(rw http.ResponseWriter, ar AuthorizeRequest query.Add("error", rfcerr.Name) query.Add("error_description", rfcerr.Description) query.Add("state", ar.GetState()) + if c.SendDebugMessagesToClients && rfcerr.Debug != "" { + query.Add("error_debug", rfcerr.Debug) + } + + if rfcerr.Hint != "" { + query.Add("error_hint", rfcerr.Hint) + } if ar.GetResponseTypes().Exact("token") || len(ar.GetResponseTypes()) > 1 { redirectURI.Fragment = query.Encode() diff --git a/authorize_error_test.go b/authorize_error_test.go index 1eb51fda..c39d1bb0 100644 --- a/authorize_error_test.go +++ b/authorize_error_test.go @@ -19,6 +19,8 @@ import ( "net/url" "testing" + "fmt" + "github.com/golang/mock/gomock" . "github.com/ory/fosite" . "github.com/ory/fosite/internal" @@ -40,11 +42,6 @@ import ( // additional query parameters. The endpoint URI MUST NOT include a // fragment component. func TestWriteAuthorizeError(t *testing.T) { - ctrl := gomock.NewController(t) - rw := NewMockResponseWriter(ctrl) - req := NewMockAuthorizeRequester(ctrl) - defer ctrl.Finish() - var urls = []string{ "https://foobar.com/", "https://foobar.com/?foo=bar", @@ -55,28 +52,29 @@ func TestWriteAuthorizeError(t *testing.T) { purls = append(purls, purl) } - oauth2 := &Fosite{} header := http.Header{} for k, c := range []struct { err error - mock func() - checkHeader func(int) + debug bool + mock func(*MockResponseWriter, *MockAuthorizeRequester) + checkHeader func(*testing.T, int) }{ { err: ErrInvalidGrant, - mock: func() { + mock: func(rw *MockResponseWriter, req *MockAuthorizeRequester) { req.EXPECT().IsRedirectURIValid().Return(false) rw.EXPECT().Header().Return(header) rw.EXPECT().WriteHeader(http.StatusBadRequest) rw.EXPECT().Write(gomock.Any()) }, - checkHeader: func(k int) { - assert.Equal(t, "application/json", header.Get("Content-Type"), "%d", k) + checkHeader: func(t *testing.T, k int) { + assert.Equal(t, "application/json", header.Get("Content-Type")) }, }, { - err: ErrInvalidRequest, - mock: func() { + debug: true, + err: ErrInvalidRequest.WithDebug("with-debug"), + mock: func(rw *MockResponseWriter, req *MockAuthorizeRequester) { req.EXPECT().IsRedirectURIValid().Return(true) req.EXPECT().GetRedirectURI().Return(copyUrl(purls[0])) req.EXPECT().GetState().Return("foostate") @@ -84,15 +82,31 @@ func TestWriteAuthorizeError(t *testing.T) { rw.EXPECT().Header().Return(header) rw.EXPECT().WriteHeader(http.StatusFound) }, - checkHeader: func(k int) { - a, _ := url.Parse("https://foobar.com/?error=invalid_request&error_description=The+request+is+missing+a+required+parameter%2C+includes+an+invalid+parameter+value%2C+includes+a+parameter+more+than+once%2C+or+is+otherwise+malformed&state=foostate") + checkHeader: func(t *testing.T, k int) { + a, _ := url.Parse("https://foobar.com/?error=invalid_request&error_debug=with-debug&error_description=The+request+is+missing+a+required+parameter%2C+includes+an+invalid+parameter+value%2C+includes+a+parameter+more+than+once%2C+or+is+otherwise+malformed&error_hint=Make+sure+that+the+various+parameters+are+correct%2C+be+aware+of+case+sensitivity+and+trim+your+parameters.+Make+sure+that+the+client+you+are+using+has+exactly+whitelisted+the+redirect_uri+you+specified.&state=foostate") b, _ := url.Parse(header.Get("Location")) - assert.Equal(t, a, b, "%d", k) + assert.Equal(t, a, b) + }, + }, + { + err: ErrInvalidRequest.WithDebug("with-debug"), + mock: func(rw *MockResponseWriter, req *MockAuthorizeRequester) { + req.EXPECT().IsRedirectURIValid().Return(true) + req.EXPECT().GetRedirectURI().Return(copyUrl(purls[0])) + req.EXPECT().GetState().Return("foostate") + req.EXPECT().GetResponseTypes().MaxTimes(2).Return(Arguments([]string{"code"})) + rw.EXPECT().Header().Return(header) + rw.EXPECT().WriteHeader(http.StatusFound) + }, + checkHeader: func(t *testing.T, k int) { + a, _ := url.Parse("https://foobar.com/?error=invalid_request&error_description=The+request+is+missing+a+required+parameter%2C+includes+an+invalid+parameter+value%2C+includes+a+parameter+more+than+once%2C+or+is+otherwise+malformed&error_hint=Make+sure+that+the+various+parameters+are+correct%2C+be+aware+of+case+sensitivity+and+trim+your+parameters.+Make+sure+that+the+client+you+are+using+has+exactly+whitelisted+the+redirect_uri+you+specified.&state=foostate") + b, _ := url.Parse(header.Get("Location")) + assert.Equal(t, a, b) }, }, { err: ErrInvalidRequest, - mock: func() { + mock: func(rw *MockResponseWriter, req *MockAuthorizeRequester) { req.EXPECT().IsRedirectURIValid().Return(true) req.EXPECT().GetRedirectURI().Return(copyUrl(purls[1])) req.EXPECT().GetState().Return("foostate") @@ -100,15 +114,15 @@ func TestWriteAuthorizeError(t *testing.T) { rw.EXPECT().Header().Return(header) rw.EXPECT().WriteHeader(http.StatusFound) }, - checkHeader: func(k int) { - a, _ := url.Parse("https://foobar.com/?error=invalid_request&error_description=The+request+is+missing+a+required+parameter%2C+includes+an+invalid+parameter+value%2C+includes+a+parameter+more+than+once%2C+or+is+otherwise+malformed&foo=bar&state=foostate") + checkHeader: func(t *testing.T, k int) { + a, _ := url.Parse("https://foobar.com/?error=invalid_request&error_description=The+request+is+missing+a+required+parameter%2C+includes+an+invalid+parameter+value%2C+includes+a+parameter+more+than+once%2C+or+is+otherwise+malformed&error_hint=Make+sure+that+the+various+parameters+are+correct%2C+be+aware+of+case+sensitivity+and+trim+your+parameters.+Make+sure+that+the+client+you+are+using+has+exactly+whitelisted+the+redirect_uri+you+specified.&foo=bar&state=foostate") b, _ := url.Parse(header.Get("Location")) - assert.Equal(t, a, b, "%d", k) + assert.Equal(t, a, b) }, }, { err: ErrInvalidRequest, - mock: func() { + mock: func(rw *MockResponseWriter, req *MockAuthorizeRequester) { req.EXPECT().IsRedirectURIValid().Return(true) req.EXPECT().GetRedirectURI().Return(copyUrl(purls[0])) req.EXPECT().GetState().Return("foostate") @@ -116,16 +130,16 @@ func TestWriteAuthorizeError(t *testing.T) { rw.EXPECT().Header().Return(header) rw.EXPECT().WriteHeader(http.StatusFound) }, - checkHeader: func(k int) { + checkHeader: func(t *testing.T, k int) { a, _ := url.Parse("https://foobar.com/") - a.Fragment = "error=invalid_request&error_description=The+request+is+missing+a+required+parameter%2C+includes+an+invalid+parameter+value%2C+includes+a+parameter+more+than+once%2C+or+is+otherwise+malformed&state=foostate" + a.Fragment = "error=invalid_request&error_description=The+request+is+missing+a+required+parameter%2C+includes+an+invalid+parameter+value%2C+includes+a+parameter+more+than+once%2C+or+is+otherwise+malformed&error_hint=Make+sure+that+the+various+parameters+are+correct%2C+be+aware+of+case+sensitivity+and+trim+your+parameters.+Make+sure+that+the+client+you+are+using+has+exactly+whitelisted+the+redirect_uri+you+specified.&state=foostate" b, _ := url.Parse(header.Get("Location")) - assert.Equal(t, a, b, "%d", k) + assert.Equal(t, a, b) }, }, { err: ErrInvalidRequest, - mock: func() { + mock: func(rw *MockResponseWriter, req *MockAuthorizeRequester) { req.EXPECT().IsRedirectURIValid().Return(true) req.EXPECT().GetRedirectURI().Return(copyUrl(purls[1])) req.EXPECT().GetState().Return("foostate") @@ -133,16 +147,16 @@ func TestWriteAuthorizeError(t *testing.T) { rw.EXPECT().Header().Return(header) rw.EXPECT().WriteHeader(http.StatusFound) }, - checkHeader: func(k int) { + checkHeader: func(t *testing.T, k int) { a, _ := url.Parse("https://foobar.com/?foo=bar") - a.Fragment = "error=invalid_request&error_description=The+request+is+missing+a+required+parameter%2C+includes+an+invalid+parameter+value%2C+includes+a+parameter+more+than+once%2C+or+is+otherwise+malformed&state=foostate" + a.Fragment = "error=invalid_request&error_description=The+request+is+missing+a+required+parameter%2C+includes+an+invalid+parameter+value%2C+includes+a+parameter+more+than+once%2C+or+is+otherwise+malformed&error_hint=Make+sure+that+the+various+parameters+are+correct%2C+be+aware+of+case+sensitivity+and+trim+your+parameters.+Make+sure+that+the+client+you+are+using+has+exactly+whitelisted+the+redirect_uri+you+specified.&state=foostate" b, _ := url.Parse(header.Get("Location")) - assert.Equal(t, a.String(), b.String(), "%d", k) + assert.Equal(t, a.String(), b.String()) }, }, { err: ErrInvalidRequest, - mock: func() { + mock: func(rw *MockResponseWriter, req *MockAuthorizeRequester) { req.EXPECT().IsRedirectURIValid().Return(true) req.EXPECT().GetRedirectURI().Return(copyUrl(purls[0])) req.EXPECT().GetState().Return("foostate") @@ -150,16 +164,16 @@ func TestWriteAuthorizeError(t *testing.T) { rw.EXPECT().Header().Return(header) rw.EXPECT().WriteHeader(http.StatusFound) }, - checkHeader: func(k int) { + checkHeader: func(t *testing.T, k int) { a, _ := url.Parse("https://foobar.com/") - a.Fragment = "error=invalid_request&error_description=The+request+is+missing+a+required+parameter%2C+includes+an+invalid+parameter+value%2C+includes+a+parameter+more+than+once%2C+or+is+otherwise+malformed&state=foostate" + a.Fragment = "error=invalid_request&error_description=The+request+is+missing+a+required+parameter%2C+includes+an+invalid+parameter+value%2C+includes+a+parameter+more+than+once%2C+or+is+otherwise+malformed&error_hint=Make+sure+that+the+various+parameters+are+correct%2C+be+aware+of+case+sensitivity+and+trim+your+parameters.+Make+sure+that+the+client+you+are+using+has+exactly+whitelisted+the+redirect_uri+you+specified.&state=foostate" b, _ := url.Parse(header.Get("Location")) - assert.Equal(t, a, b, "%d", k) + assert.Equal(t, a, b) }, }, { - err: ErrInvalidRequest, - mock: func() { + err: ErrInvalidRequest.WithDebug("with-debug"), + mock: func(rw *MockResponseWriter, req *MockAuthorizeRequester) { req.EXPECT().IsRedirectURIValid().Return(true) req.EXPECT().GetRedirectURI().Return(copyUrl(purls[1])) req.EXPECT().GetState().Return("foostate") @@ -167,23 +181,51 @@ func TestWriteAuthorizeError(t *testing.T) { rw.EXPECT().Header().Return(header) rw.EXPECT().WriteHeader(http.StatusFound) }, - checkHeader: func(k int) { + checkHeader: func(t *testing.T, k int) { a, _ := url.Parse("https://foobar.com/?foo=bar") - a.Fragment = "error=invalid_request&error_description=The+request+is+missing+a+required+parameter%2C+includes+an+invalid+parameter+value%2C+includes+a+parameter+more+than+once%2C+or+is+otherwise+malformed&state=foostate" + a.Fragment = "error=invalid_request&error_description=The+request+is+missing+a+required+parameter%2C+includes+an+invalid+parameter+value%2C+includes+a+parameter+more+than+once%2C+or+is+otherwise+malformed&error_hint=Make+sure+that+the+various+parameters+are+correct%2C+be+aware+of+case+sensitivity+and+trim+your+parameters.+Make+sure+that+the+client+you+are+using+has+exactly+whitelisted+the+redirect_uri+you+specified.&state=foostate" b, _ := url.Parse(header.Get("Location")) - assert.Equal(t, a.String(), b.String(), "%d", k) + assert.Equal(t, a.String(), b.String()) + }, + }, + { + debug: true, + err: ErrInvalidRequest.WithDebug("with-debug"), + mock: func(rw *MockResponseWriter, req *MockAuthorizeRequester) { + req.EXPECT().IsRedirectURIValid().Return(true) + req.EXPECT().GetRedirectURI().Return(copyUrl(purls[1])) + req.EXPECT().GetState().Return("foostate") + req.EXPECT().GetResponseTypes().MaxTimes(2).Return(Arguments([]string{"code", "token"})) + rw.EXPECT().Header().Return(header) + rw.EXPECT().WriteHeader(http.StatusFound) + }, + checkHeader: func(t *testing.T, k int) { + a, _ := url.Parse("https://foobar.com/?foo=bar") + a.Fragment = "error=invalid_request&error_debug=with-debug&error_description=The+request+is+missing+a+required+parameter%2C+includes+an+invalid+parameter+value%2C+includes+a+parameter+more+than+once%2C+or+is+otherwise+malformed&error_hint=Make+sure+that+the+various+parameters+are+correct%2C+be+aware+of+case+sensitivity+and+trim+your+parameters.+Make+sure+that+the+client+you+are+using+has+exactly+whitelisted+the+redirect_uri+you+specified.&state=foostate" + b, _ := url.Parse(header.Get("Location")) + assert.Equal(t, a.String(), b.String()) }, }, } { - c.mock() - oauth2.WriteAuthorizeError(rw, req, c.err) - c.checkHeader(k) - header = http.Header{} - t.Logf("Passed test case %d", k) + t.Run(fmt.Sprintf("case=%d", k), func(t *testing.T) { + oauth2 := &Fosite{ + SendDebugMessagesToClients: c.debug, + } + + ctrl := gomock.NewController(t) + defer ctrl.Finish() + rw := NewMockResponseWriter(ctrl) + req := NewMockAuthorizeRequester(ctrl) + + c.mock(rw, req) + oauth2.WriteAuthorizeError(rw, req, c.err) + c.checkHeader(t, k) + header = http.Header{} + }) } } func copyUrl(u *url.URL) *url.URL { - url, _ := url.Parse(u.String()) - return url + u2, _ := url.Parse(u.String()) + return u2 } diff --git a/errors.go b/errors.go index 70e24e62..224d2017 100644 --- a/errors.go +++ b/errors.go @@ -218,9 +218,9 @@ func ErrorToRFC6749Error(err error) *RFC6749Error { type RFC6749Error struct { Name string `json:"error"` Description string `json:"error_description"` - Hint string `json:"-"` - Code int `json:"statusCode"` - Debug string `json:"-"` + Hint string `json:"error_hint,omitempty"` + Code int `json:"status_code,omitempty"` + Debug string `json:"error_debug,omitempty"` } func (e *RFC6749Error) Status() string { diff --git a/fosite.go b/fosite.go index ccc91381..bb5c3c6f 100644 --- a/fosite.go +++ b/fosite.go @@ -83,4 +83,9 @@ type Fosite struct { RevocationHandlers RevocationHandlers Hasher Hasher ScopeStrategy ScopeStrategy + + // SendDebugMessagesToClients if set to true, includes error debug messages in response payloads. Be aware that sensitive + // data may be exposed, depending on your implementation of Fosite. Such sensitive data might include database error + // codes or other information. Proceed with caution! + SendDebugMessagesToClients bool } diff --git a/introspection_response_writer.go b/introspection_response_writer.go index 1d937511..ebaceb44 100644 --- a/introspection_response_writer.go +++ b/introspection_response_writer.go @@ -50,7 +50,7 @@ func (f *Fosite) WriteIntrospectionError(rw http.ResponseWriter, err error) { switch errors.Cause(err) { case ErrInvalidRequest, ErrRequestUnauthorized: - writeJsonError(rw, err) + f.writeJsonError(rw, err) return } From 1ef3041c4da40d27ea25d56710e59d5f9352df5f Mon Sep 17 00:00:00 2001 From: Aeneas Date: Sat, 23 Dec 2017 22:02:18 +0100 Subject: [PATCH 35/35] compose: Makes SendDebugMessages first class citizen (#243) --- compose/compose.go | 1 + compose/config.go | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/compose/compose.go b/compose/compose.go index 75d233df..49dd2c04 100644 --- a/compose/compose.go +++ b/compose/compose.go @@ -56,6 +56,7 @@ func Compose(config *Config, storage interface{}, strategy interface{}, hasher f RevocationHandlers: fosite.RevocationHandlers{}, Hasher: hasher, ScopeStrategy: config.GetScopeStrategy(), + SendDebugMessagesToClients: config.SendDebugMessagesToClients, } for _, factory := range factories { diff --git a/compose/config.go b/compose/config.go index 1d7c6399..7ef4389f 100644 --- a/compose/config.go +++ b/compose/config.go @@ -36,6 +36,12 @@ type Config struct { // DisableRefreshTokenValidation sets the introspection endpoint to disable refresh token validation. DisableRefreshTokenValidation bool + // SendDebugMessagesToClients if set to true, includes error debug messages in response payloads. Be aware that sensitive + // data may be exposed, depending on your implementation of Fosite. Such sensitive data might include database error + // codes or other information. Proceed with caution! + SendDebugMessagesToClients bool + + // ScopeStrategy sets the scope strategy that should be supported, for example fosite.WildcardScopeStrategy. ScopeStrategy fosite.ScopeStrategy }