auth

Paddy 2014-08-16 Parent:9fe684b33b3d

21:51700827b6ee Go to Latest

auth/session.go

Redirect after login. After a successful login, redirect based on a query parameter. Only allow redirections to the domain listed in the config and its subdomains. If no redirect is specified, redirect to the root of the domain listed in the config.

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