Implement ClearSession for cookie SessionStore
This commit is contained in:
parent
8b3a3853eb
commit
15a2cf8b9e
34
pkg/cookies/cookies.go
Normal file
34
pkg/cookies/cookies.go
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
package cookies
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/pusher/oauth2_proxy/logger"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MakeCookie constructs a cookie from the given parameters,
|
||||||
|
// discovering the domain from the request if not specified.
|
||||||
|
func MakeCookie(req *http.Request, name string, value string, path string, domain string, httpOnly bool, secure bool, expiration time.Duration, now time.Time) *http.Cookie {
|
||||||
|
if domain != "" {
|
||||||
|
host := req.Host
|
||||||
|
if h, _, err := net.SplitHostPort(host); err == nil {
|
||||||
|
host = h
|
||||||
|
}
|
||||||
|
if !strings.HasSuffix(host, domain) {
|
||||||
|
logger.Printf("Warning: request host is %q but using configured cookie domain of %q", host, domain)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return &http.Cookie{
|
||||||
|
Name: name,
|
||||||
|
Value: value,
|
||||||
|
Path: path,
|
||||||
|
Domain: domain,
|
||||||
|
HttpOnly: httpOnly,
|
||||||
|
Secure: secure,
|
||||||
|
Expires: now.Add(expiration),
|
||||||
|
}
|
||||||
|
}
|
@ -4,12 +4,14 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"regexp"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/pusher/oauth2_proxy/cookie"
|
"github.com/pusher/oauth2_proxy/cookie"
|
||||||
"github.com/pusher/oauth2_proxy/pkg/apis/options"
|
"github.com/pusher/oauth2_proxy/pkg/apis/options"
|
||||||
"github.com/pusher/oauth2_proxy/pkg/apis/sessions"
|
"github.com/pusher/oauth2_proxy/pkg/apis/sessions"
|
||||||
|
"github.com/pusher/oauth2_proxy/pkg/cookies"
|
||||||
"github.com/pusher/oauth2_proxy/pkg/sessions/utils"
|
"github.com/pusher/oauth2_proxy/pkg/sessions/utils"
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -20,9 +22,13 @@ var _ sessions.SessionStore = &SessionStore{}
|
|||||||
// interface that stores sessions in client side cookies
|
// interface that stores sessions in client side cookies
|
||||||
type SessionStore struct {
|
type SessionStore struct {
|
||||||
CookieCipher *cookie.Cipher
|
CookieCipher *cookie.Cipher
|
||||||
|
CookieDomain string
|
||||||
CookieExpire time.Duration
|
CookieExpire time.Duration
|
||||||
|
CookieHTTPOnly bool
|
||||||
CookieName string
|
CookieName string
|
||||||
|
CookiePath string
|
||||||
CookieSecret string
|
CookieSecret string
|
||||||
|
CookieSecure bool
|
||||||
}
|
}
|
||||||
|
|
||||||
// SaveSession takes a sessions.SessionState and stores the information from it
|
// SaveSession takes a sessions.SessionState and stores the information from it
|
||||||
@ -54,7 +60,35 @@ func (s *SessionStore) LoadSession(req *http.Request) (*sessions.SessionState, e
|
|||||||
// ClearSession clears any saved session information by writing a cookie to
|
// ClearSession clears any saved session information by writing a cookie to
|
||||||
// clear the session
|
// clear the session
|
||||||
func (s *SessionStore) ClearSession(rw http.ResponseWriter, req *http.Request) error {
|
func (s *SessionStore) ClearSession(rw http.ResponseWriter, req *http.Request) error {
|
||||||
return fmt.Errorf("method not implemented")
|
var cookies []*http.Cookie
|
||||||
|
|
||||||
|
// matches CookieName, CookieName_<number>
|
||||||
|
var cookieNameRegex = regexp.MustCompile(fmt.Sprintf("^%s(_\\d+)?$", s.CookieName))
|
||||||
|
|
||||||
|
for _, c := range req.Cookies() {
|
||||||
|
if cookieNameRegex.MatchString(c.Name) {
|
||||||
|
clearCookie := s.makeCookie(req, c.Name, "", time.Hour*-1)
|
||||||
|
|
||||||
|
http.SetCookie(rw, clearCookie)
|
||||||
|
cookies = append(cookies, clearCookie)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *SessionStore) makeCookie(req *http.Request, name string, value string, expiration time.Duration) *http.Cookie {
|
||||||
|
return cookies.MakeCookie(
|
||||||
|
req,
|
||||||
|
name,
|
||||||
|
value,
|
||||||
|
s.CookiePath,
|
||||||
|
s.CookieDomain,
|
||||||
|
s.CookieHTTPOnly,
|
||||||
|
s.CookieSecure,
|
||||||
|
expiration,
|
||||||
|
time.Now(),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewCookieSessionStore initialises a new instance of the SessionStore from
|
// NewCookieSessionStore initialises a new instance of the SessionStore from
|
||||||
@ -71,9 +105,13 @@ func NewCookieSessionStore(opts options.CookieStoreOptions, cookieOpts *options.
|
|||||||
|
|
||||||
return &SessionStore{
|
return &SessionStore{
|
||||||
CookieCipher: cipher,
|
CookieCipher: cipher,
|
||||||
|
CookieDomain: cookieOpts.CookieDomain,
|
||||||
CookieExpire: cookieOpts.CookieExpire,
|
CookieExpire: cookieOpts.CookieExpire,
|
||||||
|
CookieHTTPOnly: cookieOpts.CookieHTTPOnly,
|
||||||
CookieName: cookieOpts.CookieName,
|
CookieName: cookieOpts.CookieName,
|
||||||
|
CookiePath: cookieOpts.CookiePath,
|
||||||
CookieSecret: cookieOpts.CookieSecret,
|
CookieSecret: cookieOpts.CookieSecret,
|
||||||
|
CookieSecure: cookieOpts.CookieSecure,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2,6 +2,7 @@ package sessions_test
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
@ -9,6 +10,7 @@ import (
|
|||||||
. "github.com/onsi/gomega"
|
. "github.com/onsi/gomega"
|
||||||
"github.com/pusher/oauth2_proxy/pkg/apis/options"
|
"github.com/pusher/oauth2_proxy/pkg/apis/options"
|
||||||
sessionsapi "github.com/pusher/oauth2_proxy/pkg/apis/sessions"
|
sessionsapi "github.com/pusher/oauth2_proxy/pkg/apis/sessions"
|
||||||
|
"github.com/pusher/oauth2_proxy/pkg/cookies"
|
||||||
"github.com/pusher/oauth2_proxy/pkg/sessions"
|
"github.com/pusher/oauth2_proxy/pkg/sessions"
|
||||||
"github.com/pusher/oauth2_proxy/pkg/sessions/cookie"
|
"github.com/pusher/oauth2_proxy/pkg/sessions/cookie"
|
||||||
)
|
)
|
||||||
@ -23,16 +25,14 @@ var _ = Describe("NewSessionStore", func() {
|
|||||||
var cookieOpts *options.CookieOptions
|
var cookieOpts *options.CookieOptions
|
||||||
|
|
||||||
var request *http.Request
|
var request *http.Request
|
||||||
var response http.ResponseWriter
|
var response *httptest.ResponseRecorder
|
||||||
var session *sessionsapi.SessionState
|
var session *sessionsapi.SessionState
|
||||||
|
|
||||||
CheckCookieOptions := func() {
|
CheckCookieOptions := func() {
|
||||||
Context("the cookies returned", func() {
|
Context("the cookies returned", func() {
|
||||||
var cookies []*http.Cookie
|
var cookies []*http.Cookie
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
req := http.Request{}
|
cookies = response.Result().Cookies()
|
||||||
req.Header.Add("Cookie", response.Header().Get("Set-Cookie"))
|
|
||||||
cookies = req.Cookies()
|
|
||||||
})
|
})
|
||||||
|
|
||||||
It("have the correct name set", func() {
|
It("have the correct name set", func() {
|
||||||
@ -97,6 +97,17 @@ var _ = Describe("NewSessionStore", func() {
|
|||||||
|
|
||||||
Context("when ClearSession is called", func() {
|
Context("when ClearSession is called", func() {
|
||||||
BeforeEach(func() {
|
BeforeEach(func() {
|
||||||
|
cookie := cookies.MakeCookie(request,
|
||||||
|
cookieOpts.CookieName,
|
||||||
|
"foo",
|
||||||
|
cookieOpts.CookiePath,
|
||||||
|
cookieOpts.CookieDomain,
|
||||||
|
cookieOpts.CookieHTTPOnly,
|
||||||
|
cookieOpts.CookieSecure,
|
||||||
|
cookieOpts.CookieExpire,
|
||||||
|
time.Now(),
|
||||||
|
)
|
||||||
|
request.AddCookie(cookie)
|
||||||
err := ss.ClearSession(response, request)
|
err := ss.ClearSession(response, request)
|
||||||
Expect(err).ToNot(HaveOccurred())
|
Expect(err).ToNot(HaveOccurred())
|
||||||
})
|
})
|
||||||
@ -166,6 +177,9 @@ var _ = Describe("NewSessionStore", func() {
|
|||||||
CookieSecure: true,
|
CookieSecure: true,
|
||||||
CookieHTTPOnly: true,
|
CookieHTTPOnly: true,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
request = httptest.NewRequest("GET", "http://example.com/", nil)
|
||||||
|
response = httptest.NewRecorder()
|
||||||
})
|
})
|
||||||
|
|
||||||
Context("with type 'cookie'", func() {
|
Context("with type 'cookie'", func() {
|
||||||
|
Loading…
Reference in New Issue
Block a user