103 lines
3.0 KiB
Go
103 lines
3.0 KiB
Go
package middleware
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
model2 "mangezmieux-backend/internal/acl/model"
|
|
"mangezmieux-backend/internal/jwt"
|
|
"mangezmieux-backend/internal/logger"
|
|
"mangezmieux-backend/internal/responses"
|
|
"mangezmieux-backend/internal/users/model"
|
|
"strings"
|
|
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
const CtxUser = "user"
|
|
const CtxUserRight = "userRight"
|
|
const CtxRole = "role"
|
|
const CtxToken = "token"
|
|
|
|
type IntrospectService interface {
|
|
Introspect(token string) (user *model.User, err error)
|
|
GetRole(ctx context.Context, user *model.User) (userRight *model2.UserRight, err error)
|
|
GetAllRole(ctx context.Context) ([]*model2.Role, error)
|
|
}
|
|
|
|
func GetAuthenticationMiddleware(introspectService IntrospectService, jwtService *jwt.Service) gin.HandlerFunc {
|
|
|
|
return func(c *gin.Context) {
|
|
token, err := getTokenFromGinCtx(c)
|
|
c.Set(CtxToken, token)
|
|
|
|
ctx := c.Request.Context()
|
|
ctx = context.WithValue(ctx, CtxToken, token)
|
|
if err != nil {
|
|
logger.GetLogger().WithError(err).Debug("no token found")
|
|
responses.JSONErrorWithMessage(c.Writer, responses.ErrBadRequestFormat, err.Error())
|
|
c.Abort()
|
|
return
|
|
}
|
|
|
|
_, err = jwtService.ValidateToken(token)
|
|
if err != nil {
|
|
logger.GetLogger().WithError(err).Debug("error during token validation")
|
|
responses.JSONErrorWithMessage(c.Writer, responses.ErrBadRequestFormat, err.Error())
|
|
c.Abort()
|
|
return
|
|
}
|
|
user, err := introspectService.Introspect(token)
|
|
if err != nil {
|
|
logger.GetLogger().WithError(err).Debug("error during introspect")
|
|
responses.JSONErrorWithMessage(c.Writer, responses.ErrBadRequestFormat, err.Error())
|
|
c.Abort()
|
|
return
|
|
}
|
|
c.Set(CtxUser, user)
|
|
|
|
userRight, err := introspectService.GetRole(ctx, user)
|
|
if err != nil {
|
|
logger.GetLogger().WithError(err).Debug("error during getting role for user")
|
|
responses.JSONErrorWithMessage(c.Writer, responses.ErrBadRequestFormat, err.Error())
|
|
c.Abort()
|
|
return
|
|
}
|
|
c.Set(CtxUserRight, userRight)
|
|
|
|
roles, err := introspectService.GetAllRole(ctx)
|
|
if err != nil {
|
|
logger.GetLogger().WithError(err).Debug("error during getting role map")
|
|
responses.JSONErrorWithMessage(c.Writer, responses.ErrBadRequestFormat, err.Error())
|
|
c.Abort()
|
|
return
|
|
}
|
|
c.Set(CtxRole, roles)
|
|
|
|
c.Next()
|
|
}
|
|
}
|
|
|
|
// getTokenFromGinCtx allow to get the access token of the request in the Authorization request header.
|
|
// It will split the header and remove the Bearer part to extract only the token.
|
|
func getTokenFromGinCtx(c *gin.Context) (string, error) {
|
|
auth := c.GetHeader("Authorization")
|
|
if auth != "" {
|
|
authSplitted := strings.SplitN(auth, " ", 2)
|
|
if len(authSplitted) != 2 {
|
|
return "", errors.New("malformed authorization header")
|
|
}
|
|
|
|
if strings.ToUpper(authSplitted[0]) != strings.ToUpper("Bearer") && strings.ToUpper(authSplitted[0]) != strings.ToUpper("JWT") {
|
|
return "", errors.New("unsupported authentication scheme")
|
|
}
|
|
|
|
return authSplitted[1], nil
|
|
}
|
|
|
|
if cookie, err := c.Cookie("token"); err == nil {
|
|
return cookie, nil
|
|
}
|
|
|
|
return "", errors.New("no token found in the request")
|
|
}
|