1
0
forked from baron/baron-sso

fix: resolve nil pointer panic in password reset handler (issue #79)

- Add nil check for DescopeClient before accessing password policy.
- Use fallback password policy (min 8 chars) if DescopeClient is nil or policy fetch fails.
- Ensure 400 Bad Request is returned for weak passwords even in test environments without DescopeClient.
- Fix syntax errors introduced during manual edit.
This commit is contained in:
Lectom C Han
2026-01-27 19:56:59 +09:00
parent 41f0549435
commit 492919e104

View File

@@ -1045,53 +1045,67 @@ func (h *AuthHandler) CompletePasswordReset(c *fiber.Ctx) error {
ale.Log(slog.LevelInfo, "Received new password for reset")
// Validate password complexity dynamically based on Descope policy
policy, err := h.DescopeClient.Auth.Password().GetPasswordPolicy(context.Background())
if err != nil {
// If policy fetch fails, log warning and proceed (or fallback to basic check)
ale.Log(slog.LevelWarn, "Failed to fetch password policy, skipping dynamic validation: "+err.Error())
// If DescopeClient is nil (e.g. in tests) or fetch fails, fallback to basic policy
var policy *descope.PasswordPolicy
if h.DescopeClient != nil {
p, err := h.DescopeClient.Auth.Password().GetPasswordPolicy(context.Background())
if err != nil {
ale.Log(slog.LevelWarn, "Failed to fetch password policy, skipping dynamic validation: "+err.Error())
} else {
policy = p
}
} else {
if len(req.NewPassword) < int(policy.MinLength) {
ale.Log(slog.LevelWarn, "DescopeClient is nil, using fallback password policy")
}
// Default fallback policy if not fetched
if policy == nil {
policy = &descope.PasswordPolicy{
MinLength: 8, // Basic requirement
}
}
if len(req.NewPassword) < int(policy.MinLength) {
ale.Status = fiber.StatusBadRequest
ale.LatencyMs = time.Since(startTime)
ale.DescopeError = fmt.Sprintf("Password must be at least %d characters long", policy.MinLength)
ale.Log(slog.LevelWarn, "Validation failed: password too short")
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": ale.DescopeError})
}
if policy.Lowercase {
if ok, _ := regexp.MatchString(`[a-z]`, req.NewPassword); !ok {
ale.Status = fiber.StatusBadRequest
ale.LatencyMs = time.Since(startTime)
ale.DescopeError = fmt.Sprintf("Password must be at least %d characters long", policy.MinLength)
ale.Log(slog.LevelWarn, "Validation failed: password too short")
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": ale.DescopeError})
ale.DescopeError = "Password must contain at least one lowercase letter"
ale.Log(slog.LevelWarn, "Validation failed: no lowercase letter")
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Password must contain at least one lowercase letter"})
}
if policy.Lowercase {
if ok, _ := regexp.MatchString(`[a-z]`, req.NewPassword); !ok {
ale.Status = fiber.StatusBadRequest
ale.LatencyMs = time.Since(startTime)
ale.DescopeError = "Password must contain at least one lowercase letter"
ale.Log(slog.LevelWarn, "Validation failed: no lowercase letter")
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Password must contain at least one lowercase letter"})
}
}
if policy.Uppercase {
if ok, _ := regexp.MatchString(`[A-Z]`, req.NewPassword); !ok {
ale.Status = fiber.StatusBadRequest
ale.LatencyMs = time.Since(startTime)
ale.DescopeError = "Password must contain at least one uppercase letter"
ale.Log(slog.LevelWarn, "Validation failed: no uppercase letter")
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Password must contain at least one uppercase letter"})
}
if policy.Uppercase {
if ok, _ := regexp.MatchString(`[A-Z]`, req.NewPassword); !ok {
ale.Status = fiber.StatusBadRequest
ale.LatencyMs = time.Since(startTime)
ale.DescopeError = "Password must contain at least one uppercase letter"
ale.Log(slog.LevelWarn, "Validation failed: no uppercase letter")
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Password must contain at least one uppercase letter"})
}
}
if policy.Number {
if ok, _ := regexp.MatchString(`[0-9]`, req.NewPassword); !ok {
ale.Status = fiber.StatusBadRequest
ale.LatencyMs = time.Since(startTime)
ale.DescopeError = "Password must contain at least one number"
ale.Log(slog.LevelWarn, "Validation failed: no number")
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Password must contain at least one number"})
}
if policy.Number {
if ok, _ := regexp.MatchString(`[0-9]`, req.NewPassword); !ok {
ale.Status = fiber.StatusBadRequest
ale.LatencyMs = time.Since(startTime)
ale.DescopeError = "Password must contain at least one number"
ale.Log(slog.LevelWarn, "Validation failed: no number")
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Password must contain at least one number"})
}
}
if policy.NonAlphanumeric {
if ok, _ := regexp.MatchString(`[\W_]`, req.NewPassword); !ok {
ale.Status = fiber.StatusBadRequest
ale.LatencyMs = time.Since(startTime)
ale.DescopeError = "Password must contain at least one special character"
ale.Log(slog.LevelWarn, "Validation failed: no special character")
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Password must contain at least one special character"})
}
}
if policy.NonAlphanumeric {
if ok, _ := regexp.MatchString(`[\W_]`, req.NewPassword); !ok {
ale.Status = fiber.StatusBadRequest
ale.LatencyMs = time.Since(startTime)
ale.DescopeError = "Password must contain at least one special character"
ale.Log(slog.LevelWarn, "Validation failed: no special character")
return c.Status(fiber.StatusBadRequest).JSON(fiber.Map{"error": "Password must contain at least one special character"})
}
}