Skip to content
Snippets Groups Projects
Commit b1c0a012 authored by ale's avatar ale
Browse files

Simplify login handler by isolating session init logic

And standardize on a single structure for the gorilla session
map, using the 'data' key for our gob-encoded objects.
parent 10365b59
No related branches found
No related tags found
No related merge requests found
......@@ -200,7 +200,7 @@ func (h *Server) loginCallback(w http.ResponseWriter, req *http.Request, usernam
// Create cookie-based session for the authenticated user.
session := newAuthSession(h.authSessionLifetime, username, userinfo)
httpSession, _ := h.authSessionStore.Get(req, authSessionKey) // nolint
httpSession.Values["auth"] = session
httpSession.Values["data"] = session
return httpSession.Save(req, w)
}
......@@ -211,12 +211,13 @@ func (h *Server) withAuth(f func(http.ResponseWriter, *http.Request, *authSessio
http.Error(w, err.Error(), http.StatusInternalServerError)
return
}
session, ok := httpSession.Values["auth"].(*authSession)
if ok && session != nil && session.Valid() {
session, ok := httpSession.Values["data"].(*authSession)
if ok && session.Valid() {
f(w, req, session)
return
}
httpSession.Options.MaxAge = -1
delete(httpSession.Values, "data")
if err := httpSession.Save(req, w); err != nil {
log.Printf("error saving session: %v", err)
}
......@@ -224,9 +225,9 @@ func (h *Server) withAuth(f func(http.ResponseWriter, *http.Request, *authSessio
})
}
// Homepage handler. Authorizes an authenticated user to a service by
// signing a token with the user's identity. The client is redirected
// back to the service, with the signed token.
// Token signing handler. Authorizes an authenticated user to a service by
// signing a token with the user's identity. The client is redirected back to
// the original service, with the signed token.
func (h *Server) handleHomepage(w http.ResponseWriter, req *http.Request, session *authSession) {
// Extract the authorization request parameters from the HTTP
// request.
......
......@@ -105,21 +105,43 @@ func newLoginHandler(okHandler loginCallbackFunc, devMgr *device.Manager, authCl
}
}
func (l *loginHandler) fetchOrInitSession(req *http.Request) (*sessions.Session, *loginSession, error) {
// Either fetch the current session or create a new blank one.
httpSession, err := l.loginSessionStore.Get(req, loginSessionKey)
if err != nil {
return nil, nil, err
}
session, ok := httpSession.Values["data"].(*loginSession)
if !ok || !session.Valid() {
session = newLoginSession()
// Initialize session. The only parameter is 'r', the target
// redirect location. Enforce relative redirect URL (no host
// should be specified).
session.Redir = req.FormValue("r")
if session.Redir == "" {
return nil, nil, errors.New("empty login redirect target")
}
if !strings.HasPrefix(session.Redir, "/") || strings.HasPrefix(session.Redir, "//") {
return nil, nil, errors.New("bad login redirect target")
}
httpSession.Values["data"] = session
}
return httpSession, session, nil
}
// The login session controls the flow of the client - it's just a way
// to ensure that every step is authorized as part of the login
// sequence.
func (l *loginHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// Either fetch the current session or create a new blank one.
httpSession, err := l.loginSessionStore.Get(req, loginSessionKey)
httpSession, session, err := l.fetchOrInitSession(req)
if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError)
log.Printf("login session init error: %v", err)
http.Error(w, err.Error(), http.StatusBadRequest)
return
}
session, ok := httpSession.Values["ls"].(*loginSession)
if !ok || session == nil || !session.Valid() {
session = newLoginSession()
httpSession.Values["ls"] = session
}
// Dispatch the current state to its handler. Handlers will
// handle the current request and either 1) validate the
......@@ -142,6 +164,7 @@ func (l *loginHandler) ServeHTTP(w http.ResponseWriter, req *http.Request) {
// the login callback, before redirecting to the
// original URL.
httpSession.Options.MaxAge = -1
delete(httpSession.Values, "data")
if err := httpSession.Save(req, w); err != nil {
log.Printf("login error saving session: %v", err)
http.Error(w, err.Error(), http.StatusInternalServerError)
......@@ -188,14 +211,6 @@ func (l *loginHandler) handlePassword(w http.ResponseWriter, req *http.Request,
username := req.FormValue("username")
password := req.FormValue("password")
if req.Method == "GET" && session.Redir == "" {
session.Redir = req.FormValue("r")
// Enforce relative redirect URL (no host specified).
if session.Redir == "" || !strings.HasPrefix(session.Redir, "/") {
return loginStateNone, nil, errors.New("bad request")
}
}
// If the request is a POST, attempt login with username/password.
env := map[string]interface{}{
"Error": false,
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment