Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
edad65d6a9 | ||
|
|
486c972bba |
@@ -34,7 +34,7 @@ func NewMembershipController(service *service.MembershipService, auth *middlewar
|
|||||||
}
|
}
|
||||||
|
|
||||||
routeGroups.Auth.Post("/login", mc.Login)
|
routeGroups.Auth.Post("/login", mc.Login)
|
||||||
routeGroups.Auth.Post("/open-token", mc.GenerateOpenToken)
|
routeGroups.Auth.Post("/open-token", mc.auth.Authenticate, mc.GenerateOpenToken)
|
||||||
|
|
||||||
usersGroup := routeGroups.Membership
|
usersGroup := routeGroups.Membership
|
||||||
usersGroup.Use(mc.auth.Authenticate)
|
usersGroup.Use(mc.auth.Authenticate)
|
||||||
|
|||||||
@@ -52,20 +52,28 @@ func NewAuthMiddleware(ms *service.MembershipService, cache *cache.InMemoryCache
|
|||||||
|
|
||||||
// Authenticate is a middleware for JWT authentication with enhanced security.
|
// Authenticate is a middleware for JWT authentication with enhanced security.
|
||||||
func (m *AuthMiddleware) AuthenticateOpen(ctx *fiber.Ctx) error {
|
func (m *AuthMiddleware) AuthenticateOpen(ctx *fiber.Ctx) error {
|
||||||
return m.AuthenticateWithHandler(m.openJWTHandler.JWTHandler, ctx)
|
return m.AuthenticateWithHandler(m.openJWTHandler.JWTHandler, true, ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Authenticate is a middleware for JWT authentication with enhanced security.
|
// Authenticate is a middleware for JWT authentication with enhanced security.
|
||||||
func (m *AuthMiddleware) Authenticate(ctx *fiber.Ctx) error {
|
func (m *AuthMiddleware) Authenticate(ctx *fiber.Ctx) error {
|
||||||
return m.AuthenticateWithHandler(m.jwtHandler, ctx)
|
return m.AuthenticateWithHandler(m.jwtHandler, false, ctx)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m *AuthMiddleware) AuthenticateWithHandler(jwtHandler *jwt.JWTHandler, ctx *fiber.Ctx) error {
|
func (m *AuthMiddleware) AuthenticateWithHandler(jwtHandler *jwt.JWTHandler, isOpenToken bool, ctx *fiber.Ctx) error {
|
||||||
// Log authentication attempt
|
// Log authentication attempt
|
||||||
ip := ctx.IP()
|
ip := ctx.IP()
|
||||||
userAgent := ctx.Get("User-Agent")
|
userAgent := ctx.Get("User-Agent")
|
||||||
|
|
||||||
authHeader := ctx.Get("Authorization")
|
authHeader := ctx.Get("Authorization")
|
||||||
|
|
||||||
|
if jwtHandler.IsOpenToken && !isOpenToken {
|
||||||
|
logging.Error("Authentication failed: attempting to authenticate with open token")
|
||||||
|
return ctx.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||||
|
"error": "Wrong token type used",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
if authHeader == "" {
|
if authHeader == "" {
|
||||||
logging.Error("Authentication failed: missing Authorization header from IP %s", ip)
|
logging.Error("Authentication failed: missing Authorization header from IP %s", ip)
|
||||||
return ctx.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
return ctx.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||||
@@ -98,6 +106,13 @@ func (m *AuthMiddleware) AuthenticateWithHandler(jwtHandler *jwt.JWTHandler, ctx
|
|||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if !jwtHandler.IsOpenToken && claims.IsOpenToken {
|
||||||
|
logging.Error("Authentication failed: attempting to authenticate with open token")
|
||||||
|
return ctx.Status(fiber.StatusUnauthorized).JSON(fiber.Map{
|
||||||
|
"error": "Wrong token type used",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
// Additional security: validate user ID format
|
// Additional security: validate user ID format
|
||||||
if claims.UserID == "" || len(claims.UserID) < 10 {
|
if claims.UserID == "" || len(claims.UserID) < 10 {
|
||||||
logging.Error("Authentication failed: invalid user ID in token from IP %s", ip)
|
logging.Error("Authentication failed: invalid user ID in token from IP %s", ip)
|
||||||
|
|||||||
@@ -63,16 +63,11 @@ func (s *MembershipService) Login(ctx context.Context, username, password string
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
return s.jwtHandler.GenerateToken(user)
|
return s.jwtHandler.GenerateToken(user.ID.String())
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *MembershipService) GenerateOpenToken(ctx context.Context, userId string) (string, error) {
|
func (s *MembershipService) GenerateOpenToken(ctx context.Context, userId string) (string, error) {
|
||||||
user, err := s.repo.GetByID(ctx, userId)
|
return s.openJwtHandler.GenerateToken(userId)
|
||||||
if err != nil {
|
|
||||||
return "", err
|
|
||||||
}
|
|
||||||
|
|
||||||
return s.openJwtHandler.GenerateToken(user)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// CreateUser creates a new user.
|
// CreateUser creates a new user.
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
Version = "0.10.5"
|
Version = "0.10.6"
|
||||||
Prefix = "v1"
|
Prefix = "v1"
|
||||||
Secret string
|
Secret string
|
||||||
SecretCode string
|
SecretCode string
|
||||||
|
|||||||
@@ -14,11 +14,13 @@ import (
|
|||||||
// Claims represents the JWT claims.
|
// Claims represents the JWT claims.
|
||||||
type Claims struct {
|
type Claims struct {
|
||||||
UserID string `json:"user_id"`
|
UserID string `json:"user_id"`
|
||||||
|
IsOpenToken bool `json:"is_open_token"`
|
||||||
jwt.RegisteredClaims
|
jwt.RegisteredClaims
|
||||||
}
|
}
|
||||||
|
|
||||||
type JWTHandler struct {
|
type JWTHandler struct {
|
||||||
SecretKey []byte
|
SecretKey []byte
|
||||||
|
IsOpenToken bool
|
||||||
}
|
}
|
||||||
|
|
||||||
type OpenJWTHandler struct {
|
type OpenJWTHandler struct {
|
||||||
@@ -28,6 +30,7 @@ type OpenJWTHandler struct {
|
|||||||
// NewJWTHandler creates a new JWTHandler instance with the provided secret key.
|
// NewJWTHandler creates a new JWTHandler instance with the provided secret key.
|
||||||
func NewOpenJWTHandler(jwtSecret string) *OpenJWTHandler {
|
func NewOpenJWTHandler(jwtSecret string) *OpenJWTHandler {
|
||||||
jwtHandler := NewJWTHandler(jwtSecret)
|
jwtHandler := NewJWTHandler(jwtSecret)
|
||||||
|
jwtHandler.IsOpenToken = true
|
||||||
return &OpenJWTHandler{
|
return &OpenJWTHandler{
|
||||||
JWTHandler: jwtHandler,
|
JWTHandler: jwtHandler,
|
||||||
}
|
}
|
||||||
@@ -68,13 +71,14 @@ func (jh *JWTHandler) GenerateSecretKey() string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// GenerateToken generates a new JWT for a given user.
|
// GenerateToken generates a new JWT for a given user.
|
||||||
func (jh *JWTHandler) GenerateToken(user *model.User) (string, error) {
|
func (jh *JWTHandler) GenerateToken(userId string) (string, error) {
|
||||||
expirationTime := time.Now().Add(24 * time.Hour)
|
expirationTime := time.Now().Add(24 * time.Hour)
|
||||||
claims := &Claims{
|
claims := &Claims{
|
||||||
UserID: user.ID.String(),
|
UserID: userId,
|
||||||
RegisteredClaims: jwt.RegisteredClaims{
|
RegisteredClaims: jwt.RegisteredClaims{
|
||||||
ExpiresAt: jwt.NewNumericDate(expirationTime),
|
ExpiresAt: jwt.NewNumericDate(expirationTime),
|
||||||
},
|
},
|
||||||
|
IsOpenToken: jh.IsOpenToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||||
@@ -88,6 +92,7 @@ func (jh *JWTHandler) GenerateTokenWithExpiry(user *model.User, expiry time.Time
|
|||||||
RegisteredClaims: jwt.RegisteredClaims{
|
RegisteredClaims: jwt.RegisteredClaims{
|
||||||
ExpiresAt: jwt.NewNumericDate(expirationTime),
|
ExpiresAt: jwt.NewNumericDate(expirationTime),
|
||||||
},
|
},
|
||||||
|
IsOpenToken: jh.IsOpenToken,
|
||||||
}
|
}
|
||||||
|
|
||||||
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ func GenerateTestToken() (string, error) {
|
|||||||
jwtHandler := jwt.NewJWTHandler(testSecret)
|
jwtHandler := jwt.NewJWTHandler(testSecret)
|
||||||
|
|
||||||
// Generate JWT token
|
// Generate JWT token
|
||||||
token, err := jwtHandler.GenerateToken(user)
|
token, err := jwtHandler.GenerateToken(user.ID.String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", fmt.Errorf("failed to generate test token: %w", err)
|
return "", fmt.Errorf("failed to generate test token: %w", err)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ func TestJWT_GenerateAndValidateToken(t *testing.T) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Test JWT generation
|
// Test JWT generation
|
||||||
token, err := jwtHandler.GenerateToken(user)
|
token, err := jwtHandler.GenerateToken(user.ID.String())
|
||||||
tests.AssertNoError(t, err)
|
tests.AssertNoError(t, err)
|
||||||
tests.AssertNotNil(t, token)
|
tests.AssertNotNil(t, token)
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user