package auth import ( "errors" "fmt" "net/http" "strings" "time" "git.schreifuchs.ch/schreifuchs/ng-blog/backend/internal/model" jwt "github.com/golang-jwt/jwt/v5" ) var ErrJWTInvalid = errors.New("JWT not valid") func (s *Service) createJWT(user *model.User) (token string, err error) { claims := &Claims{ Role: user.Role, UserID: user.ID, RegisteredClaims: jwt.RegisteredClaims{ Subject: user.UUID.String(), ExpiresAt: &jwt.NumericDate{ Time: time.Now().Add(s.cfg.ValidDuration), }, }, } return jwt.NewWithClaims(jwt.SigningMethodHS512, claims).SignedString([]byte(s.cfg.Secret)) } // validateJWT returns the token Claims and if token ist invalid ErrJWTInvalid func (s *Service) validateJWT(tokenString string) (claims Claims, err error) { _, err = jwt.ParseWithClaims(tokenString, &claims, 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 []byte(s.cfg.Secret), nil }) if err != nil { return } if claims.ExpiresAt.Before(time.Now()) { err = ErrJWTInvalid return } // check if user has logged out this token var invalidated bool err = s.db.Model(&model.InvalidJWT{}). Select("count(*) > 0"). Where("jwt = ?", tokenString). Find(&invalidated). Error if invalidated || err != nil { err = ErrJWTInvalid return } return } // extractToken extracts the Bearer token from the request 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 }