auth
2014-09-01
Parent:1aa3a85ff853
auth/session.go.old
Rough out tokens and begin the memstore. Rough out the Token type for working with OAuth2 access and refresh tokens. Rough out the TokenStore interface that dictates how Tokens will be stored and retrieved. Write tests for the successful (in the working-as-intended sense) calls to TokenStore. Begin a Memstore type that stores data in memory. Implement the TokenStore interface for Memstore.
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 Profile uuid.ID
22 Expires time.Time
23 Created time.Time
24 IP string
25 }
27 type SessionStore interface {
28 GetSession(token string) (Session, error)
29 GetAllSessions(userID uuid.ID, num, page int) ([]Session, error)
30 SaveSession(session Session) error
31 DeleteSession(sessionID uuid.ID) error
32 }
34 func validateSession(r *http.Request, c Context) error {
35 cookie, err := r.Cookie(sessionCookie)
36 if err == http.ErrNoCookie {
37 return ErrSessionNotFound
38 }
39 _, err = c.Sessions.GetSession(cookie.Value)
40 return err
41 }
43 func HandleLoginRequest(w http.ResponseWriter, r *http.Request, ctx Context) {
44 if r.Method == "GET" {
45 ctx.RenderLogin(w, r)
46 return
47 } else if r.Method != "POST" {
48 // TODO: return bad method error
49 return
50 }
52 if r.FormValue("username") == "" || r.FormValue("password") == "" {
53 // TODO: return unauthenticated error
54 return
55 }
56 id, err := ctx.Profiles.GetProfile(r.FormValue("username"), r.FormValue("password"))
57 if err != nil {
58 if err == ErrProfileNotFound {
59 // TODO: return unauthenticated error
60 return
61 }
62 // TODO: return internal server error
63 return
64 }
65 session := Session{
66 Token: newToken(),
67 Profile: id,
68 Expires: time.Now().Add(ctx.Config.SessionLength),
69 Created: time.Now(),
70 IP: r.Header.Get(ctx.Config.RequestIPHeader),
71 }
72 err = ctx.Sessions.SetSession(session)
73 if err != nil {
74 // TODO: return internal server error
75 return
76 }
77 http.SetCookie(w, &http.Cookie{
78 Name: sessionCookie,
79 Value: session.Token,
80 Expires: session.Expires,
81 Secure: true,
82 HttpOnly: true,
83 })
85 redirectString := r.URL.Query().Get("redirect_to")
86 if redirectString != "" {
87 redirectURI, err := url.Parse(redirectString)
88 if err != nil {
89 // TODO: render a bad request error
90 return
91 }
92 if !strings.HasSuffix("."+ctx.Config.LoginRedirectDomain, redirectURI.Host) && redirectURI.Host != ctx.Config.LoginRedirectDomain {
93 // TODO: render a bad request error
94 return
95 }
96 } else {
97 redirectString = "https://" + ctx.Config.LoginRedirectDomain
98 }
99 http.Redirect(w, r, redirectString, http.StatusFound)
100 return
101 }