Skip to content

Commit 9d855bd

Browse files
zeripathtechknowlogicklafriks
authored
Simplify Gothic to use our session store instead of creating a different store (#17507)
* Simplify Gothic to use our session store instead of creating a different store We have been using xormstore to provide a separate session store for our OAuth2 logins however, this relies on using gorilla context and some doubling of our session storing. We can however, simplify and simply use our own chi-based session store. Thus removing a cookie and some of the weirdness with missing contexts. Signed-off-by: Andrew Thornton <[email protected]> * as per review Signed-off-by: Andrew Thornton <[email protected]> * as per review Signed-off-by: Andrew Thornton <[email protected]> * Handle MaxTokenLength Signed-off-by: Andrew Thornton <[email protected]> * oops Signed-off-by: Andrew Thornton <[email protected]> Co-authored-by: techknowlogick <[email protected]> Co-authored-by: Lauris BH <[email protected]>
1 parent 95da01c commit 9d855bd

File tree

25 files changed

+110
-934
lines changed

25 files changed

+110
-934
lines changed

cmd/web.go

+7-8
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@ import (
1919
"code.gitea.io/gitea/routers"
2020
"code.gitea.io/gitea/routers/install"
2121

22-
context2 "github.com/gorilla/context"
2322
"github.com/urfave/cli"
2423
ini "gopkg.in/ini.v1"
2524
)
@@ -71,7 +70,7 @@ func runHTTPRedirector() {
7170
http.Redirect(w, r, target, http.StatusTemporaryRedirect)
7271
})
7372

74-
var err = runHTTP("tcp", source, "HTTP Redirector", context2.ClearHandler(handler))
73+
var err = runHTTP("tcp", source, "HTTP Redirector", handler)
7574

7675
if err != nil {
7776
log.Fatal("Failed to start port redirection: %v", err)
@@ -209,10 +208,10 @@ func listen(m http.Handler, handleRedirector bool) error {
209208
if handleRedirector {
210209
NoHTTPRedirector()
211210
}
212-
err = runHTTP("tcp", listenAddr, "Web", context2.ClearHandler(m))
211+
err = runHTTP("tcp", listenAddr, "Web", m)
213212
case setting.HTTPS:
214213
if setting.EnableLetsEncrypt {
215-
err = runLetsEncrypt(listenAddr, setting.Domain, setting.LetsEncryptDirectory, setting.LetsEncryptEmail, context2.ClearHandler(m))
214+
err = runLetsEncrypt(listenAddr, setting.Domain, setting.LetsEncryptDirectory, setting.LetsEncryptEmail, m)
216215
break
217216
}
218217
if handleRedirector {
@@ -222,22 +221,22 @@ func listen(m http.Handler, handleRedirector bool) error {
222221
NoHTTPRedirector()
223222
}
224223
}
225-
err = runHTTPS("tcp", listenAddr, "Web", setting.CertFile, setting.KeyFile, context2.ClearHandler(m))
224+
err = runHTTPS("tcp", listenAddr, "Web", setting.CertFile, setting.KeyFile, m)
226225
case setting.FCGI:
227226
if handleRedirector {
228227
NoHTTPRedirector()
229228
}
230-
err = runFCGI("tcp", listenAddr, "FCGI Web", context2.ClearHandler(m))
229+
err = runFCGI("tcp", listenAddr, "FCGI Web", m)
231230
case setting.UnixSocket:
232231
if handleRedirector {
233232
NoHTTPRedirector()
234233
}
235-
err = runHTTP("unix", listenAddr, "Web", context2.ClearHandler(m))
234+
err = runHTTP("unix", listenAddr, "Web", m)
236235
case setting.FCGIUnix:
237236
if handleRedirector {
238237
NoHTTPRedirector()
239238
}
240-
err = runFCGI("unix", listenAddr, "Web", context2.ClearHandler(m))
239+
err = runFCGI("unix", listenAddr, "Web", m)
241240
default:
242241
log.Fatal("Invalid protocol: %s", setting.Protocol)
243242
}

cmd/web_letsencrypt.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ import (
1313
"code.gitea.io/gitea/modules/setting"
1414

1515
"github.com/caddyserver/certmagic"
16-
context2 "github.com/gorilla/context"
1716
)
1817

1918
func runLetsEncrypt(listenAddr, domain, directory, email string, m http.Handler) error {
@@ -67,7 +66,7 @@ func runLetsEncrypt(listenAddr, domain, directory, email string, m http.Handler)
6766
}()
6867
}
6968

70-
return runHTTPSWithTLSConfig("tcp", listenAddr, "Web", tlsConfig, context2.ClearHandler(m))
69+
return runHTTPSWithTLSConfig("tcp", listenAddr, "Web", tlsConfig, m)
7170
}
7271

7372
func runLetsEncryptFallbackHandler(w http.ResponseWriter, r *http.Request) {

contrib/pr/checkout.go

+1-2
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,6 @@ import (
3636
"github.com/go-git/go-git/v5"
3737
"github.com/go-git/go-git/v5/config"
3838
"github.com/go-git/go-git/v5/plumbing"
39-
context2 "github.com/gorilla/context"
4039
"xorm.io/xorm"
4140
)
4241

@@ -138,7 +137,7 @@ func runPR() {
138137
*/
139138

140139
//Start the server
141-
http.ListenAndServe(":8080", context2.ClearHandler(c))
140+
http.ListenAndServe(":8080", c)
142141

143142
log.Printf("[PR] Cleaning up ...\n")
144143
/*

go.mod

+1-3
Original file line numberDiff line numberDiff line change
@@ -55,10 +55,9 @@ require (
5555
github.com/golang/snappy v0.0.4 // indirect
5656
github.com/google/go-github/v39 v39.2.0
5757
github.com/google/uuid v1.2.0
58-
github.com/gorilla/context v1.1.1
5958
github.com/gorilla/feeds v1.1.1
6059
github.com/gorilla/mux v1.8.0 // indirect
61-
github.com/gorilla/sessions v1.2.1 // indirect
60+
github.com/gorilla/sessions v1.2.1
6261
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
6362
github.com/hashicorp/go-retryablehttp v0.7.0 // indirect
6463
github.com/hashicorp/go-version v1.3.1
@@ -73,7 +72,6 @@ require (
7372
github.com/klauspost/compress v1.13.1
7473
github.com/klauspost/cpuid/v2 v2.0.9 // indirect
7574
github.com/klauspost/pgzip v1.2.5 // indirect
76-
github.com/lafriks/xormstore v1.4.0
7775
github.com/lib/pq v1.10.2
7876
github.com/lunny/dingtalk_webhook v0.0.0-20171025031554-e3534c89ef96
7977
github.com/markbates/goth v1.68.0

go.sum

-9
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,6 @@ github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAE
7373
github.com/ProtonMail/go-crypto v0.0.0-20210428141323-04723f9f07d7/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
7474
github.com/ProtonMail/go-crypto v0.0.0-20210705153151-cc34b1f6908b h1:BF5p87XWvmgdrTPPzcRMwC0TMQbviwQ+uBKfNfWJy50=
7575
github.com/ProtonMail/go-crypto v0.0.0-20210705153151-cc34b1f6908b/go.mod h1:z4/9nQmJSSwwds7ejkxaJwO37dru3geImFUdJlaLzQo=
76-
github.com/PuerkitoBio/goquery v1.5.1/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
7776
github.com/PuerkitoBio/goquery v1.7.0 h1:O5SP3b9JWqMSVMG69zMfj577zwkSNpxrFf7ybS74eiw=
7877
github.com/PuerkitoBio/goquery v1.7.0/go.mod h1:GsLWisAFVj4WgDibEWF4pvYnkVQBpKBKeU+7zCJoLcc=
7978
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
@@ -256,7 +255,6 @@ github.com/danwakefield/fnmatch v0.0.0-20160403171240-cbb64ac3d964/go.mod h1:Xd9
256255
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
257256
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
258257
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
259-
github.com/denisenkom/go-mssqldb v0.0.0-20200428022330-06a60b6afbbc/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
260258
github.com/denisenkom/go-mssqldb v0.10.0 h1:QykgLZBorFE95+gO3u9esLd0BmbvpWp0/waNNZfHBM8=
261259
github.com/denisenkom/go-mssqldb v0.10.0/go.mod h1:xbL0rPBG9cCiLr28tMa8zpbdarY27NDyej4t/EjAShU=
262260
github.com/dgrijalva/jwt-go v3.2.0+incompatible/go.mod h1:E3ru+11k8xSBh+hMPgOLZmtrrCbhqsmaPHjLKYnJCaQ=
@@ -801,14 +799,11 @@ github.com/kr/pty v1.1.8/go.mod h1:O1sed60cT9XZ5uDucP5qwvh+TE3NnUj51EiZO/lmSfw=
801799
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
802800
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
803801
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
804-
github.com/lafriks/xormstore v1.4.0 h1:DX1yS9WUhVY+MTHGaOJ2tDVpwL1w/247iro5KR0BQEQ=
805-
github.com/lafriks/xormstore v1.4.0/go.mod h1:5a3wJ6Ro0TFJmJcH1ywtHO/fBEIWYfSfO4WTYmM7qEk=
806802
github.com/lestrrat-go/jwx v0.9.0/go.mod h1:iEoxlYfZjvoGpuWwxUz+eR5e6KTJGsaRcy/YNA/UnBk=
807803
github.com/lib/pq v1.0.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
808804
github.com/lib/pq v1.1.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
809805
github.com/lib/pq v1.2.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
810806
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
811-
github.com/lib/pq v1.7.0/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
812807
github.com/lib/pq v1.10.2 h1:AqzbZs4ZoCBp+GtejcpCpcxM3zlSMx29dXbUSeVtJb8=
813808
github.com/lib/pq v1.10.2/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
814809
github.com/libdns/libdns v0.2.1 h1:Wu59T7wSHRgtA0cfxC+n1c/e+O3upJGWytknkmFEDis=
@@ -858,7 +853,6 @@ github.com/mattn/go-runewidth v0.0.9/go.mod h1:H031xJmbD/WCDINGzjvQ9THkh0rPKHF+m
858853
github.com/mattn/go-runewidth v0.0.13 h1:lTGmDsbAYt5DmK6OnoV7EuIF1wEIFAcxld6ypU4OSgU=
859854
github.com/mattn/go-runewidth v0.0.13/go.mod h1:Jdepj2loyihRzMpdS35Xk/zdY8IAYHsh153qUoGf23w=
860855
github.com/mattn/go-sqlite3 v1.11.0/go.mod h1:FPy6KqzDD04eiIsT53CuJW3U88zkxoIYsOqkbpncsNc=
861-
github.com/mattn/go-sqlite3 v1.14.0/go.mod h1:JIl7NbARA7phWnGvh0LKTyg7S9BA+6gx71ShQilpsus=
862856
github.com/mattn/go-sqlite3 v1.14.6/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
863857
github.com/mattn/go-sqlite3 v1.14.7/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
864858
github.com/mattn/go-sqlite3 v1.14.8 h1:gDp86IdQsN/xWjIEmr9MF6o9mpksUgh0fu+9ByFxzIU=
@@ -1260,7 +1254,6 @@ golang.org/x/crypto v0.0.0-20190617133340-57b3e21c3d56/go.mod h1:yigFU9vqHzYiE8U
12601254
golang.org/x/crypto v0.0.0-20190701094942-4def268fd1a4/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
12611255
golang.org/x/crypto v0.0.0-20190820162420-60c769a6c586/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
12621256
golang.org/x/crypto v0.0.0-20190911031432-227b76d455e7/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
1263-
golang.org/x/crypto v0.0.0-20190927123631-a832865fa7ad/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
12641257
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
12651258
golang.org/x/crypto v0.0.0-20200302210943-78000ba7a073/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
12661259
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
@@ -1761,9 +1754,7 @@ sigs.k8s.io/yaml v1.1.0/go.mod h1:UJmg0vDUVViEyp3mgSv9WPwZCDxu4rQW1olrI1uml+o=
17611754
sourcegraph.com/sourcegraph/appdash v0.0.0-20190731080439-ebfcffb1b5c0/go.mod h1:hI742Nqp5OhwiqlzhgfbWU4mW4yO10fP+LoT9WOswdU=
17621755
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251 h1:mUcz5b3FJbP5Cvdq7Khzn6J9OCUQJaBwgBkCR+MOwSs=
17631756
strk.kbt.io/projects/go/libravatar v0.0.0-20191008002943-06d1c002b251/go.mod h1:FJGmPh3vz9jSos1L/F91iAgnC/aejc0wIIrF2ZwJxdY=
1764-
xorm.io/builder v0.3.7/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
17651757
xorm.io/builder v0.3.9 h1:Sd65/LdWyO7LR8+Cbd+e7mm3sK/7U9k0jS3999IDHMc=
17661758
xorm.io/builder v0.3.9/go.mod h1:aUW0S9eb9VCaPohFCH3j7czOx1PMW3i1HrSzbLYGBSE=
1767-
xorm.io/xorm v1.0.6/go.mod h1:uF9EtbhODq5kNWxMbnBEj8hRRZnlcNSz2t2N7HW/+A4=
17681759
xorm.io/xorm v1.2.5 h1:tqN7OhN8P9xi52qBb76I8m5maAJMz/SSbgK2RGPCPbo=
17691760
xorm.io/xorm v1.2.5/go.mod h1:fTG8tSjk6O1BYxwuohZUK+S1glnRycsCF05L1qQyEU0=

models/db/store.go

-18
This file was deleted.

models/login/session.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ import (
1414
// Session represents a session compatible for go-chi session
1515
type Session struct {
1616
Key string `xorm:"pk CHAR(16)"` // has to be Key to match with go-chi/session
17-
Data []byte `xorm:"BLOB"`
17+
Data []byte `xorm:"BLOB"` // on MySQL this has a maximum size of 64Kb - this may need to be increased
1818
Expiry timeutil.TimeStamp // has to be Expiry to match with go-chi/session
1919
}
2020

routers/web/user/auth.go

+1-1
Original file line numberDiff line numberDiff line change
@@ -789,7 +789,7 @@ func handleOAuth2SignIn(ctx *context.Context, source *login.Source, u *models.Us
789789
func oAuth2UserLoginCallback(loginSource *login.Source, request *http.Request, response http.ResponseWriter) (*models.User, goth.User, error) {
790790
gothUser, err := loginSource.Cfg.(*oauth2.Source).Callback(request, response)
791791
if err != nil {
792-
if err.Error() == "securecookie: the value is too long" {
792+
if err.Error() == "securecookie: the value is too long" || strings.Contains(err.Error(), "Data too long") {
793793
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)
794794
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)
795795
}

services/auth/source/oauth2/init.go

+7-18
Original file line numberDiff line numberDiff line change
@@ -5,23 +5,21 @@
55
package oauth2
66

77
import (
8+
"encoding/gob"
89
"net/http"
910
"sync"
1011

11-
"code.gitea.io/gitea/models/db"
1212
"code.gitea.io/gitea/models/login"
1313
"code.gitea.io/gitea/modules/log"
1414
"code.gitea.io/gitea/modules/setting"
1515

1616
"github.com/google/uuid"
17+
"github.com/gorilla/sessions"
1718
"github.com/markbates/goth/gothic"
1819
)
1920

2021
var gothRWMutex = sync.RWMutex{}
2122

22-
// SessionTableName is the table name that OAuth2 will use to store things
23-
const SessionTableName = "oauth2_session"
24-
2523
// UsersStoreKey is the key for the store
2624
const UsersStoreKey = "gitea-oauth2-sessions"
2725

@@ -34,23 +32,14 @@ func Init() error {
3432
return err
3533
}
3634

37-
store, err := db.CreateStore(SessionTableName, UsersStoreKey)
38-
if err != nil {
39-
return err
40-
}
41-
42-
// according to the Goth lib:
43-
// set the maxLength of the cookies stored on the disk to a larger number to prevent issues with:
44-
// securecookie: the value is too long
45-
// when using OpenID Connect , since this can contain a large amount of extra information in the id_token
46-
47-
// Note, when using the FilesystemStore only the session.ID is written to a browser cookie, so this is explicit for the storage on disk
48-
store.MaxLength(setting.OAuth2.MaxTokenLength)
49-
5035
// Lock our mutex
5136
gothRWMutex.Lock()
5237

53-
gothic.Store = store
38+
gob.Register(&sessions.Session{})
39+
40+
gothic.Store = &SessionsStore{
41+
maxLength: int64(setting.OAuth2.MaxTokenLength),
42+
}
5443

5544
gothic.SetState = func(req *http.Request) string {
5645
return uuid.New().String()

services/auth/source/oauth2/store.go

+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
// Copyright 2021 The Gitea Authors. All rights reserved.
2+
// Use of this source code is governed by a MIT-style
3+
// license that can be found in the LICENSE file.
4+
5+
package oauth2
6+
7+
import (
8+
"encoding/gob"
9+
"fmt"
10+
"net/http"
11+
12+
"code.gitea.io/gitea/modules/log"
13+
chiSession "gitea.com/go-chi/session"
14+
"github.com/gorilla/sessions"
15+
)
16+
17+
// SessionsStore creates a gothic store from our session
18+
type SessionsStore struct {
19+
maxLength int64
20+
}
21+
22+
// Get should return a cached session.
23+
func (st *SessionsStore) Get(r *http.Request, name string) (*sessions.Session, error) {
24+
return st.getOrNew(r, name, false)
25+
}
26+
27+
// New should create and return a new session.
28+
//
29+
// Note that New should never return a nil session, even in the case of
30+
// an error if using the Registry infrastructure to cache the session.
31+
func (st *SessionsStore) New(r *http.Request, name string) (*sessions.Session, error) {
32+
return st.getOrNew(r, name, true)
33+
}
34+
35+
// getOrNew gets the session from the chi-session if it exists. Override permits the overriding of an unexpected object.
36+
func (st *SessionsStore) getOrNew(r *http.Request, name string, override bool) (*sessions.Session, error) {
37+
chiStore := chiSession.GetSession(r)
38+
39+
session := sessions.NewSession(st, name)
40+
41+
rawData := chiStore.Get(name)
42+
if rawData != nil {
43+
oldSession, ok := rawData.(*sessions.Session)
44+
if ok {
45+
session.ID = oldSession.ID
46+
session.IsNew = oldSession.IsNew
47+
session.Options = oldSession.Options
48+
session.Values = oldSession.Values
49+
50+
return session, nil
51+
} else if !override {
52+
log.Error("Unexpected object in session at name: %s: %v", name, rawData)
53+
return nil, fmt.Errorf("unexpected object in session at name: %s", name)
54+
}
55+
}
56+
57+
session.ID = chiStore.ID() // Simply copy the session id from the chi store
58+
59+
return session, chiStore.Set(name, session)
60+
}
61+
62+
// Save should persist session to the underlying store implementation.
63+
func (st *SessionsStore) Save(r *http.Request, w http.ResponseWriter, session *sessions.Session) error {
64+
chiStore := chiSession.GetSession(r)
65+
66+
if err := chiStore.Set(session.Name(), session); err != nil {
67+
return err
68+
}
69+
70+
if st.maxLength > 0 {
71+
sizeWriter := &sizeWriter{}
72+
73+
_ = gob.NewEncoder(sizeWriter).Encode(session)
74+
if sizeWriter.size > st.maxLength {
75+
return fmt.Errorf("encode session: Data too long: %d > %d", sizeWriter.size, st.maxLength)
76+
}
77+
}
78+
79+
return chiStore.Release()
80+
}
81+
82+
type sizeWriter struct {
83+
size int64
84+
}
85+
86+
func (s *sizeWriter) Write(data []byte) (int, error) {
87+
s.size += int64(len(data))
88+
return len(data), nil
89+
}
90+
91+
var _ (sessions.Store) = &SessionsStore{}

vendor/github.com/gorilla/context/.travis.yml

-19
This file was deleted.

vendor/github.com/gorilla/context/LICENSE

-27
This file was deleted.

0 commit comments

Comments
 (0)