Files
lti-api/internal/middleware/auth.go
T

113 lines
3.3 KiB
Go

package middleware
import (
"strings"
"gitlab.com/mbugroup/lti-api.git/internal/config"
"gitlab.com/mbugroup/lti-api.git/internal/modules/sso/session"
service "gitlab.com/mbugroup/lti-api.git/internal/modules/users/services"
"gitlab.com/mbugroup/lti-api.git/internal/sso"
"gitlab.com/mbugroup/lti-api.git/internal/utils"
"github.com/gofiber/fiber/v2"
)
func Auth(userService service.UserService, requiredRights ...string) fiber.Handler {
return func(c *fiber.Ctx) error {
authHeader := c.Get("Authorization")
token := strings.TrimSpace(strings.TrimPrefix(authHeader, "Bearer "))
if token == "" {
cookieName := config.SSOAccessCookieName
if cookieName == "" {
cookieName = "access"
}
token = strings.TrimSpace(c.Cookies(cookieName))
}
if token == "" {
return fiber.NewError(fiber.StatusUnauthorized, "Please authenticate")
}
verification, err := sso.VerifyAccessToken(token)
if err != nil {
return fiber.NewError(fiber.StatusUnauthorized, "Please authenticate")
}
if len(config.SSOAllowedAudiences) > 0 {
allowed := make(map[string]struct{}, len(config.SSOAllowedAudiences))
for _, aud := range config.SSOAllowedAudiences {
aud = strings.TrimSpace(aud)
if aud != "" {
allowed[aud] = struct{}{}
}
}
audienceValid := false
for _, aud := range verification.Claims.Audience {
if _, ok := allowed[aud]; ok {
audienceValid = true
break
}
}
if !audienceValid {
return fiber.NewError(fiber.StatusUnauthorized, "invalid audience")
}
}
if revoker := session.GetRevocationStore(); revoker != nil {
logoutAt, err := revoker.UserLogoutTime(c.Context(), verification.UserID)
if err != nil {
utils.Log.WithError(err).Warn("failed to load logout marker")
return fiber.NewError(fiber.StatusUnauthorized, "Please authenticate")
}
if !logoutAt.IsZero() {
if verification.Claims.IssuedAt == nil || !verification.Claims.IssuedAt.Time.After(logoutAt) {
return fiber.NewError(fiber.StatusUnauthorized, "Please authenticate")
}
}
if fingerprint := session.TokenFingerprint(token); fingerprint != "" {
revoked, err := revoker.IsRevoked(c.Context(), fingerprint)
if err != nil {
utils.Log.WithError(err).Warn("failed to check token revocation")
return fiber.NewError(fiber.StatusUnauthorized, "Please authenticate")
}
if revoked {
return fiber.NewError(fiber.StatusUnauthorized, "Please authenticate")
}
}
}
user, err := userService.GetBySSOUserID(c, verification.UserID)
if err != nil || user == nil {
return fiber.NewError(fiber.StatusUnauthorized, "Please authenticate")
}
c.Locals("user", user)
c.Locals("token_claims", verification.Claims)
// if len(requiredRights) > 0 {
// userRights, hasRights := config.RoleRights[user.Role]
// if (!hasRights || !hasAllRights(userRights, requiredRights)) && c.Params("userId") != userID {
// return fiber.NewError(fiber.StatusForbidden, "You don't have permission to access this resource")
// }
// }
return c.Next()
}
}
// func hasAllRights(userRights, requiredRights []string) bool {
// rightSet := make(map[string]struct{}, len(userRights))
// for _, right := range userRights {
// rightSet[right] = struct{}{}
// }
// for _, right := range requiredRights {
// if _, exists := rightSet[right]; !exists {
// return false
// }
// }
// return true
// }