package server import ( "crypto/rand" "encoding/hex" "encoding/json" "fmt" "html/template" "io" "log" "net/http" "strings" "github.com/nsheridan/cashier/lib" "github.com/nsheridan/cashier/server/templates" "golang.org/x/oauth2" ) func (a *app) sign(w http.ResponseWriter, r *http.Request) { var t string if ah := r.Header.Get("Authorization"); ah != "" { if len(ah) > 6 && strings.ToUpper(ah[0:7]) == "BEARER " { t = ah[7:] } } token := &oauth2.Token{ AccessToken: t, } if !a.authprovider.Valid(token) { w.WriteHeader(http.StatusUnauthorized) fmt.Fprint(w, http.StatusText(http.StatusUnauthorized)) return } // Sign the pubkey and issue the cert. req := &lib.SignRequest{} if err := json.NewDecoder(r.Body).Decode(req); err != nil { fmt.Println(err) w.WriteHeader(http.StatusBadRequest) fmt.Fprint(w, http.StatusText(http.StatusBadRequest)) return } username := a.authprovider.Username(token) cert, err := a.keysigner.SignUserKey(req, username) if err != nil { w.WriteHeader(http.StatusInternalServerError) fmt.Fprintf(w, "Error signing key") return } if err := json.NewEncoder(w).Encode(&lib.SignResponse{ Status: "ok", Response: string(lib.GetPublicKey(cert)), }); err != nil { w.WriteHeader(http.StatusInternalServerError) fmt.Fprintf(w, "Error signing key") return } } func (a *app) auth(w http.ResponseWriter, r *http.Request) { switch r.URL.EscapedPath() { case "/auth/login": buf := make([]byte, 32) io.ReadFull(rand.Reader, buf) state := hex.EncodeToString(buf) a.setSessionVariable(w, r, "state", state) http.Redirect(w, r, a.authprovider.StartSession(state), http.StatusFound) case "/auth/callback": state := a.getSessionVariable(r, "state") if r.FormValue("state") != state { log.Printf("Not authorized on /auth/callback") w.WriteHeader(http.StatusUnauthorized) w.Write([]byte(http.StatusText(http.StatusUnauthorized))) break } originURL := a.getSessionVariable(r, "origin_url") if originURL == "" { originURL = "/" } code := r.FormValue("code") token, err := a.authprovider.Exchange(code) if err != nil { log.Printf("Error on /auth/callback: %v", err) w.WriteHeader(http.StatusInternalServerError) w.Write([]byte(http.StatusText(http.StatusInternalServerError))) w.Write([]byte(err.Error())) break } log.Printf("Token found on /auth/callback, redirecting to %s", originURL) a.setAuthToken(w, r, token) http.Redirect(w, r, originURL, http.StatusFound) default: w.WriteHeader(http.StatusInternalServerError) } } func (a *app) index(w http.ResponseWriter, r *http.Request) { tok := a.getAuthToken(r) page := struct { Token string }{tok.AccessToken} page.Token = encodeString(page.Token) tmpl := template.Must(template.New("token.html").Parse(templates.Token)) tmpl.Execute(w, page) }