Files
bibliomane/internal/middleware/auth.go

91 lines
1.9 KiB
Go

package middleware
import (
"net/http"
"strconv"
"strings"
"git.artlef.fr/bibliomane/internal/jwtauth"
"github.com/gin-gonic/gin"
"github.com/golang-jwt/jwt/v5"
)
func Auth() gin.HandlerFunc {
return func(c *gin.Context) {
//do not check current user if we are creating an account or logging in
if strings.HasPrefix(c.FullPath(), "/ws/auth/") {
return
}
//do not check appinfo
if strings.HasPrefix(c.FullPath(), "/ws/appinfo") {
return
}
//do not check static files
if strings.HasPrefix(c.FullPath(), "/static/bookcover/") {
return
}
jwtokenStr := jwtFromBearerToken(c.GetHeader("Authorization"))
jwtoken, err := jwt.Parse(jwtokenStr,
func(token *jwt.Token) (any, error) {
return jwtauth.GetJwtKey()
}, jwt.WithValidMethods([]string{jwt.SigningMethodHS256.Alg()}))
if err != nil {
abortError(c)
return
}
//check admin rights
if strings.HasPrefix(c.FullPath(), "/ws/admin/") && !hasAdminRights(jwtoken) {
c.AbortWithStatusJSON(http.StatusForbidden,
gin.H{"error": "You do not have the right to access this resource."})
return
}
username, err := jwtoken.Claims.GetSubject()
if err != nil {
abortError(c)
} else {
c.Set("user", username)
}
}
}
func jwtFromBearerToken(bearerToken string) string {
splitToken := strings.Split(bearerToken, " ")
if len(splitToken) == 2 {
return splitToken[1]
} else {
return ""
}
}
func hasAdminRights(token *jwt.Token) bool {
claims, ok := token.Claims.(jwt.MapClaims)
if !ok {
return false
}
raw, ok := claims["admin"]
if !ok {
return false
}
adminStr, ok := raw.(string)
if !ok {
return false
}
isAdmin, err := strconv.ParseBool(adminStr)
if err != nil {
return false
}
return isAdmin
}
func abortError(c *gin.Context) {
c.AbortWithStatusJSON(http.StatusUnauthorized,
gin.H{"error": "You must be logged in to access this resource."})
}