Potion/internal/app/server/middleware.go
Hayden Hargreaves 8e4a0deec8 (FEAT): Removed the need for sessions, going to use JWT's in cookies.
This works very well, just need to determine what routes will be
protected and such. For now, a simple system is setup, with more to
come. For now, this is a WIP and needs some light work. But auth is
almost complete.
2025-06-14 23:52:43 -07:00

88 lines
2.4 KiB
Go

package server
import (
"errors"
"fmt"
"log"
"net/http"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v5"
domain "github.com/haydenhargreaves/Potion/internal/domain/server"
)
// DepedencyInjectionMiddleware injects the dependencies into the context set. This is a middleware
// that is used to apply the required services.
func DepedencyInjectionMiddleware(deps *domain.InjectedDependencies) gin.HandlerFunc {
return func(ctx *gin.Context) {
ctx.Set("deps", deps)
ctx.Next()
}
}
func JwtAuthMiddleWare(jwtSecretKey []byte) gin.HandlerFunc {
return func(ctx *gin.Context) {
// NOTE: Option One: From auth header
//
// authHeader := ctx.GetHeader("Authorization")
//
// if authHeader == "" {
// ctx.JSON(http.StatusUnauthorized, gin.H{"error": "Authorization required."})
// ctx.Abort()
// return
// }
//
// parts := strings.SplitN(authHeader, " ", 2)
// if !(len(parts) == 2 && parts[0] == "Bearer") {
// ctx.JSON(http.StatusUnauthorized, gin.H{"error": "Authorization header must be Bearer token"})
// ctx.Abort()
// return
// }
//
// tokenString := parts[1]
// TODO: How are we handling faliure?
tokenString, err := ctx.Cookie("jwt_token")
if err != nil {
ctx.JSON(http.StatusUnauthorized, gin.H{"error": "JWT token cookie not found"})
ctx.Abort()
return
}
claims := &domain.JwtClaims{}
// token, err := jwt.ParseWithClaims(tokenString, claims, )
token, err := jwt.ParseWithClaims(tokenString, claims, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return jwtSecretKey, nil
})
if err != nil {
if errors.Is(err, jwt.ErrSignatureInvalid) {
ctx.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token signature"})
} else if errors.Is(err, jwt.ErrTokenExpired) || errors.Is(err, jwt.ErrTokenNotValidYet) {
ctx.JSON(http.StatusUnauthorized, gin.H{"error": "Token expired or not yet valid"})
} else {
log.Printf("JWT parsing error: %v", err)
ctx.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"})
}
ctx.Abort()
return
}
if !token.Valid {
ctx.JSON(http.StatusUnauthorized, gin.H{"error": "Invalid token"})
ctx.Abort()
return
}
// Found: Set the values
ctx.Set("userId", claims.UserId)
ctx.Set("userEmail", claims.Email)
ctx.Next()
}
}