auth

Paddy 2014-09-01 Parent:1aa3a85ff853

28:75cf37088852 Go to Latest

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.

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 }