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 <art27@cantab.net>

Co-authored-by: techknowlogick <techknowlogick@gitea.io>
This commit is contained in:
zeripath 2020-04-22 23:47:23 +01:00 committed by GitHub
parent b51fd30522
commit e74c4e1be9
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
5 changed files with 12 additions and 3 deletions

View file

@ -916,6 +916,8 @@ REFRESH_TOKEN_EXPIRATION_TIME=730
INVALIDATE_REFRESH_TOKENS=false INVALIDATE_REFRESH_TOKENS=false
; OAuth2 authentication secret for access and refresh tokens, change this to a unique string. ; OAuth2 authentication secret for access and refresh tokens, change this to a unique string.
JWT_SECRET=Bk0yK7Y9g_p56v86KaHqjSbxvNvu3SbKoOdOt2ZcXvU JWT_SECRET=Bk0yK7Y9g_p56v86KaHqjSbxvNvu3SbKoOdOt2ZcXvU
; Maximum length of oauth2 token/cookie stored on server
MAX_TOKEN_LENGTH=32767
[i18n] [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 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

View file

@ -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 - `REFRESH_TOKEN_EXPIRATION_TIME`: **730**: Lifetime of an OAuth2 access token in hours
- `INVALIDATE_REFRESH_TOKEN`: **false**: Check if refresh token got already used - `INVALIDATE_REFRESH_TOKEN`: **false**: Check if refresh token got already used
- `JWT_SECRET`: **\<empty\>**: OAuth2 authentication secret for access and refresh tokens, change this a unique string. - `JWT_SECRET`: **\<empty\>**: 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`) ## i18n (`i18n`)

View file

@ -5,7 +5,6 @@
package oauth2 package oauth2
import ( import (
"math"
"net/http" "net/http"
"code.gitea.io/gitea/modules/log" "code.gitea.io/gitea/modules/log"
@ -26,7 +25,7 @@ import (
"github.com/markbates/goth/providers/openidConnect" "github.com/markbates/goth/providers/openidConnect"
"github.com/markbates/goth/providers/twitter" "github.com/markbates/goth/providers/twitter"
"github.com/markbates/goth/providers/yandex" "github.com/markbates/goth/providers/yandex"
"github.com/satori/go.uuid" uuid "github.com/satori/go.uuid"
"xorm.io/xorm" "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 // 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 // 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.Store = store
gothic.SetState = func(req *http.Request) string { gothic.SetState = func(req *http.Request) string {

View file

@ -10,6 +10,7 @@ import (
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"math"
"net" "net"
"net/url" "net/url"
"os" "os"
@ -323,11 +324,13 @@ var (
InvalidateRefreshTokens bool InvalidateRefreshTokens bool
JWTSecretBytes []byte `ini:"-"` JWTSecretBytes []byte `ini:"-"`
JWTSecretBase64 string `ini:"JWT_SECRET"` JWTSecretBase64 string `ini:"JWT_SECRET"`
MaxTokenLength int
}{ }{
Enable: true, Enable: true,
AccessTokenExpirationTime: 3600, AccessTokenExpirationTime: 3600,
RefreshTokenExpirationTime: 730, RefreshTokenExpirationTime: 730,
InvalidateRefreshTokens: false, InvalidateRefreshTokens: false,
MaxTokenLength: math.MaxInt16,
} }
U2F = struct { U2F = struct {

View file

@ -670,6 +670,10 @@ func oAuth2UserLoginCallback(loginSource *models.LoginSource, request *http.Requ
gothUser, err := oauth2.ProviderCallback(loginSource.Name, request, response) gothUser, err := oauth2.ProviderCallback(loginSource.Name, request, response)
if err != nil { 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 return nil, goth.User{}, err
} }