From e74c4e1be988f2815146338cbce8210e515a937e Mon Sep 17 00:00:00 2001 From: zeripath Date: Wed, 22 Apr 2020 23:47:23 +0100 Subject: [PATCH] Add option to increase provided OAuth2 token maximum size (#11180) Some OAuth2 providers return quite large structured tokens >32767 bytes. Gitea currently has a fixed maximum of 32767 bytes for these and unfortunately due to the convoluted nature of the dependent libraries the error returned is rather opaque. Here we manage the error a little better - detecting the rather opaque github.com/gorilla/securecookie.errEncodedValueTooLong and converting it to a more readable error. Further we provide a configurable option to increase the maximum size of the provided OAuth2 tokens. Fix #9907 Signed-off-by: Andrew Thornton Co-authored-by: techknowlogick --- custom/conf/app.ini.sample | 2 ++ docs/content/doc/advanced/config-cheat-sheet.en-us.md | 1 + modules/auth/oauth2/oauth2.go | 5 ++--- modules/setting/setting.go | 3 +++ routers/user/auth.go | 4 ++++ 5 files changed, 12 insertions(+), 3 deletions(-) diff --git a/custom/conf/app.ini.sample b/custom/conf/app.ini.sample index 414cd3f278..691a65cc53 100644 --- a/custom/conf/app.ini.sample +++ b/custom/conf/app.ini.sample @@ -916,6 +916,8 @@ REFRESH_TOKEN_EXPIRATION_TIME=730 INVALIDATE_REFRESH_TOKENS=false ; OAuth2 authentication secret for access and refresh tokens, change this to a unique string. JWT_SECRET=Bk0yK7Y9g_p56v86KaHqjSbxvNvu3SbKoOdOt2ZcXvU +; Maximum length of oauth2 token/cookie stored on server +MAX_TOKEN_LENGTH=32767 [i18n] LANGS = en-US,zh-CN,zh-HK,zh-TW,de-DE,fr-FR,nl-NL,lv-LV,ru-RU,uk-UA,ja-JP,es-ES,pt-BR,pl-PL,bg-BG,it-IT,fi-FI,tr-TR,cs-CZ,sr-SP,sv-SE,ko-KR diff --git a/docs/content/doc/advanced/config-cheat-sheet.en-us.md b/docs/content/doc/advanced/config-cheat-sheet.en-us.md index 7d59041ec4..fd32bfd161 100644 --- a/docs/content/doc/advanced/config-cheat-sheet.en-us.md +++ b/docs/content/doc/advanced/config-cheat-sheet.en-us.md @@ -587,6 +587,7 @@ NB: You must `REDIRECT_MACARON_LOG` and have `DISABLE_ROUTER_LOG` set to `false` - `REFRESH_TOKEN_EXPIRATION_TIME`: **730**: Lifetime of an OAuth2 access token in hours - `INVALIDATE_REFRESH_TOKEN`: **false**: Check if refresh token got already used - `JWT_SECRET`: **\**: OAuth2 authentication secret for access and refresh tokens, change this a unique string. +- `MAX_TOKEN_LENGTH`: **32767**: Maximum length of token/cookie to accept from OAuth2 provider ## i18n (`i18n`) diff --git a/modules/auth/oauth2/oauth2.go b/modules/auth/oauth2/oauth2.go index 0b18afdaf7..a50c639885 100644 --- a/modules/auth/oauth2/oauth2.go +++ b/modules/auth/oauth2/oauth2.go @@ -5,7 +5,6 @@ package oauth2 import ( - "math" "net/http" "code.gitea.io/gitea/modules/log" @@ -26,7 +25,7 @@ import ( "github.com/markbates/goth/providers/openidConnect" "github.com/markbates/goth/providers/twitter" "github.com/markbates/goth/providers/yandex" - "github.com/satori/go.uuid" + uuid "github.com/satori/go.uuid" "xorm.io/xorm" ) @@ -58,7 +57,7 @@ func Init(x *xorm.Engine) error { // when using OpenID Connect , since this can contain a large amount of extra information in the id_token // Note, when using the FilesystemStore only the session.ID is written to a browser cookie, so this is explicit for the storage on disk - store.MaxLength(math.MaxInt16) + store.MaxLength(setting.OAuth2.MaxTokenLength) gothic.Store = store gothic.SetState = func(req *http.Request) string { diff --git a/modules/setting/setting.go b/modules/setting/setting.go index a18b47a7e9..069a3556da 100644 --- a/modules/setting/setting.go +++ b/modules/setting/setting.go @@ -10,6 +10,7 @@ import ( "fmt" "io" "io/ioutil" + "math" "net" "net/url" "os" @@ -323,11 +324,13 @@ var ( InvalidateRefreshTokens bool JWTSecretBytes []byte `ini:"-"` JWTSecretBase64 string `ini:"JWT_SECRET"` + MaxTokenLength int }{ Enable: true, AccessTokenExpirationTime: 3600, RefreshTokenExpirationTime: 730, InvalidateRefreshTokens: false, + MaxTokenLength: math.MaxInt16, } U2F = struct { diff --git a/routers/user/auth.go b/routers/user/auth.go index 6d762a058c..5ad095b857 100644 --- a/routers/user/auth.go +++ b/routers/user/auth.go @@ -670,6 +670,10 @@ func oAuth2UserLoginCallback(loginSource *models.LoginSource, request *http.Requ gothUser, err := oauth2.ProviderCallback(loginSource.Name, request, response) if err != nil { + if err.Error() == "securecookie: the value is too long" { + log.Error("OAuth2 Provider %s returned too long a token. Current max: %d. Either increase the [OAuth2] MAX_TOKEN_LENGTH or reduce the information returned from the OAuth2 provider", loginSource.Name, setting.OAuth2.MaxTokenLength) + err = fmt.Errorf("OAuth2 Provider %s returned too long a token. Current max: %d. Either increase the [OAuth2] MAX_TOKEN_LENGTH or reduce the information returned from the OAuth2 provider", loginSource.Name, setting.OAuth2.MaxTokenLength) + } return nil, goth.User{}, err }