Replace token-based admin auth with JWT session authentication
CI / test (push) Failing after 12m45s
CI / test (push) Failing after 12m45s
- Add AdminUser model (bcrypt hashed passwords) and admin_users table - Add AdminJWTService for HS256 JWT sessions (24h TTL) - Add AdminSessionAuth middleware for /api/v1/admin/* routes - Add admin handlers: login, logout, me, change-password, users CRUD - Keys and model management routes now require admin JWT session - Remove ADMIN_TOKEN, add ADMIN_USERNAME, ADMIN_PASSWORD env vars - Update frontend: username/password login, admin_session storage, AdminUsers CRUD view
This commit is contained in:
@@ -14,6 +14,7 @@ import (
|
||||
const (
|
||||
ApiKeyCtx = "api_key"
|
||||
ApiKeyIDCtx = "api_key_id"
|
||||
AdminCtx = "admin_user"
|
||||
)
|
||||
|
||||
func APIKeyAuth(authService *auth.Service) gin.HandlerFunc {
|
||||
@@ -142,6 +143,46 @@ func AdminTokenAuth(token string) gin.HandlerFunc {
|
||||
}
|
||||
}
|
||||
|
||||
func AdminSessionAuth(jwtService *auth.AdminJWTService) gin.HandlerFunc {
|
||||
return func(c *gin.Context) {
|
||||
authHeader := c.GetHeader("Authorization")
|
||||
if authHeader == "" {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
|
||||
"error": gin.H{
|
||||
"code": "unauthorized",
|
||||
"message": "Authorization header required",
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
token := strings.TrimPrefix(authHeader, "Bearer ")
|
||||
if token == authHeader || strings.HasPrefix(token, auth.TokenPrefix) {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
|
||||
"error": gin.H{
|
||||
"code": "unauthorized",
|
||||
"message": "Admin session required",
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
claims, err := jwtService.VerifyToken(token)
|
||||
if err != nil {
|
||||
c.AbortWithStatusJSON(http.StatusUnauthorized, gin.H{
|
||||
"error": gin.H{
|
||||
"code": "unauthorized",
|
||||
"message": "Invalid or expired session",
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
c.Set(AdminCtx, claims)
|
||||
c.Next()
|
||||
}
|
||||
}
|
||||
|
||||
func GetAPIKeyID(c *gin.Context) uuid.UUID {
|
||||
id, _ := c.Get(ApiKeyIDCtx)
|
||||
return id.(uuid.UUID)
|
||||
@@ -154,3 +195,11 @@ func GetAPIKey(c *gin.Context) *db.ApiKey {
|
||||
}
|
||||
return key.(*db.ApiKey)
|
||||
}
|
||||
|
||||
func GetAdminClaims(c *gin.Context) *auth.AdminClaims {
|
||||
claims, _ := c.Get(AdminCtx)
|
||||
if claims == nil {
|
||||
return nil
|
||||
}
|
||||
return claims.(*auth.AdminClaims)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user