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