Skip to content

Commit

Permalink
Merge pull request #2732 from cloudfoundry-incubator/fix-can-not-log-…
Browse files Browse the repository at this point in the history
…out-cookie-domain

Fix issue where cookie domain name change can mean you can't log out
  • Loading branch information
Irfan Habib authored Jul 25, 2018
2 parents ac0e1bb + c31e621 commit e52e458
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 10 deletions.
6 changes: 1 addition & 5 deletions src/backend/app-core/auth.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,6 @@ import (
"fmt"
"net/http"
"net/url"
"regexp"
"strconv"
"strings"
"time"
Expand Down Expand Up @@ -48,9 +47,6 @@ const SessionExpiresOnHeader = "X-Cap-Session-Expires-On"
// ClientRequestDateHeader Custom header for getting date form client
const ClientRequestDateHeader = "X-Cap-Request-Date"

// EmptyCookieMatcher - Used to detect and remove empty Cookies sent by certain browsers
var EmptyCookieMatcher *regexp.Regexp = regexp.MustCompile(portalSessionName + "=(?:;[ ]*|$)")

// XSRFTokenHeader - XSRF Token Header name
const XSRFTokenHeader = "X-Xsrf-Token"

Expand All @@ -68,7 +64,7 @@ func (p *portalProxy) getUAAIdentityEndpoint() string {
func (p *portalProxy) removeEmptyCookie(c echo.Context) {
req := c.Request().(*standard.Request).Request
originalCookie := req.Header.Get("Cookie")
cleanCookie := EmptyCookieMatcher.ReplaceAllLiteralString(originalCookie, "")
cleanCookie := p.EmptyCookieMatcher.ReplaceAllLiteralString(originalCookie, "")
req.Header.Set("Cookie", cleanCookie)
}

Expand Down
20 changes: 20 additions & 0 deletions src/backend/app-core/main.go
Original file line number Diff line number Diff line change
@@ -1,19 +1,22 @@
package main

import (
"crypto/sha1"
"crypto/tls"
"database/sql"
"encoding/gob"
"encoding/hex"
"errors"
"fmt"
"io"
"io/ioutil"
"net"
"net/http"
"os"
"os/signal"
"path"
"path/filepath"
"regexp"
"strings"
"syscall"
"time"
Expand Down Expand Up @@ -323,6 +326,8 @@ func initSessionStore(db *sql.DB, databaseProvider string, pc interfaces.PortalC
domain = ""
}

log.Infof("Session Cookie Domain: %s", domain)

// Store depends on the DB Type
if databaseProvider == datastore.PGSQL {
log.Info("Creating Postgres session store")
Expand Down Expand Up @@ -446,11 +451,26 @@ func detectTLSCert(pc interfaces.PortalConfig) (string, string, error) {

func newPortalProxy(pc interfaces.PortalConfig, dcp *sql.DB, ss HttpSessionStore, sessionStoreOptions *sessions.Options) *portalProxy {
log.Debug("newPortalProxy")

// Generate cookie name - avoids issues if the cookie domain is changed
cookieName := jetstreamSessionName
domain := pc.CookieDomain
if len(domain) > 0 && domain != "-" {
h := sha1.New()
io.WriteString(h, domain)
hash := fmt.Sprintf("%x", h.Sum(nil))
cookieName = fmt.Sprintf("%s-%s", jetstreamSessionName, hash[0:10])
}

log.Infof("Session Cookie name: %s", cookieName)

pp := &portalProxy{
Config: pc,
DatabaseConnectionPool: dcp,
SessionStore: ss,
SessionStoreOptions: sessionStoreOptions,
SessionCookieName: cookieName,
EmptyCookieMatcher: regexp.MustCompile(cookieName + "=(?:;[ ]*|$)"),
}

return pp
Expand Down
3 changes: 3 additions & 0 deletions src/backend/app-core/portal_proxy.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package main

import (
"database/sql"
"regexp"
"time"

"github.com/SUSE/stratos-ui/repository/interfaces"
Expand All @@ -14,6 +15,8 @@ type portalProxy struct {
SessionStore interfaces.SessionStorer
SessionStoreOptions *sessions.Options
Plugins map[string]interfaces.StratosPlugin
SessionCookieName string
EmptyCookieMatcher *regexp.Regexp // Used to detect and remove empty Cookies sent by certain browsers
}

// HttpSessionStore - Interface for a store that can manage HTTP Sessions
Expand Down
11 changes: 6 additions & 5 deletions src/backend/app-core/session.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,8 @@ import (
)

const (
portalSessionName = "console-session"
// Default cookie name/cookie name prefix
jetstreamSessionName = "console-session"
)

// SessionValueNotFound - Error returned when a requested key was not found in the session
Expand All @@ -26,7 +27,7 @@ func (e *SessionValueNotFound) Error() string {
func (p *portalProxy) GetSession(c echo.Context) (*sessions.Session, error) {
log.Debug("getSession")
req := c.Request().(*standard.Request).Request
return p.SessionStore.Get(req, portalSessionName)
return p.SessionStore.Get(req, p.SessionCookieName)
}

func (p *portalProxy) GetSessionValue(c echo.Context, key string) (interface{}, error) {
Expand Down Expand Up @@ -80,7 +81,7 @@ func (p *portalProxy) setSessionValues(c echo.Context, values map[string]interfa
log.Debug("setSessionValues")

req := c.Request().(*standard.Request).Request
session, err := p.SessionStore.Get(req, portalSessionName)
session, err := p.SessionStore.Get(req, p.SessionCookieName)
if err != nil {
return err
}
Expand All @@ -96,7 +97,7 @@ func (p *portalProxy) unsetSessionValue(c echo.Context, sessionKey string) error
log.Debug("unsetSessionValues")

req := c.Request().(*standard.Request).Request
session, err := p.SessionStore.Get(req, portalSessionName)
session, err := p.SessionStore.Get(req, p.SessionCookieName)
if err != nil {
return err
}
Expand All @@ -111,7 +112,7 @@ func (p *portalProxy) clearSession(c echo.Context) error {

req := c.Request().(*standard.Request).Request
res := c.Response().(*standard.Response).ResponseWriter
session, err := p.SessionStore.Get(req, portalSessionName)
session, err := p.SessionStore.Get(req, p.SessionCookieName)
if err != nil {
return err
}
Expand Down

0 comments on commit e52e458

Please sign in to comment.