diff --git a/backend/src/main/java/ru/micord/ervu/security/SecurityConstants.java b/backend/src/main/java/ru/micord/ervu/security/SecurityConstants.java index feafe00..be40765 100644 --- a/backend/src/main/java/ru/micord/ervu/security/SecurityConstants.java +++ b/backend/src/main/java/ru/micord/ervu/security/SecurityConstants.java @@ -5,4 +5,5 @@ public class SecurityConstants { public static final String AUTH_TOKEN = "auth_token"; public static final String AUTH_MARKER = "webbpm.ervu-lkrp-fl"; public static final String PRNS_UUID = "prns_uuid_fl"; + public static final String STICKY_SESSION = "stickysession"; } diff --git a/backend/src/main/java/ru/micord/ervu/security/esia/EsiaAuthInfoStore.java b/backend/src/main/java/ru/micord/ervu/security/esia/EsiaAuthInfoStore.java index b05860f..8f40e24 100644 --- a/backend/src/main/java/ru/micord/ervu/security/esia/EsiaAuthInfoStore.java +++ b/backend/src/main/java/ru/micord/ervu/security/esia/EsiaAuthInfoStore.java @@ -106,10 +106,12 @@ public class EsiaAuthInfoStore { }); } - public static void validateState(String prnsUUID, String state) { + public static void validateState(String prnsUUID, String state, String stickySession) { List states = PRNS_UUID_STATE_MAP.get(prnsUUID); if (states == null) { - throw new EsiaException("State invalid. No state found"); + throw new EsiaException( + "State invalid. No state found. PrnsUUID: " + prnsUUID + ". State: " + state + + ". Sticky session:" + stickySession); } long currentTime = System.currentTimeMillis(); @@ -117,13 +119,17 @@ public class EsiaAuthInfoStore { for (ExpiringState expiringState : states) { if (expiringState.getState().equals(state)) { if (expiringState.getExpiryTime() < currentTime) { - throw new EsiaException("State invalid. State : " + state + " expired at : " + expiringState.getExpiryTime()); + throw new EsiaException( + "State invalid. PrnsUUID: " + prnsUUID + ". Sticky session:" + stickySession + + ". State : " + state + " expired at : " + expiringState.getExpiryTime()); } return; } - statesStringBuilder.append(expiringState.getState(), 0, 8).append(", "); + statesStringBuilder.append(expiringState.getState()).append(", "); } - throw new EsiaException("State invalid. Backend states :" + statesStringBuilder + " cookie state :" + state); + throw new EsiaException( + "State invalid. PrnsUUID: " + prnsUUID + ". Sticky session:" + stickySession + + ". Backend states :" + statesStringBuilder + " cookie state :" + state); } public static void removeState(String prnsUUID) { diff --git a/backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaAuthService.java b/backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaAuthService.java index 126f2a3..fd45a01 100644 --- a/backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaAuthService.java +++ b/backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaAuthService.java @@ -60,6 +60,7 @@ import ru.micord.ervu.security.webbpm.jwt.model.Token; import ru.cg.webbpm.modules.core.runtime.api.MessageBundleUtils; import static ru.micord.ervu.security.SecurityConstants.PRNS_UUID; +import static ru.micord.ervu.security.SecurityConstants.STICKY_SESSION; /** * @author Eduard Tihomirov @@ -124,6 +125,10 @@ public class EsiaAuthService { String state = signResponse.getState(); String clientSecret = signResponse.getSignature(); EsiaAuthInfoStore.addState(prnsUUID, state, esiaConfig.getEsiaStateCookieLifeTime(), esiaConfig.getEsiaLoginAttemptsCount()); + Cookie stickySession = WebUtils.getCookie(request, STICKY_SESSION); + LOGGER.info("Auth states initialized: PrnsUUID: {}; State: {}; StickySession: {}", prnsUUID, state, + stickySession != null ? stickySession.getValue() : "is null" + ); ResponseCookie prnsCookie = securityHelper.createAccessCookie(PRNS_UUID, prnsUUID) .maxAge(esiaConfig.getEsiaStateCookieLifeTime()) .build(); @@ -519,15 +524,21 @@ public class EsiaAuthService { private void verifyStateFromCookie(HttpServletRequest request, String state, HttpServletResponse response) { Cookie cookie = WebUtils.getCookie(request, PRNS_UUID); + Cookie stickySessionCookie = WebUtils.getCookie(request, STICKY_SESSION); + String stickySession = stickySessionCookie != null ? stickySessionCookie.getValue() : "is null"; if (cookie == null) { - throw new EsiaException("State invalid. Cookie not found"); + throw new EsiaException( + "State invalid. Cookie not found. State: " + state + ". Sticky session: " + stickySession); } String prnsUUID = cookie.getValue(); try { - EsiaAuthInfoStore.validateState(prnsUUID, state); + EsiaAuthInfoStore.validateState(prnsUUID, state, stickySession); } finally { EsiaAuthInfoStore.removeState(prnsUUID); + LOGGER.info( + "Remove all states for prnsUUID: " + prnsUUID + ". State: " + state + ". Sticky session: " + + stickySession); securityHelper.clearAccessCookie(response, PRNS_UUID); } } diff --git a/frontend/src/ts/modules/security/guard/auth.guard.ts b/frontend/src/ts/modules/security/guard/auth.guard.ts index 427904d..341a012 100644 --- a/frontend/src/ts/modules/security/guard/auth.guard.ts +++ b/frontend/src/ts/modules/security/guard/auth.guard.ts @@ -29,6 +29,9 @@ export abstract class AuthGuard implements CanActivate { let state = params.get('state'); let error = params.get('error'); let errorDescription = params.get('error_description'); + if (code || state || error || errorDescription) { + window.history.replaceState({}, document.title, url.pathname); + } if (isAccess) { return true; }