package auth import ( "encoding/json" "errors" "fmt" "net/http" "strings" "time" "git.schreifuchs.ch/schreifuchs/ng-blog/backend/model" "github.com/golang-jwt/jwt/v5" ) func Login(username, password string, secret []byte) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { login := model.Login{} if err := json.NewDecoder(r.Body).Decode(&login); err != nil { w.WriteHeader(http.StatusUnauthorized) return } if login.Name == username && login.Password == password { token, err := createJWT(secret) if err != nil { w.WriteHeader(http.StatusUnauthorized) return } err = json.NewEncoder(w).Encode(&model.LoginResponse{ Token: token, }) if err != nil { w.WriteHeader(http.StatusUnauthorized) return } w.WriteHeader(http.StatusOK) return } } } func Authenticated(secret []byte) func(http.HandlerFunc) http.Handler { return func(next http.HandlerFunc) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { // Our middleware logic goes here... token, err := extractToken(r) if err != nil { w.WriteHeader(http.StatusUnauthorized) return } err = validateJWT(token, secret) if err != nil { w.WriteHeader(http.StatusUnauthorized) return } next(w, r) }) } } func createJWT(secret []byte) (token string, err error) { return jwt.NewWithClaims(jwt.SigningMethodHS512, jwt.MapClaims{ "exp": time.Now().Add(time.Hour * 24).Unix(), }).SignedString(secret) } func validateJWT(tokenString string, secret []byte) (err error) { token, err := jwt.Parse(tokenString, func(token *jwt.Token) (any, error) { // Don't forget to validate the alg is what you expect: if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) } return secret, nil }) if err != nil { return } if date, err := token.Claims.GetExpirationTime(); err == nil && date.After(time.Now()) { return nil } return errors.New("JWT not valid") } func extractToken(r *http.Request) (token string, err error) { tokenHeader := r.Header.Get("Authorization") // Grab the token from the header if tokenHeader == "" { err = errors.New("missing token") return } token = strings.TrimPrefix(tokenHeader, "Bearer ") if token == "" { err = errors.New("malformed token") } return }