From b28d1787fceca15cbf2e8d5a3658feab5f28bee6 Mon Sep 17 00:00:00 2001
From: Bolke de Bruin <bolke@xs4all.nl>
Date: Thu, 11 Aug 2022 12:29:52 +0200
Subject: [PATCH] Allow filesystemstore for sessions (#15)

AD and other IdPs can provide long lists of group
membership. This can lead to securecookie too big
as this cannot always be stored inside a HTTP header.
Filesystem session storage removes this limitions at the
cost of not being entirely stateless anymore. It is therefore
required that clients can keep state with the rdpgw
instance.
---
 cmd/rdpgw/api/web.go              | 12 ++++++++++--
 cmd/rdpgw/config/configuration.go |  3 +++
 cmd/rdpgw/main.go                 |  1 +
 3 files changed, 14 insertions(+), 2 deletions(-)

diff --git a/cmd/rdpgw/api/web.go b/cmd/rdpgw/api/web.go
index e7ccd84..ac804e2 100644
--- a/cmd/rdpgw/api/web.go
+++ b/cmd/rdpgw/api/web.go
@@ -13,6 +13,7 @@ import (
 	"log"
 	"math/rand"
 	"net/http"
+	"os"
 	"strconv"
 	"strings"
 	"time"
@@ -29,11 +30,12 @@ type UserTokenGeneratorFunc func(context.Context, string) (string, error)
 type Config struct {
 	SessionKey           []byte
 	SessionEncryptionKey []byte
+	SessionStore		 string
 	PAATokenGenerator    TokenGeneratorFunc
 	UserTokenGenerator   UserTokenGeneratorFunc
 	EnableUserToken      bool
 	OAuth2Config         *oauth2.Config
-	store                *sessions.CookieStore
+	store                sessions.Store
 	OIDCTokenVerifier    *oidc.IDTokenVerifier
 	stateStore           *cache.Cache
 	Hosts                []string
@@ -53,7 +55,13 @@ func (c *Config) NewApi() {
 	if len(c.Hosts) < 1 {
 		log.Fatal("Not enough hosts to connect to specified")
 	}
-	c.store = sessions.NewCookieStore(c.SessionKey, c.SessionEncryptionKey)
+	if c.SessionStore == "file" {
+		log.Println("Filesystem is used as session storage")
+		c.store = sessions.NewFilesystemStore(os.TempDir(), c.SessionKey, c.SessionEncryptionKey)
+	} else {
+		log.Println("Cookies are used as session storage")
+		c.store = sessions.NewCookieStore(c.SessionKey, c.SessionEncryptionKey)
+	}
 	c.stateStore = cache.New(time.Minute*2, 5*time.Minute)
 }
 
diff --git a/cmd/rdpgw/config/configuration.go b/cmd/rdpgw/config/configuration.go
index f47733e..cb851e3 100644
--- a/cmd/rdpgw/config/configuration.go
+++ b/cmd/rdpgw/config/configuration.go
@@ -23,6 +23,7 @@ type ServerConfig struct {
 	RoundRobin           bool
 	SessionKey           string
 	SessionEncryptionKey string
+	SessionStore         string
 	SendBuf				 int
 	ReceiveBuf			 int
 }
@@ -72,6 +73,8 @@ func init() {
 	viper.SetDefault("client.bandwidthAutoDetect", 1)
 	viper.SetDefault("security.verifyClientIp", true)
 	viper.SetDefault("server.tlsDisabled",  false)
+	viper.SetDefault("server.sessionStore", "cookie")
+	viper.SetDefault("caps.tokenAuth", true)
 }
 
 func Load(configFile string) Configuration {
diff --git a/cmd/rdpgw/main.go b/cmd/rdpgw/main.go
index 1736a8f..9f8510b 100644
--- a/cmd/rdpgw/main.go
+++ b/cmd/rdpgw/main.go
@@ -71,6 +71,7 @@ func main() {
 		EnableUserToken:      conf.Security.EnableUserToken,
 		SessionKey:           []byte(conf.Server.SessionKey),
 		SessionEncryptionKey: []byte(conf.Server.SessionEncryptionKey),
+		SessionStore: 		  conf.Server.SessionStore,
 		Hosts:                conf.Server.Hosts,
 		NetworkAutoDetect:    conf.Client.NetworkAutoDetect,
 		UsernameTemplate:     conf.Client.UsernameTemplate,
-- 
GitLab