Skip to content

fix(customer): restore storefront login and session auth#321

Open
Ibochkarev wants to merge 9 commits into
betafrom
fix/285-customer-auth
Open

fix(customer): restore storefront login and session auth#321
Ibochkarev wants to merge 9 commits into
betafrom
fix/285-customer-auth

Conversation

@Ibochkarev

@Ibochkarev Ibochkarev commented Jun 15, 2026

Copy link
Copy Markdown
Member

Описание

Починена авторизация покупателя на витрине и в ЛК (#285): после входа сессия не держалась, редирект возвращал на login, повторный вход падал, пароль из менеджера не сходился с проверкой на витрине.

Корневые причины

  • AuthUI читал result.object, Web API отдаёт payload в data
  • SSR ЛК не поднимал сессию из httpOnly cookie
  • после login token/get / middleware могли затереть auth guest-токеном
  • snippet ?action=logout чистил только PHP-сессию и оставлял auth cookie (с restoreSessionFromCookie это снова логинило)
  • manager: пустой пароль / trim / разный hash path vs витрина; email без нормализации регистра
  • отсутствовал маршрут POST /api/v1/customer/logout (API logout → 404)

Backend

  • AuthManager::establishCustomerSession() — bind customer ↔ token ↔ cookie ↔ session ↔ draft; ротация токена на login
  • AuthManager::logoutCurrentCustomer() — общий logout для API и snippet
  • TokenService::restoreSessionFromCookie() + restore-before-mint; guest token не затирает auth customer_id
  • TokenService::persistApiToken() / sessionTokenBelongsToCustomer() — единый mint/hydrate path
  • PasswordAuthProvider::normalizeEmail() / hashPassword(); manager update через тот же path
  • SessionHelper::ensureActive(); session_regenerate_id(true) после login
  • web.php: POST /api/v1/customer/logoutLogout processor (+ tokenMiddleware)

Frontend

  • ApiClient.getPayload()data с fallback на object
  • AuthUI берёт redirect из getPayload

Тесты

  • CustomerAuthNormalizeEmailTest.php
  • CustomerAuthSessionSemanticsTest.php (policy smoke, не full MODX E2E)

Тип изменений

  • Исправление бага (non-breaking change)
  • Новая функциональность (non-breaking change)
  • Breaking change (изменение, ломающее обратную совместимость)
  • Рефакторинг (без изменения функциональности)
  • Документация
  • Другое (опишите):

Связанные Issues

Closes #285

Как это было протестировано?

  • Ручное тестирование на живом MODX (https://project.test, 2026-07-16)
  • Автоматические проверки в этой ветке
  • Тестирование на разных версиях PHP/MODX

Конфигурация:

  • MiniShop3: fix/285-customer-auth (tip 152fdc4 + локально web.php logout route)
  • MODX: 3.2.0-pl, стенд project.test
  • PHP: 8.2+
  • Тестовая страница: ресурс #2051 (ms3-customer-auth-test.html, [[!msCustomer]])
  • Тестовый клиент: #433 (http-order1779591899@test.local)

Gate (exit 0):

  • php -l на затронутых PHP
  • php core/components/minishop3/tests/CustomerAuthNormalizeEmailTest.php
  • php core/components/minishop3/tests/CustomerAuthSessionSemanticsTest.php

Ручной чеклист — результаты

# Сценарий Результат
1 Менеджер → задать пароль MgrPass285! → вход на витрине OK: redirect на #2051, профиль
2 Reload страницы профиля OK: SSR восстанавливает сессию из cookie
3 Менеджер → сохранить с пустым паролем OK: hash не сброшен, вход старым паролем работает
4 Email с другим регистром OK (API)
5 Logout (?action=logout) → снова открыть ЛК OK: форма login, не профиль
6 Повторный login после logout OK (UI + API)
7 Token rotation: guest token ≠ login token OK
8 API POST /customer/logout OK после добавления маршрута; сообщение RU
9 Неверный пароль OK: «Неверный email или пароль» (RU)

Примечания по стенду

  • Для redirect после login временно выставлен ms3_customer_redirect_after_login = 2051
  • Snippet/chunk msCustomer синхронизированы с файлами в БД MODX
  • Маршрут logout в web.php проверен на live; в ветке пока uncommitted — нужен отдельный commit перед merge

Скриншоты (если применимо)

До После

Чеклист

  • Код соответствует стилю проекта
  • Добавлены/обновлены комментарии в сложных местах
  • Изменения не ломают существующую функциональность
  • Лексиконы добавлены на двух языках (ru/en)
  • PHPStan проходит без новых ошибок
  • ESLint проходит без ошибок (для JS/Vue изменений) — Vue не трогали
  • Обновлён CHANGELOG.md — maintainer при релизе

Дополнительные заметки

  • При регистрации с новым токеном вызывается bindDraftToCustomer().
  • Если auto-login после register не смог установить сессию, аккаунт уже создан: success + ms3_customer_register_success_login_required и redirect на login (не «email занят» при повторе).
  • Вне scope: полный split TokenService / snippet secrets; email-verification path с legacy msCustomer.token.
  • Review: security HIGH по snippet logout закрыт через logoutCurrentCustomer().
  • Ручной прогон выполнен по просьбе @biz87.

@Ibochkarev Ibochkarev requested a review from biz87 June 15, 2026 17:27
@biz87

biz87 commented Jun 15, 2026

Copy link
Copy Markdown
Member

Вань, серьезные изменения. А ты это проверял руками? Или как всегда только теоритическая автоматизированная проверка?

@Ibochkarev

Copy link
Copy Markdown
Member Author

Вань, серьезные изменения. А ты это проверял руками? Или как всегда только теоритическая автоматизированная проверка?

Привет!

Давай пока не вливать, дополнительно все протестирую

@Ibochkarev Ibochkarev changed the title fix(customer): restore storefront login and session auth (#285) fix(customer): restore storefront login and session auth Jul 16, 2026
@Ibochkarev Ibochkarev added the bug Something isn't working label Jul 16, 2026
Unify token/session binding after login and registration, restore SSR auth from cookie without minting guest tokens, and align email/password handling between manager and storefront.
Prevent guest token mint and middleware from wiping an authenticated
customer session, fail register auto-login when session bind fails, and
add focused regression tests for email normalize and API payload shape.
Snippet and API logout now revoke tokens, mint a guest cookie, and
extend TTL in DB on refresh. Registration keeps the account if
auto-login session bind fails and points the user to the login page.
@Ibochkarev Ibochkarev force-pushed the fix/285-customer-auth branch from 5c0654f to fa8e4f9 Compare July 16, 2026 05:56
@Ibochkarev

Ibochkarev commented Jul 16, 2026

Copy link
Copy Markdown
Member Author

@biz87, учёл твой комментарий: в описание PR добавил обязательный ручной чеклист перед merge (logout через сайдбар, пароль из менеджера, reload ЛК, token/get после login).

В этой итерации дополнительно:

  • единый logoutCurrentCustomer() для snippet ?action=logout и API (чтобы restoreSessionFromCookie не поднимал сессию после «выхода»);
  • restore-before-mint / guest не затирает auth customer_id;
  • register не отдаёт failure после уже созданного аккаунта, если auto-login session bind упал.

Автоматически прогнал php -l + два точечных теста. Живой стенд MODX в этой сессии не крутил — merge после ручного прогона по чеклисту в описании.

Fail register auto-login when session bind fails, clear customer_id on
guest token hydrate, enforce active/blocked checks in TokenMiddleware,
and harden save/TTL/session observability around auth flows.
Route login/logout/guest mint through TokenService::persistApiToken so
session/cookie hydrate from one DB row, move normalizeEmail to
AuthManager, and drop the misplaced PHP ApiClient payload test.
Return distinct blocked/inactive login messages without lockout increment,
add legacy email lookup with soft normalize on success, drop dead remember
checkbox, and add smoke tests for guest wipe and token reuse guards.
Mint a fresh token on establishCustomerSession, transfer guest/own draft
cart then revoke the old token, require session token ownership in
middleware/checkAuth, and clear local session after password reset revoke.
Pass raw email into authenticate/register for legacy case lookup, always
revoke the previous browser token after login rotation, enforce token
expiry in session ownership checks, and harden logout/clearAuthSession.
Expose POST /api/v1/customer/logout so AuthUI and API clients can revoke
the session token after login; closes the 404 gap found during #285 QA.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

bug Something isn't working

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Bug] Не работает авторизация покупателя

2 participants