From 2391a279f9d0e1657e8b17a3b8ffaa9698231719 Mon Sep 17 00:00:00 2001 From: Mihai Parparita Date: Sat, 26 Jul 2014 15:34:47 -0700 Subject: [PATCH] Store OAuth token in a session cookie. Not the final design (it'll instead be persisted to the App Engine data store, and the session will just have the user ID), but this has most of the scaffolding for session cookies. --- .gitignore | 1 + app/config/session.json.SAMPLE | 6 +++ app/githop.go | 80 +++++++++++++++++++++++++---- app/templates/index-signed-out.html | 15 ++++++ 4 files changed, 92 insertions(+), 10 deletions(-) create mode 100644 app/config/session.json.SAMPLE create mode 100644 app/templates/index-signed-out.html diff --git a/.gitignore b/.gitignore index afc1d00..5ceb254 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ app/config/*oauth*.json +app/config/session.json diff --git a/app/config/session.json.SAMPLE b/app/config/session.json.SAMPLE new file mode 100644 index 0000000..e70d30a --- /dev/null +++ b/app/config/session.json.SAMPLE @@ -0,0 +1,6 @@ +{ + "AuthenticationKey": "REPLACE_ME_WITH_A_32_BYTE_BASE_64_ENCODED_KEY_BYES", + "EncryptionKey": "REPLACE_ME_WITH_A_32_BYTE_BASE_64_ENCODED_KEY_BYTES", + "CookieName": "session", + "TokenKey": "token_temp" +} diff --git a/app/githop.go b/app/githop.go index 177a0c8..560cacf 100644 --- a/app/githop.go +++ b/app/githop.go @@ -10,7 +10,6 @@ import ( "log" "net/http" "net/http/httputil" - "net/url" "sort" "strings" "time" @@ -22,10 +21,20 @@ import ( "code.google.com/p/goauth2/oauth" "github.com/google/go-github/github" "github.com/gorilla/mux" + "github.com/gorilla/sessions" ) var router *mux.Router var githubOauthConfig oauth.Config +var sessionStore *sessions.CookieStore +var sessionConfig SessionConfig + +type SessionConfig struct { + AuthenticationKey string + EncryptionKey string + CookieName string + TokenKey string +} type RepoDigest struct { Repo *github.Repository @@ -82,6 +91,32 @@ func (digest *Digest) Fetch(repos []github.Repository, githubClient *github.Clie return nil } +func initSessionConfig() { + configBytes, err := ioutil.ReadFile("config/session.json") + if err != nil { + log.Panicf("Could not read session config: %s", err.Error()) + } + err = json.Unmarshal(configBytes, &sessionConfig) + if err != nil { + log.Panicf("Could not parse session config %s: %s", configBytes, err.Error()) + } + + authenticationKey, err := base64.StdEncoding.DecodeString(sessionConfig.AuthenticationKey) + if err != nil { + log.Panicf("Could not decode session config authentication key %s: %s", sessionConfig.AuthenticationKey, err.Error()) + } + encryptionKey, err := base64.StdEncoding.DecodeString(sessionConfig.EncryptionKey) + if err != nil { + log.Panicf("Could not decode session config encryption key %s: %s", sessionConfig.EncryptionKey, err.Error()) + } + + sessionStore = sessions.NewCookieStore(authenticationKey, encryptionKey) + sessionStore.Options.Path = "/" + sessionStore.Options.MaxAge = 86400 * 30 + sessionStore.Options.HttpOnly = true + sessionStore.Options.Secure = !appengine.IsDevAppServer() +} + func initGithubOAuthConfig() { path := "config/github-oauth" if appengine.IsDevAppServer() { @@ -94,7 +129,7 @@ func initGithubOAuthConfig() { } err = json.Unmarshal(configBytes, &githubOauthConfig) if err != nil { - log.Panicf("Could not parse GitHut OAuth %s", err.Error()) + log.Panicf("Could not parse GitHub OAuth config %s: %s", configBytes, err.Error()) } githubOauthConfig.Scope = "repo" githubOauthConfig.AuthURL = "https://github.com/login/oauth/authorize" @@ -102,20 +137,43 @@ func initGithubOAuthConfig() { } func init() { + initSessionConfig() initGithubOAuthConfig() router = mux.NewRouter() router.HandleFunc("/", indexHandler).Name("index") + router.HandleFunc("/session/sign-in", signInHandler).Name("sign-in") + router.HandleFunc("/session/sign-out", signOutHandler).Name("sign-out") router.HandleFunc("/github/callback", githubOAuthCallbackHandler) http.Handle("/", router) } var indexTemplate = template.Must(template.ParseFiles("templates/index.html")) +var indexSignedOutTemplate = template.Must(template.ParseFiles("templates/index-signed-out.html")) + +func signInHandler(w http.ResponseWriter, r *http.Request) { + http.Redirect(w, r, githubOauthConfig.AuthCodeURL(""), http.StatusFound) +} + +func signOutHandler(w http.ResponseWriter, r *http.Request) { + session, _ := sessionStore.Get(r, sessionConfig.CookieName) + session.Options.MaxAge = 0 + session.Save(r, w) + indexUrl, _ := router.Get("index").URL() + http.Redirect(w, r, indexUrl.String(), http.StatusFound) +} func indexHandler(w http.ResponseWriter, r *http.Request) { - tokenEncoded := r.FormValue("token") - if tokenEncoded == "" { - http.Redirect(w, r, githubOauthConfig.AuthCodeURL(""), http.StatusFound) + session, _ := sessionStore.Get(r, sessionConfig.CookieName) + tokenEncoded, ok := session.Values[sessionConfig.TokenKey].(string) + if !ok { + signInUrl, _ := router.Get("sign-in").URL() + var signedOutParams = map[string]string{ + "SignInUrl": signInUrl.String(), + } + if err := indexSignedOutTemplate.Execute(w, signedOutParams); err != nil { + http.Error(w, err.Error(), http.StatusInternalServerError) + } return } token, err := decodeOAuthToken(tokenEncoded) @@ -200,11 +258,13 @@ func githubOAuthCallbackHandler(w http.ResponseWriter, r *http.Request) { http.Error(w, err.Error(), http.StatusInternalServerError) return } - redirectUrl, _ := router.GetRoute("index").URL() - redirectParams := url.Values{} - redirectParams.Add("token", tokenEncoded) - redirectUrl.RawQuery = redirectParams.Encode() - http.Redirect(w, r, redirectUrl.String(), http.StatusFound) + + session, _ := sessionStore.Get(r, sessionConfig.CookieName) + session.Values[sessionConfig.TokenKey] = tokenEncoded + session.Save(r, w) + log.Printf("session.Values: %s", session.Values) + indexUrl, _ := router.Get("index").URL() + http.Redirect(w, r, indexUrl.String(), http.StatusFound) } func githubOAuthTransport(r *http.Request) *oauth.Transport { diff --git a/app/templates/index-signed-out.html b/app/templates/index-signed-out.html new file mode 100644 index 0000000..1c06116 --- /dev/null +++ b/app/templates/index-signed-out.html @@ -0,0 +1,15 @@ + + + + + GitHop + + + +

GitHop!

+ + + Sign In + + +