auth

Paddy 2014-09-01 Parent:1aa3a85ff853

25:9fc5fd8196b4 Go to Latest

auth/session.go.old

Rough out client. Remove our old client implementation, and start exploring a new ClientStore interface for storing and retrieving Client data. Keep track of a website for clients.

History
paddy@23 1 package auth
paddy@23 2
paddy@23 3 import (
paddy@23 4 "errors"
paddy@23 5 "net/http"
paddy@23 6 "net/url"
paddy@23 7 "time"
paddy@23 8
paddy@23 9 "strings"
paddy@23 10 "secondbit.org/uuid"
paddy@23 11 )
paddy@23 12
paddy@23 13 const sessionCookie = "session"
paddy@23 14
paddy@23 15 var (
paddy@23 16 ErrSessionNotFound = errors.New("Session not found.")
paddy@23 17 )
paddy@23 18
paddy@23 19 type Session struct {
paddy@23 20 Token string
paddy@23 21 Profile uuid.ID
paddy@23 22 Expires time.Time
paddy@23 23 Created time.Time
paddy@23 24 IP string
paddy@23 25 }
paddy@23 26
paddy@23 27 type SessionStore interface {
paddy@23 28 GetSession(token string) (Session, error)
paddy@23 29 GetAllSessions(userID uuid.ID, num, page int) ([]Session, error)
paddy@23 30 SaveSession(session Session) error
paddy@23 31 DeleteSession(sessionID uuid.ID) error
paddy@23 32 }
paddy@23 33
paddy@23 34 func validateSession(r *http.Request, c Context) error {
paddy@23 35 cookie, err := r.Cookie(sessionCookie)
paddy@23 36 if err == http.ErrNoCookie {
paddy@23 37 return ErrSessionNotFound
paddy@23 38 }
paddy@23 39 _, err = c.Sessions.GetSession(cookie.Value)
paddy@23 40 return err
paddy@23 41 }
paddy@23 42
paddy@23 43 func HandleLoginRequest(w http.ResponseWriter, r *http.Request, ctx Context) {
paddy@23 44 if r.Method == "GET" {
paddy@23 45 ctx.RenderLogin(w, r)
paddy@23 46 return
paddy@23 47 } else if r.Method != "POST" {
paddy@23 48 // TODO: return bad method error
paddy@23 49 return
paddy@23 50 }
paddy@23 51
paddy@23 52 if r.FormValue("username") == "" || r.FormValue("password") == "" {
paddy@23 53 // TODO: return unauthenticated error
paddy@23 54 return
paddy@23 55 }
paddy@23 56 id, err := ctx.Profiles.GetProfile(r.FormValue("username"), r.FormValue("password"))
paddy@23 57 if err != nil {
paddy@23 58 if err == ErrProfileNotFound {
paddy@23 59 // TODO: return unauthenticated error
paddy@23 60 return
paddy@23 61 }
paddy@23 62 // TODO: return internal server error
paddy@23 63 return
paddy@23 64 }
paddy@23 65 session := Session{
paddy@23 66 Token: newToken(),
paddy@23 67 Profile: id,
paddy@23 68 Expires: time.Now().Add(ctx.Config.SessionLength),
paddy@23 69 Created: time.Now(),
paddy@23 70 IP: r.Header.Get(ctx.Config.RequestIPHeader),
paddy@23 71 }
paddy@23 72 err = ctx.Sessions.SetSession(session)
paddy@23 73 if err != nil {
paddy@23 74 // TODO: return internal server error
paddy@23 75 return
paddy@23 76 }
paddy@23 77 http.SetCookie(w, &http.Cookie{
paddy@23 78 Name: sessionCookie,
paddy@23 79 Value: session.Token,
paddy@23 80 Expires: session.Expires,
paddy@23 81 Secure: true,
paddy@23 82 HttpOnly: true,
paddy@23 83 })
paddy@23 84
paddy@23 85 redirectString := r.URL.Query().Get("redirect_to")
paddy@23 86 if redirectString != "" {
paddy@23 87 redirectURI, err := url.Parse(redirectString)
paddy@23 88 if err != nil {
paddy@23 89 // TODO: render a bad request error
paddy@23 90 return
paddy@23 91 }
paddy@23 92 if !strings.HasSuffix("."+ctx.Config.LoginRedirectDomain, redirectURI.Host) && redirectURI.Host != ctx.Config.LoginRedirectDomain {
paddy@23 93 // TODO: render a bad request error
paddy@23 94 return
paddy@23 95 }
paddy@23 96 } else {
paddy@23 97 redirectString = "https://" + ctx.Config.LoginRedirectDomain
paddy@23 98 }
paddy@23 99 http.Redirect(w, r, redirectString, http.StatusFound)
paddy@23 100 return
paddy@23 101 }