package main import ( "log" "net/http" "time" jwt "github.com/dgrijalva/jwt-go" "riedstra.dev/mitch/go-website/page" "riedstra.dev/mitch/go-website/users" ) func (a *App) Err5xx(w http.ResponseWriter, r *http.Request, statusCode int, title, desc string) { page.Render5xx(w, r, map[string]interface{}{ "Error": title, "Description": desc, }, statusCode) } func (a *App) Err500Default(w http.ResponseWriter, r *http.Request) { a.Err5xx(w, r, http.StatusInternalServerError, "Internal server error", "Internal server error.") } func (a *App) LogoutHandler(w http.ResponseWriter, r *http.Request) { http.SetCookie(w, &http.Cookie{ Name: "Auth", HttpOnly: a.auth.HTTPOnly, SameSite: a.auth.SameSiteStrict, Secure: a.auth.Secure, Value: "logout", Expires: time.Now().Add(time.Second * 15), //nolint }) http.Redirect(w, r, "/", http.StatusFound) } func (a *App) LoginHandler(w http.ResponseWriter, r *http.Request) { //nolint if r.Method == "GET" { page.RenderForPath(w, r, "login") return } if r.Method != "POST" { a.Err500Default(w, r) return } log.Printf("made it") username := r.FormValue("username") password := r.FormValue("password") var ( err error = nil u *users.SiteUser found = false ) for _, u = range a.auth.Users { if u.Username == username { err = u.CheckPassword(password) found = true } } if err != nil || !found { page.Render(w, r, "login", map[string]interface{}{ "Error": "Invalid username or password", "Username": username, }, http.StatusUnauthorized) return } token := jwt.NewWithClaims(jwt.SigningMethodHS512, &jwt.StandardClaims{ ExpiresAt: time.Now().Add( time.Hour * time.Duration(a.auth.LoginHours)).Unix(), Id: u.Username, }) ss, err := token.SignedString([]byte(a.auth.TokenKey)) if err != nil { log.Println("login: encountered while setting up JWT: ", err) a.Err500Default(w, r) return } log.Println(ss) http.SetCookie(w, &http.Cookie{ Name: "Auth", HttpOnly: a.auth.HTTPOnly, SameSite: a.auth.SameSiteStrict, Secure: a.auth.Secure, Value: ss, }) http.Redirect(w, r, "/login", http.StatusFound) } func (a *App) RequiresLogin(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { mustLoginResp := func() { page.Render(w, r, "login", map[string]interface{}{ "Error": "You must login to view this page", }, http.StatusUnauthorized) } c, err := r.Cookie("Auth") if err != nil { mustLoginResp() return } token, err := jwt.Parse(c.Value, func(token *jwt.Token) (interface{}, error) { return []byte(a.auth.TokenKey), nil }, ) if err != nil { log.Printf("Unauthorized request %s %s", r.Method, r.URL.Path) mustLoginResp() return } if !token.Valid { mustLoginResp() return } next.ServeHTTP(w, r) }) }