diff --git a/ordinis-admin-ui/src/api/client.ts b/ordinis-admin-ui/src/api/client.ts index 8520ee3..f9c25fd 100644 --- a/ordinis-admin-ui/src/api/client.ts +++ b/ordinis-admin-ui/src/api/client.ts @@ -72,13 +72,22 @@ apiClient.interceptors.request.use((config) => { return config }) -// Единственный 401 interceptor. Логика silent renew / redirect / loop guard -// делегируется handler'у который TokenSync устанавливает через -// setUnauthorizedHandler(). +// Auth-related interceptor. 401 классический «нет/невалидный JWT» → +// handler делает silent renew / redirect. +// +// 403 + accessToken=null обрабатывается так же. Корень: на проде +// ORDINIS_AUTH_REQUIRED=false → Spring Security пропускает anonymous → +// контроллер видит PUBLIC scope → отдаёт 403 (не 401). Это происходит +// когда silent-renew падает, oidc-client-ts убирает user, accessToken +// зануляется → следующий запрос идёт без Bearer. Без этой ветки юзер +// залипал на 403 и видел «forbidden» вместо relogin redirect'а. apiClient.interceptors.response.use( (resp) => resp, (error) => { - if (error?.response?.status === 401 && unauthorizedHandler) { + const status = error?.response?.status + const needsReauth = + status === 401 || (status === 403 && accessToken == null) + if (needsReauth && unauthorizedHandler) { try { unauthorizedHandler(error) } catch (e) {