diff options
Diffstat (limited to 'internal/auth/auth.go')
| -rw-r--r-- | internal/auth/auth.go | 68 |
1 files changed, 49 insertions, 19 deletions
diff --git a/internal/auth/auth.go b/internal/auth/auth.go index 2826a47..b58af82 100644 --- a/internal/auth/auth.go +++ b/internal/auth/auth.go @@ -5,6 +5,7 @@ import ( "net/http" "os" "strings" + "time" "github.com/golang-jwt/jwt/v5" "github.com/joho/godotenv" @@ -14,43 +15,72 @@ func init() { godotenv.Load() } -var ( - jwtsecret = []byte(os.Getenv("JWT_SECRET")) - algo = string(os.Getenv("JWT_ALGO")) -) +var jwtSecret = []byte(os.Getenv("JWT_SECRET")) + +const algo = "HS256" + +func GenerateJWT(userID string, duration time.Duration) (string, error) { + claims := jwt.MapClaims{ + "sub": userID, + "exp": time.Now().Add(duration).Unix(), + "iat": time.Now().Unix(), + } + + token := jwt.NewWithClaims(jwt.GetSigningMethod(algo), claims) + signedToken, err := token.SignedString(jwtSecret) + if err != nil { + return "", fmt.Errorf("failed to sign token: %w", err) + } + + return signedToken, nil +} -func validateJWT(tokenString string, expectedAlg string) (bool, error) { - token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) { +func validateJWT(tokenString string, expectedAlg string) (jwt.MapClaims, error) { + token, err := jwt.Parse(tokenString, func(token *jwt.Token) (any, error) { if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok { return nil, fmt.Errorf("invalid token: %v", token.Header["alg"]) } - if token.Header["alg"] != expectedAlg { - return nil, fmt.Errorf("incorrect alg: %v", token.Header["alg"]) + if token.Method != jwt.GetSigningMethod(expectedAlg) { + return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"]) } - return jwtsecret, nil + return jwtSecret, nil }) - if err != nil || !token.Valid { - return false, err + + if err != nil { + return nil, err + } + + claims, ok := token.Claims.(jwt.MapClaims) + if !ok || !token.Valid { + return nil, fmt.Errorf("JWT validation failed: invalid claims") } - if _, ok := token.Claims.(jwt.MapClaims); ok && token.Valid { - return true, nil + if exp, ok := claims["exp"].(float64); ok { + if int64(exp) < time.Now().Unix() { + return nil, fmt.Errorf("JWT validation failed: token expired") + } } - return false, fmt.Errorf("invalid token") + + return claims, nil } -func Verifyrequest(r *http.Request) bool { +func VerifyRequest(r *http.Request) (jwt.MapClaims, error) { authHeader := r.Header.Get("Authorization") if authHeader == "" { - return false + return nil, fmt.Errorf("Missing Authorization header in request") } // expected: "Bearer <token>" authSplit := strings.Split(authHeader, " ") if len(authSplit) != 2 || authSplit[0] != "Bearer" { - return false + return nil, fmt.Errorf("Malformed Authorization header in request") } token := authSplit[1] - isValid, _ := validateJWT(token, algo) - return isValid + claims, err := validateJWT(token, algo) + if err != nil { + fmt.Printf("JWT error: %v for token: %s\n", err, token) + return nil, err + } + + return claims, nil } |
