diff --git a/backend/src/main/java/ervu/service/fileupload/EmployeeInfoFileUploadService.java b/backend/src/main/java/ervu/service/fileupload/EmployeeInfoFileUploadService.java index d79e1b98..c9eb916e 100644 --- a/backend/src/main/java/ervu/service/fileupload/EmployeeInfoFileUploadService.java +++ b/backend/src/main/java/ervu/service/fileupload/EmployeeInfoFileUploadService.java @@ -35,7 +35,7 @@ import ru.micord.ervu.exception.JsonParsingException; import ru.micord.ervu.security.esia.model.EmployeeModel; import ru.micord.ervu.security.esia.model.PersonModel; import ru.micord.ervu.security.esia.service.UlDataService; -import ru.micord.ervu.security.esia.token.EsiaTokensStore; +import ru.micord.ervu.security.esia.EsiaAuthInfoStore; import ru.micord.ervu.security.webbpm.jwt.UserIdsPair; import ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil; import ru.micord.ervu.service.InteractionService; @@ -91,7 +91,7 @@ public class EmployeeInfoFileUploadService { formType); String esiaUserId = userIdsPair.getEsiaUserId(); String ervuId = userIdsPair.getErvuId(); - String accessToken = EsiaTokensStore.getAccessToken(esiaUserId); + String accessToken = EsiaAuthInfoStore.getAccessToken(esiaUserId); EmployeeModel employeeModel = ulDataService.getEmployeeModel(accessToken); PersonModel personModel = employeeModel.getPerson(); diff --git a/backend/src/main/java/ru/micord/ervu/security/esia/token/EsiaTokensStore.java b/backend/src/main/java/ru/micord/ervu/security/esia/EsiaAuthInfoStore.java similarity index 71% rename from backend/src/main/java/ru/micord/ervu/security/esia/token/EsiaTokensStore.java rename to backend/src/main/java/ru/micord/ervu/security/esia/EsiaAuthInfoStore.java index e16d48ac..34655858 100644 --- a/backend/src/main/java/ru/micord/ervu/security/esia/token/EsiaTokensStore.java +++ b/backend/src/main/java/ru/micord/ervu/security/esia/EsiaAuthInfoStore.java @@ -1,4 +1,4 @@ -package ru.micord.ervu.security.esia.token; +package ru.micord.ervu.security.esia; import java.lang.invoke.MethodHandles; import java.util.Map; @@ -6,15 +6,17 @@ import java.util.concurrent.ConcurrentHashMap; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import org.springframework.security.authentication.CredentialsExpiredException; +import ru.micord.ervu.security.esia.model.ExpiringState; +import ru.micord.ervu.security.esia.model.ExpiringToken; /** * @author Eduard Tihomirov */ -public class EsiaTokensStore { +public class EsiaAuthInfoStore { private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private static final Map ACCESS_TOKENS_MAP = new ConcurrentHashMap<>(); private static final Map REFRESH_TOKENS_MAP = new ConcurrentHashMap<>(); + private static final Map PRNS_UUID_STATE_MAP = new ConcurrentHashMap<>(); public static void addAccessToken(String prnOid, String token, long expiresIn) { if (token != null) { @@ -77,4 +79,25 @@ public class EsiaTokensStore { REFRESH_TOKENS_MAP.remove(prnOid); } + public static void addState(String prnsUUID, String state, long expiresIn) { + long expiryTime = System.currentTimeMillis() + expiresIn * 1000L; + PRNS_UUID_STATE_MAP.put(prnsUUID, new ExpiringState(state, expiryTime)); + } + + public static String getState(String prnsUUID) { + return PRNS_UUID_STATE_MAP.get(prnsUUID).getState(); + } + + public static void removeState(String prnsUUID) { + PRNS_UUID_STATE_MAP.remove(prnsUUID); + } + + public static void removeExpiredState() { + for (String key : PRNS_UUID_STATE_MAP.keySet()) { + ExpiringState state = PRNS_UUID_STATE_MAP.get(key); + if (state != null && state.isExpired()) { + PRNS_UUID_STATE_MAP.remove(key); + } + } + } } diff --git a/backend/src/main/java/ru/micord/ervu/security/esia/config/EsiaConfig.java b/backend/src/main/java/ru/micord/ervu/security/esia/config/EsiaConfig.java index 5a0ddc6c..43bc96aa 100644 --- a/backend/src/main/java/ru/micord/ervu/security/esia/config/EsiaConfig.java +++ b/backend/src/main/java/ru/micord/ervu/security/esia/config/EsiaConfig.java @@ -62,6 +62,12 @@ public class EsiaConfig { @Value("${esia.issuer.url}") private String esiaIssuerUrl; + @Value("${esia.marker.ver}") + private String esiaMarkerVer; + + @Value("${esia.state.cookie.life.time:300}") + private long esiaStateCookieLifeTime; + public String getEsiaOrgScopes() { String[] scopeItems = esiaOrgScopes.split(","); return String.join(" ", Arrays.stream(scopeItems).map(item -> orgScopeUrl + item.trim()).toArray(String[]::new)); @@ -125,4 +131,12 @@ public class EsiaConfig { public String getEsiaIssuerUrl() { return esiaIssuerUrl; } + + public String getEsiaMarkerVer() { + return esiaMarkerVer; + } + + public long getEsiaStateCookieLifeTime() { + return esiaStateCookieLifeTime; + } } diff --git a/backend/src/main/java/ru/micord/ervu/security/esia/controller/EsiaController.java b/backend/src/main/java/ru/micord/ervu/security/esia/controller/EsiaController.java index 2c74293b..42056fa4 100644 --- a/backend/src/main/java/ru/micord/ervu/security/esia/controller/EsiaController.java +++ b/backend/src/main/java/ru/micord/ervu/security/esia/controller/EsiaController.java @@ -25,15 +25,15 @@ public class EsiaController { private EsiaDataService esiaDataService; @GetMapping(value = "/esia/url") - public String getEsiaUrl() { - return esiaAuthService.generateAuthCodeUrl(); + public String getEsiaUrl(HttpServletResponse response) { + return esiaAuthService.generateAuthCodeUrl(response); } @GetMapping(value = "/esia/auth") - public void esiaAuth(@RequestParam(value = "code", required = false) String code, - @RequestParam(value = "error", required = false) String error, HttpServletRequest request, - HttpServletResponse response) { - esiaAuthService.authEsiaTokensByCode(code, error, request, response); + public void esiaAuth(@RequestParam String code, + @RequestParam String state, + HttpServletResponse response, HttpServletRequest request) { + esiaAuthService.authEsiaTokensByCode(code, state, response, request); } @PostMapping(value = "/esia/refresh") diff --git a/backend/src/main/java/ru/micord/ervu/security/esia/model/ExpiringState.java b/backend/src/main/java/ru/micord/ervu/security/esia/model/ExpiringState.java new file mode 100644 index 00000000..7584b668 --- /dev/null +++ b/backend/src/main/java/ru/micord/ervu/security/esia/model/ExpiringState.java @@ -0,0 +1,34 @@ +package ru.micord.ervu.security.esia.model; + +/** + * @author Eduard Tihomirov + */ +public class ExpiringState { + private String state; + private long expiryTime; + + public ExpiringState(String state, long expiryTime) { + this.state = state; + this.expiryTime = expiryTime; + } + + public String getState() { + return state; + } + + public void setState(String state) { + this.state = state; + } + + public long getExpiryTime() { + return expiryTime; + } + + public void setExpiryTime(long expiryTime) { + this.expiryTime = expiryTime; + } + + public boolean isExpired() { + return System.currentTimeMillis() > expiryTime; + } +} diff --git a/backend/src/main/java/ru/micord/ervu/security/esia/token/ExpiringToken.java b/backend/src/main/java/ru/micord/ervu/security/esia/model/ExpiringToken.java similarity index 89% rename from backend/src/main/java/ru/micord/ervu/security/esia/token/ExpiringToken.java rename to backend/src/main/java/ru/micord/ervu/security/esia/model/ExpiringToken.java index f6a476e4..a20b88c2 100644 --- a/backend/src/main/java/ru/micord/ervu/security/esia/token/ExpiringToken.java +++ b/backend/src/main/java/ru/micord/ervu/security/esia/model/ExpiringToken.java @@ -1,4 +1,4 @@ -package ru.micord.ervu.security.esia.token; +package ru.micord.ervu.security.esia.model; /** * @author Eduard Tihomirov @@ -28,7 +28,7 @@ public class ExpiringToken { this.expiryTime = expiryTime; } - boolean isExpired() { + public boolean isExpired() { return System.currentTimeMillis() > expiryTime; } } diff --git a/backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaAuthInfoClearShedulerService.java b/backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaAuthInfoClearShedulerService.java new file mode 100644 index 00000000..299876f7 --- /dev/null +++ b/backend/src/main/java/ru/micord/ervu/security/esia/service/EsiaAuthInfoClearShedulerService.java @@ -0,0 +1,22 @@ +package ru.micord.ervu.security.esia.service; + +import net.javacrumbs.shedlock.core.SchedulerLock; +import org.springframework.scheduling.annotation.Scheduled; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import ru.micord.ervu.security.esia.EsiaAuthInfoStore; + +/** + * @author Eduard Tihomirov + */ +@Service +public class EsiaAuthInfoClearShedulerService { + @Scheduled(cron = "${esia.auth.info.clear.cron:0 0 */1 * * *}") + @SchedulerLock(name = "clearAuthInfo") + @Transactional + public void run() { + EsiaAuthInfoStore.removeExpiredRefreshToken(); + EsiaAuthInfoStore.removeExpiredAccessToken(); + EsiaAuthInfoStore.removeExpiredState(); + } +} 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 475672a1..9bd82dcb 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 @@ -10,13 +10,16 @@ import java.net.http.HttpRequest; import java.net.http.HttpResponse; import java.nio.charset.StandardCharsets; import java.time.Duration; +import java.time.Instant; +import java.time.LocalDateTime; +import java.time.ZoneId; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; import java.util.Arrays; import java.util.LinkedHashMap; import java.util.Map; -import java.util.Objects; import java.util.UUID; +import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; @@ -24,9 +27,11 @@ import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.databind.ObjectMapper; import ervu.service.okopf.OkopfService; import org.springframework.context.support.MessageSourceAccessor; +import org.springframework.http.ResponseCookie; import org.springframework.stereotype.Service; import ru.micord.ervu.audit.constants.AuditConstants; import ru.micord.ervu.audit.service.AuditService; +import org.springframework.web.util.WebUtils; import ru.micord.ervu.security.esia.exception.EsiaException; import ru.micord.ervu.security.esia.model.EmployeeModel; import ru.micord.ervu.security.esia.model.EsiaAccessToken; @@ -35,7 +40,7 @@ import ru.micord.ervu.security.esia.model.EsiaTokenResponse; import ru.micord.ervu.security.esia.model.FormUrlencoded; import ru.micord.ervu.security.esia.model.OrganizationModel; import ru.micord.ervu.security.esia.model.SignResponse; -import ru.micord.ervu.security.esia.token.EsiaTokensStore; +import ru.micord.ervu.security.esia.EsiaAuthInfoStore; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.security.core.context.SecurityContext; @@ -59,8 +64,6 @@ import ru.micord.ervu.security.webbpm.jwt.model.Token; import ru.cg.webbpm.modules.core.runtime.api.LocalizedException; import ru.cg.webbpm.modules.core.runtime.api.MessageBundleUtils; -import static ru.micord.ervu.security.webbpm.jwt.util.SecurityUtil.getCurrentUsername; - /** * @author Eduard Tihomirov */ @@ -69,6 +72,7 @@ public class EsiaAuthService { private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); private static final MessageSourceAccessor MESSAGE_SOURCE = MessageBundleUtils.createAccessor( "messages/common_errors_messages"); + private static final String PRNS_UUID = "prns_uuid"; @Autowired private ObjectMapper objectMapper; @Autowired @@ -91,13 +95,14 @@ public class EsiaAuthService { @Value("${ervu.kafka.org.request.topic}") private String requestTopic; - public String generateAuthCodeUrl() { + public String generateAuthCodeUrl(HttpServletResponse response) { try { String clientId = esiaConfig.getClientId(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss xx"); ZonedDateTime dt = ZonedDateTime.now(); String timestamp = dt.format(formatter); String state = UUID.randomUUID().toString(); + String prnsUUID = UUID.randomUUID().toString(); String redirectUrl = esiaConfig.getRedirectUrl(); String redirectUrlEncoded = redirectUrl.replaceAll(":", "%3A") .replaceAll("/", "%2F"); @@ -113,7 +118,11 @@ public class EsiaAuthService { parameters.put("redirect_uri", esiaConfig.getRedirectUrl()); String clientSecret = signMap(parameters); - + EsiaAuthInfoStore.addState(prnsUUID, state, esiaConfig.getEsiaStateCookieLifeTime()); + ResponseCookie prnsCookie = securityHelper.createCookie(PRNS_UUID, prnsUUID, "/") + .maxAge(esiaConfig.getEsiaStateCookieLifeTime()) + .build(); + securityHelper.addResponseCookie(response, prnsCookie); String responseType = "code"; String authUrl = esiaConfig.getEsiaBaseUri() + esiaConfig.getEsiaCodeUrl(); @@ -164,22 +173,22 @@ public class EsiaAuthService { return uriBuilder.toString(); } - public void authEsiaTokensByCode(String esiaAuthCode, String error, - HttpServletRequest request, HttpServletResponse response) { - if (error != null && !error.equals("null")) { - throw new EsiaException(error); - } + public void authEsiaTokensByCode(String esiaAuthCode, String state, HttpServletResponse response, HttpServletRequest request) { String esiaAccessTokenStr = null; String prnOid = null; Long expiresIn = null; boolean hasRole = false; long timeSignSecret = 0, timeRequestAccessToken = 0, timeVerifySecret = 0; + String verifyStateResult = verifyStateFromCookie(request, state, response); + if (verifyStateResult != null) { + throw new EsiaException(verifyStateResult); + } try { String clientId = esiaConfig.getClientId(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss xx"); ZonedDateTime dt = ZonedDateTime.now(); String timestamp = dt.format(formatter); - String state = UUID.randomUUID().toString(); + String newState = UUID.randomUUID().toString(); String redirectUrl = esiaConfig.getRedirectUrl(); String scope = esiaConfig.getEsiaScopes(); String scopeOrg = esiaConfig.getEsiaOrgScopes(); @@ -189,7 +198,7 @@ public class EsiaAuthService { parameters.put("scope", scope); parameters.put("scope_org", scopeOrg); parameters.put("timestamp", timestamp); - parameters.put("state", state); + parameters.put("state", newState); parameters.put("redirect_uri", redirectUrl); parameters.put("code", esiaAuthCode); @@ -202,7 +211,7 @@ public class EsiaAuthService { .setParameter("code", esiaAuthCode) .setParameter("grant_type", "authorization_code") .setParameter("client_secret", clientSecret) - .setParameter("state", state) + .setParameter("state", newState) .setParameter("redirect_uri", redirectUrl) .setParameter("scope", scope) .setParameter("scope_org", scopeOrg) @@ -231,6 +240,9 @@ public class EsiaAuthService { tokenResponse != null ? tokenResponse.getErrorDescription() : "response is empty"; throw new IllegalStateException("Esia response error. " + errMsg); } + if (!tokenResponse.getState().equals(newState)) { + throw new EsiaException("Token invalid. State from request not equals with state from response."); + } esiaAccessTokenStr = tokenResponse.getAccessToken(); String esiaRefreshTokenStr = tokenResponse.getRefreshToken(); startTime = System.currentTimeMillis(); @@ -242,8 +254,8 @@ public class EsiaAuthService { EsiaAccessToken esiaAccessToken = ulDataService.readToken(esiaAccessTokenStr); prnOid = esiaAccessToken.getSbjId(); expiresIn = tokenResponse.getExpiresIn(); - EsiaTokensStore.addAccessToken(prnOid, esiaAccessTokenStr, expiresIn); - EsiaTokensStore.addRefreshToken(prnOid, esiaRefreshTokenStr, expiresIn); + EsiaAuthInfoStore.addAccessToken(prnOid, esiaAccessTokenStr, expiresIn); + EsiaAuthInfoStore.addRefreshToken(prnOid, esiaRefreshTokenStr, expiresIn); } catch (Exception e) { throw new EsiaException(e); @@ -341,8 +353,8 @@ public class EsiaAuthService { EsiaAccessToken esiaAccessToken = ulDataService.readToken(esiaAccessTokenStr); String prnOid = esiaAccessToken.getSbjId(); Long expiresIn = tokenResponse.getExpiresIn(); - EsiaTokensStore.addAccessToken(prnOid, esiaAccessTokenStr, expiresIn); - EsiaTokensStore.addRefreshToken(prnOid, esiaNewRefreshToken, expiresIn); + EsiaAuthInfoStore.addAccessToken(prnOid, esiaAccessTokenStr, expiresIn); + EsiaAuthInfoStore.addRefreshToken(prnOid, esiaNewRefreshToken, expiresIn); OrgInfo orgInfo = getOrgInfo(esiaAccessTokenStr); String ervuId = getErvuId(prnOid, orgInfo); createTokenAndAddCookie(response, esiaAccessToken.getSbjId(), ervuId, true, expiresIn); @@ -390,11 +402,11 @@ public class EsiaAuthService { String userId = null; try { userId = jwtTokenService.getUserAccountId(request); - String accessToken = EsiaTokensStore.getAccessToken(userId); + String accessToken = EsiaAuthInfoStore.getAccessToken(userId); orgInfo = getOrgInfo(accessToken); securityHelper.clearAccessCookies(response); - EsiaTokensStore.removeAccessToken(userId); - EsiaTokensStore.removeRefreshToken(userId); + EsiaAuthInfoStore.removeAccessToken(userId); + EsiaAuthInfoStore.removeRefreshToken(userId); String logoutUrl = esiaConfig.getEsiaBaseUri() + esiaConfig.getEsiaLogoutUrl(); String redirectUrl = esiaConfig.getLogoutRedirectUrl(); URL url = new URL(logoutUrl); @@ -506,13 +518,6 @@ public class EsiaAuthService { return employee; } - private String getMessageId(Exception exception) { - return Integer.toUnsignedString(Objects - .hashCode(getCurrentUsername()), 36) - + "-" - + Integer.toUnsignedString(exception.hashCode(), 36); - } - private void createTokenAndAddCookie(HttpServletResponse response, String userId, String ervuId, Boolean hasRole, Long expiresIn) { Token token = jwtTokenService.createAccessToken(userId, expiresIn, ervuId, hasRole); @@ -532,6 +537,9 @@ public class EsiaAuthService { if (!esiaHeader.getSbt().equals("access")) { return "Token invalid. Token sbt: " + esiaHeader.getSbt() + " invalid"; } + if (!esiaHeader.getVer().equals(esiaConfig.getEsiaMarkerVer())) { + return "Token invalid. Token ver: " + esiaHeader.getVer() + " invalid"; + } if (!esiaHeader.getTyp().equals("JWT")) { return "Token invalid. Token type: " + esiaHeader.getTyp() + " invalid"; } @@ -541,17 +549,16 @@ public class EsiaAuthService { if (!esiaAccessToken.getIss().equals(esiaConfig.getEsiaIssuerUrl())) { return "Token invalid. Token issuer:" + esiaAccessToken.getIss() + " invalid"; } - //TODO SUPPORT-8750 -// LocalDateTime iatTime = LocalDateTime.ofInstant(Instant.ofEpochSecond(esiaAccessToken.getIat()), -// ZoneId.systemDefault() -// ); -// LocalDateTime expTime = LocalDateTime.ofInstant(Instant.ofEpochSecond(esiaAccessToken.getExp()), -// ZoneId.systemDefault() -// ); -// LocalDateTime currentTime = LocalDateTime.now(); -// if (!currentTime.isAfter(iatTime) || !expTime.isAfter(iatTime)) { -// return "Token invalid. Token expired"; -// } + LocalDateTime iatTime = LocalDateTime.ofInstant(Instant.ofEpochSecond(esiaAccessToken.getIat()), + ZoneId.systemDefault() + ); + LocalDateTime expTime = LocalDateTime.ofInstant(Instant.ofEpochSecond(esiaAccessToken.getExp()), + ZoneId.systemDefault() + ); + LocalDateTime currentTime = LocalDateTime.now(); + if (!currentTime.isAfter(iatTime) || !expTime.isAfter(iatTime)) { + return "Token invalid. Token expired"; + } HttpResponse response = signVerify(accessToken); if (response.statusCode() != 200) { if (response.statusCode() == 401) { @@ -579,4 +586,19 @@ public class EsiaAuthService { throw new EsiaException(e); } } + + private String verifyStateFromCookie(HttpServletRequest request, String state, HttpServletResponse response) { + Cookie cookie = WebUtils.getCookie(request, PRNS_UUID); + if (cookie == null) { + return "State invalid. Cookie not found"; + } + String prnsUUID = cookie.getValue(); + String oldState = EsiaAuthInfoStore.getState(prnsUUID); + if (oldState == null || !oldState.equals(state)) { + return "State invalid. State from ESIA not equals with state before"; + } + EsiaAuthInfoStore.removeState(prnsUUID); + securityHelper.clearCookie(response, PRNS_UUID, "/"); + return null; + } } diff --git a/backend/src/main/java/ru/micord/ervu/security/esia/token/TokensClearShedulerService.java b/backend/src/main/java/ru/micord/ervu/security/esia/token/TokensClearShedulerService.java deleted file mode 100644 index 89c9db4c..00000000 --- a/backend/src/main/java/ru/micord/ervu/security/esia/token/TokensClearShedulerService.java +++ /dev/null @@ -1,20 +0,0 @@ -package ru.micord.ervu.security.esia.token; - -import net.javacrumbs.shedlock.core.SchedulerLock; -import org.springframework.scheduling.annotation.Scheduled; -import org.springframework.stereotype.Service; -import org.springframework.transaction.annotation.Transactional; - -/** - * @author Eduard Tihomirov - */ -@Service -public class TokensClearShedulerService { - @Scheduled(cron = "${esia.token.clear.cron:0 0 */1 * * *}") - @SchedulerLock(name = "clearToken") - @Transactional - public void load() { - EsiaTokensStore.removeExpiredRefreshToken(); - EsiaTokensStore.removeExpiredAccessToken(); - } -} diff --git a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/helper/SecurityHelper.java b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/helper/SecurityHelper.java index 9c966f60..6ce0411e 100644 --- a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/helper/SecurityHelper.java +++ b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/helper/SecurityHelper.java @@ -48,7 +48,7 @@ public final class SecurityHelper { addResponseCookie(response, emptyAuthMarker); } - private void addResponseCookie(HttpServletResponse response, ResponseCookie cookie) { + public void addResponseCookie(HttpServletResponse response, ResponseCookie cookie) { response.addHeader(HttpHeaders.SET_COOKIE, cookie.toString()); } @@ -86,4 +86,10 @@ public final class SecurityHelper { .secure(accessCookieSecure) .sameSite(accessCookieSameSite); } + + public void clearCookie(HttpServletResponse response, String name, String path) { + ResponseCookie emptyCookie = createCookie(name, null, path) + .maxAge(0).build(); + addResponseCookie(response, emptyCookie); + } } diff --git a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/service/JwtTokenService.java b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/service/JwtTokenService.java index db9a7e81..3e388a90 100644 --- a/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/service/JwtTokenService.java +++ b/backend/src/main/java/ru/micord/ervu/security/webbpm/jwt/service/JwtTokenService.java @@ -14,8 +14,8 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; -import ru.micord.ervu.security.esia.token.EsiaTokensStore; import ru.micord.ervu.security.exception.UnauthorizedException; +import ru.micord.ervu.security.esia.EsiaAuthInfoStore; import ru.micord.ervu.security.webbpm.jwt.model.Token; import ru.cg.webbpm.modules.resources.api.ResourceMetadataUtils; @@ -68,7 +68,7 @@ public class JwtTokenService { return false; } String[] ids = token.getUserAccountId().split(":"); - return EsiaTokensStore.validateAccessToken(ids[0]); + return EsiaAuthInfoStore.validateAccessToken(ids[0]); } public Token getToken(String token) { @@ -81,11 +81,11 @@ public class JwtTokenService { } public String getAccessToken(HttpServletRequest request) { - return EsiaTokensStore.getAccessToken(getUserAccountId(request)); + return EsiaAuthInfoStore.getAccessToken(getUserAccountId(request)); } public String getRefreshToken(HttpServletRequest request) { - return EsiaTokensStore.getRefreshToken(getUserAccountId(request)); + return EsiaAuthInfoStore.getRefreshToken(getUserAccountId(request)); } public String getUserAccountId(HttpServletRequest request) { diff --git a/config/micord.env b/config/micord.env index 14433e24..9e9cf6c7 100644 --- a/config/micord.env +++ b/config/micord.env @@ -25,7 +25,7 @@ ESIA_REDIRECT_URL=https://lkrp-dev.micord.ru/ul/ ESIA_LOGOUT_REDIRECT_URL=https://lkrp-dev.micord.ru/ul/home.html ESIA_UPLOAD_DATA_ROLE=MNSV89_UPLOAD_DATA ESIA_CLIENT_CERT_HASH=04508B4B0B58776A954A0E15F574B4E58799D74C61EE020B3330716C203E3BDD -ESIA_TOKEN_CLEAR_CRON=0 0 */1 * * * +ESIA_AUTH_INFO_CLEAR_CRON=0 0 */1 * * * SIGN_URL=https://ervu-sign-dev.k8s.micord.ru/sign diff --git a/config/standalone/dev/standalone.xml b/config/standalone/dev/standalone.xml index c2167b28..df190f4d 100644 --- a/config/standalone/dev/standalone.xml +++ b/config/standalone/dev/standalone.xml @@ -95,7 +95,7 @@ - + diff --git a/frontend/src/ts/modules/security/guard/auth.guard.ts b/frontend/src/ts/modules/security/guard/auth.guard.ts index 5cad4aa3..24a4aefd 100644 --- a/frontend/src/ts/modules/security/guard/auth.guard.ts +++ b/frontend/src/ts/modules/security/guard/auth.guard.ts @@ -42,47 +42,36 @@ export abstract class AuthGuard implements CanActivate { }).then((isAccess) => { let params = new URLSearchParams(url.search); let code = params.get('code'); + let state = params.get('state'); let error = params.get('error'); let errorDescription = params.get('error_description'); if (isAccess) { return true; } - if (code || error) { - const params = new HttpParams().set('code', code).set('error', error); + if (error) { + let errorMessage = + 'Произошла неизвестная ошибка. Обратитесь к системному администратору'; + let errorCode = this.extractCode(errorDescription); + if (errorCode) { + errorMessage = EsiaErrorDetail.getDescription(errorCode); + } + let consoleError = error + ', error description = ' + errorDescription; + this.messageService.error(errorMessage); + console.error(consoleError); + } + if (code && state) { + const params = new HttpParams().set('code', code).set('state', state); this.httpClient.get("esia/auth", { params: params, responseType: 'text', observe: 'response', - headers: { - "Error-intercept-skip": "true" - } }) .toPromise() .then( - (response) => { + () => { window.open(url.origin + url.pathname, "_self"); - }) - .catch((reason) => { - let errorMessage = reason.error.messages != null - ? reason.error.messages - : reason.error.replaceAll('\\', ''); - if (error) { - errorMessage = - 'Произошла неизвестная ошибка. Обратитесь к системному администратору'; - let errorCode = this.extractCode(errorDescription); - if (errorCode) { - errorMessage = EsiaErrorDetail.getDescription(errorCode); - } - let consoleError = error + ', error description = ' + errorDescription; - this.messageService.error(errorMessage); - console.error(consoleError); - } - else { - this.messageService.error(errorMessage); - console.error(reason); - } - }); + }); return false; } else {