auth

Paddy 2014-08-16 Parent:9a1e62c24903 Child:51700827b6ee

19:9fe684b33b3d Go to Latest

auth/session.go

Implement session management and move login. Add a session store interface to validate and retrieve data about sessions. Implement session management in endpoints that need session support. Move the login functionality from inlined into the OAuth flow into its own handler, that the OAuth flow will redirect to. The login functionality should take a redirect URL parameter to return to the OAuth flow when login is completed.

History
paddy@6 1 package auth
paddy@1 2
paddy@19 3 import (
paddy@19 4 "errors"
paddy@19 5 "net/http"
paddy@19 6 "time"
paddy@19 7
paddy@19 8 "secondbit.org/uuid"
paddy@19 9 )
paddy@19 10
paddy@19 11 const sessionCookie = "session"
paddy@19 12
paddy@19 13 var (
paddy@19 14 ErrSessionNotFound = errors.New("Session not found.")
paddy@19 15 )
paddy@19 16
paddy@19 17 type Session struct {
paddy@19 18 Token string
paddy@19 19 User uuid.ID
paddy@19 20 Expires time.Time
paddy@19 21 Created time.Time
paddy@19 22 IP string
paddy@19 23 }
paddy@1 24
paddy@2 25 func validateSession(r *http.Request, c Context) error {
paddy@19 26 cookie, err := r.Cookie(sessionCookie)
paddy@19 27 if err == http.ErrNoCookie {
paddy@19 28 return ErrSessionNotFound
paddy@19 29 }
paddy@19 30 _, err = c.Sessions.GetSession(cookie.Value)
paddy@19 31 return err
paddy@1 32 }
paddy@19 33
paddy@19 34 func HandleLoginRequest(w http.ResponseWriter, r *http.Request, ctx Context) {
paddy@19 35 if r.Method == "GET" {
paddy@19 36 ctx.RenderLogin(w, r)
paddy@19 37 return
paddy@19 38 } else if r.Method != "POST" {
paddy@19 39 // TODO: return bad method error
paddy@19 40 return
paddy@19 41 }
paddy@19 42
paddy@19 43 if r.FormValue("username") == "" || r.FormValue("password") == "" {
paddy@19 44 // TODO: return unauthenticated error
paddy@19 45 return
paddy@19 46 }
paddy@19 47 id, err := ctx.Profiles.GetProfile(r.FormValue("username"), r.FormValue("password"))
paddy@19 48 if err != nil {
paddy@19 49 if err == ErrProfileNotFound {
paddy@19 50 // TODO: return unauthenticated error
paddy@19 51 return
paddy@19 52 }
paddy@19 53 // TODO: return internal server error
paddy@19 54 return
paddy@19 55 }
paddy@19 56 session := Session{
paddy@19 57 Token: newToken(),
paddy@19 58 User: id,
paddy@19 59 Expires: time.Now().Add(ctx.Config.SessionLength),
paddy@19 60 Created: time.Now(),
paddy@19 61 IP: r.Header.Get(ctx.Config.RequestIPHeader),
paddy@19 62 }
paddy@19 63 err = ctx.Sessions.SetSession(session)
paddy@19 64 if err != nil {
paddy@19 65 // TODO: return internal server error
paddy@19 66 return
paddy@19 67 }
paddy@19 68 http.SetCookie(w, &http.Cookie{
paddy@19 69 Name: sessionCookie,
paddy@19 70 Value: session.Token,
paddy@19 71 Expires: session.Expires,
paddy@19 72 Secure: true,
paddy@19 73 HttpOnly: true,
paddy@19 74 })
paddy@19 75 // TODO: redirect
paddy@19 76 }