Fix Turnstile verification encoding and admin login diagnostics
This commit is contained in:
parent
416fbc6fc1
commit
e0fd5cea8c
|
|
@ -83,17 +83,24 @@ func (h *AdminHandler) AdminLogin(c *gin.Context) {
|
||||||
|
|
||||||
// Verify Turnstile token
|
// Verify Turnstile token
|
||||||
if h.turnstileSecret != "" {
|
if h.turnstileSecret != "" {
|
||||||
|
if strings.TrimSpace(req.TurnstileToken) == "" {
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Security verification failed"})
|
||||||
|
return
|
||||||
|
}
|
||||||
turnstileService := services.NewTurnstileService(h.turnstileSecret)
|
turnstileService := services.NewTurnstileService(h.turnstileSecret)
|
||||||
remoteIP := c.ClientIP()
|
turnstileResp, err := turnstileService.VerifyToken(req.TurnstileToken, "")
|
||||||
turnstileResp, err := turnstileService.VerifyToken(req.TurnstileToken, remoteIP)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("Admin login: Turnstile verification failed")
|
log.Error().Err(err).Msg("Admin login: Turnstile verification failed")
|
||||||
c.JSON(http.StatusBadRequest, gin.H{"error": "Security verification failed"})
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Security verification failed"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !turnstileResp.Success {
|
if !turnstileResp.Success {
|
||||||
log.Warn().Strs("errors", turnstileResp.ErrorCodes).Msg("Admin login: Turnstile validation failed")
|
log.Warn().
|
||||||
c.JSON(http.StatusForbidden, gin.H{"error": "Security verification failed. Please try again."})
|
Strs("errors", turnstileResp.ErrorCodes).
|
||||||
|
Str("hostname", turnstileResp.Hostname).
|
||||||
|
Str("action", turnstileResp.Action).
|
||||||
|
Msg("Admin login: Turnstile validation failed")
|
||||||
|
c.JSON(http.StatusBadRequest, gin.H{"error": "Security verification failed"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
@ -39,22 +40,18 @@ func (s *TurnstileService) VerifyToken(token, remoteIP string) (*TurnstileRespon
|
||||||
return &TurnstileResponse{Success: true}, nil
|
return &TurnstileResponse{Success: true}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Prepare the request data
|
// Prepare the request data (properly form-encoded)
|
||||||
data := fmt.Sprintf(
|
// Note: We intentionally do NOT send remoteip. In practice this often causes false negatives
|
||||||
"secret=%s&response=%s",
|
// behind proxies/CDNs (Cloudflare), and Turnstile does not require it.
|
||||||
s.secretKey,
|
form := url.Values{}
|
||||||
token,
|
form.Set("secret", s.secretKey)
|
||||||
)
|
form.Set("response", token)
|
||||||
|
|
||||||
if remoteIP != "" {
|
|
||||||
data += fmt.Sprintf("&remoteip=%s", remoteIP)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make the request to Cloudflare
|
// Make the request to Cloudflare
|
||||||
resp, err := s.client.Post(
|
resp, err := s.client.Post(
|
||||||
"https://challenges.cloudflare.com/turnstile/v0/siteverify",
|
"https://challenges.cloudflare.com/turnstile/v0/siteverify",
|
||||||
"application/x-www-form-urlencoded",
|
"application/x-www-form-urlencoded",
|
||||||
bytes.NewBufferString(data),
|
bytes.NewBufferString(form.Encode()),
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("failed to verify turnstile token: %w", err)
|
return nil, fmt.Errorf("failed to verify turnstile token: %w", err)
|
||||||
|
|
@ -79,13 +76,13 @@ func (s *TurnstileService) VerifyToken(token, remoteIP string) (*TurnstileRespon
|
||||||
// GetErrorMessage returns a user-friendly error message for error codes
|
// GetErrorMessage returns a user-friendly error message for error codes
|
||||||
func (s *TurnstileService) GetErrorMessage(errorCodes []string) string {
|
func (s *TurnstileService) GetErrorMessage(errorCodes []string) string {
|
||||||
errorMessages := map[string]string{
|
errorMessages := map[string]string{
|
||||||
"missing-input-secret": "Server configuration error",
|
"missing-input-secret": "Server configuration error",
|
||||||
"invalid-input-secret": "Server configuration error",
|
"invalid-input-secret": "Server configuration error",
|
||||||
"missing-input-response": "Please complete the security check",
|
"missing-input-response": "Please complete the security check",
|
||||||
"invalid-input-response": "Security check failed, please try again",
|
"invalid-input-response": "Security check failed, please try again",
|
||||||
"bad-request": "Invalid request format",
|
"bad-request": "Invalid request format",
|
||||||
"timeout-or-duplicate": "Security check expired, please try again",
|
"timeout-or-duplicate": "Security check expired, please try again",
|
||||||
"internal-error": "Verification service unavailable",
|
"internal-error": "Verification service unavailable",
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, code := range errorCodes {
|
for _, code := range errorCodes {
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue