* refactor(auth): replace dashboard sessions with stateless tokens * feat(auth): harden session issuance and distributed enforcement * fix(proxy): preserve trusted proxy compatibility defaults * refactor: address dashboard auth review feedback * refactor: remove classic frontend and flatten web app
61 lines
1.8 KiB
Go
61 lines
1.8 KiB
Go
package middleware
|
|
|
|
import (
|
|
"errors"
|
|
"net/http"
|
|
"strings"
|
|
|
|
"github.com/QuantumNous/new-api/service"
|
|
"github.com/gin-gonic/gin"
|
|
)
|
|
|
|
// SecureVerificationRequired protects channel key disclosure. Other sensitive
|
|
// operations validate their narrower proof scopes in their controller.
|
|
func SecureVerificationRequired() gin.HandlerFunc {
|
|
return func(c *gin.Context) {
|
|
if !RequireSecurityProof(c, "channel.key.read", []string{"2fa", "passkey"}) {
|
|
return
|
|
}
|
|
c.Set("secure_verified", true)
|
|
c.Next()
|
|
}
|
|
}
|
|
|
|
// RequireSecurityProof validates a proof against the authenticated dashboard
|
|
// session and writes the shared proof error contract on failure.
|
|
func RequireSecurityProof(c *gin.Context, requiredScope string, allowedMethods []string) bool {
|
|
identity, ok := GetSessionAuthIdentity(c)
|
|
if !ok {
|
|
securityProofError(c, "SECURITY_PROOF_INVALID", "安全验证状态无效")
|
|
return false
|
|
}
|
|
raw := strings.TrimSpace(c.GetHeader("X-Security-Proof"))
|
|
if raw == "" {
|
|
securityProofError(c, "SECURITY_PROOF_REQUIRED", "需要安全验证")
|
|
return false
|
|
}
|
|
if _, err := service.VerifySecurityProof(raw, identity, requiredScope, allowedMethods); err != nil {
|
|
switch {
|
|
case errors.Is(err, service.ErrAuthTokenExpired):
|
|
securityProofError(c, "SECURITY_PROOF_EXPIRED", "安全验证已过期")
|
|
case errors.Is(err, service.ErrProofScope):
|
|
securityProofError(c, "SECURITY_PROOF_SCOPE_MISMATCH", "安全验证范围不匹配")
|
|
case errors.Is(err, service.ErrProofMethod):
|
|
securityProofError(c, "SECURITY_PROOF_METHOD_MISMATCH", "安全验证方式不匹配")
|
|
default:
|
|
securityProofError(c, "SECURITY_PROOF_INVALID", "安全验证状态无效")
|
|
}
|
|
return false
|
|
}
|
|
return true
|
|
}
|
|
|
|
func securityProofError(c *gin.Context, code, message string) {
|
|
c.JSON(http.StatusForbidden, gin.H{
|
|
"success": false,
|
|
"message": message,
|
|
"code": code,
|
|
})
|
|
c.Abort()
|
|
}
|