SUPPORT-8942: Fix
This commit is contained in:
parent
efd94ee0e9
commit
6945de246a
3 changed files with 43 additions and 16 deletions
|
|
@ -1,8 +1,10 @@
|
|||
package ru.micord.ervu.security.esia;
|
||||
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
|
@ -16,7 +18,7 @@ public class EsiaAuthInfoStore {
|
|||
private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass());
|
||||
private static final Map<String, ExpiringToken> accessTokensMap = new ConcurrentHashMap<>();
|
||||
private static final Map<String, ExpiringToken> refreshTokensMap = new ConcurrentHashMap<>();
|
||||
private static final Map<String, ExpiringState> prnsUuidStateMap = new ConcurrentHashMap<>();
|
||||
private static final Map<String, List<ExpiringState>> prnsUuidStateMap = new ConcurrentHashMap<>();
|
||||
|
||||
public static void addAccessToken(String prnOid, String token, long expiresIn) {
|
||||
if (token != null) {
|
||||
|
|
@ -81,11 +83,29 @@ public class EsiaAuthInfoStore {
|
|||
|
||||
public static void addState(String prnsUUID, String state, long expiresIn) {
|
||||
long expiryTime = System.currentTimeMillis() + expiresIn * 1000L;
|
||||
prnsUuidStateMap.put(prnsUUID, new ExpiringState(state, expiryTime));
|
||||
ExpiringState newState = new ExpiringState(state, expiryTime);
|
||||
prnsUuidStateMap.compute(prnsUUID, (key, states) -> {
|
||||
if (states == null) {
|
||||
states = new CopyOnWriteArrayList<>();
|
||||
}
|
||||
states.add(newState);
|
||||
return states;
|
||||
});
|
||||
}
|
||||
|
||||
public static String getState(String prnsUUID) {
|
||||
return prnsUuidStateMap.get(prnsUUID).getState();
|
||||
public static boolean containsState(String prnsUUID, String state) {
|
||||
List<ExpiringState> states = prnsUuidStateMap.get(prnsUUID);
|
||||
if (states == null) {
|
||||
return false;
|
||||
}
|
||||
long currentTime = System.currentTimeMillis();
|
||||
states.removeIf(expiringState -> expiringState.getExpiryTime() < currentTime);
|
||||
for (ExpiringState expiringState : states) {
|
||||
if (expiringState.getState().equals(state)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static void removeState(String prnsUUID) {
|
||||
|
|
@ -94,10 +114,10 @@ public class EsiaAuthInfoStore {
|
|||
|
||||
public static void removeExpiredState() {
|
||||
for (String key : prnsUuidStateMap.keySet()) {
|
||||
ExpiringState state = prnsUuidStateMap.get(key);
|
||||
if (state != null && state.isExpired()) {
|
||||
prnsUuidStateMap.remove(key);
|
||||
}
|
||||
prnsUuidStateMap.computeIfPresent(key, (k, states) -> {
|
||||
states.removeIf(ExpiringState::isExpired);
|
||||
return states.isEmpty() ? null : states;
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -32,8 +32,8 @@ public class EsiaController {
|
|||
private JwtTokenService jwtTokenService;
|
||||
|
||||
@RequestMapping(value = "/esia/url")
|
||||
public String getEsiaUrl(HttpServletResponse response) {
|
||||
return esiaAuthService.generateAuthCodeUrl(response);
|
||||
public String getEsiaUrl(HttpServletResponse response, HttpServletRequest request) {
|
||||
return esiaAuthService.generateAuthCodeUrl(response, request);
|
||||
}
|
||||
|
||||
@GetMapping(value = "/esia/auth")
|
||||
|
|
|
|||
|
|
@ -14,6 +14,7 @@ import java.time.LocalDateTime;
|
|||
import java.time.ZoneId;
|
||||
import java.time.ZonedDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
|
@ -94,7 +95,7 @@ public class EsiaAuthService {
|
|||
@Value("${ervu.kafka.request.topic}")
|
||||
private String requestTopic;
|
||||
|
||||
public String generateAuthCodeUrl(HttpServletResponse response) {
|
||||
public String generateAuthCodeUrl(HttpServletResponse response, HttpServletRequest request) {
|
||||
try {
|
||||
String clientId = esiaConfig.getClientId();
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss xx");
|
||||
|
|
@ -102,6 +103,10 @@ public class EsiaAuthService {
|
|||
String timestamp = dt.format(formatter);
|
||||
String state = UUID.randomUUID().toString();
|
||||
String prnsUUID = UUID.randomUUID().toString();
|
||||
Cookie oldPrnsCookie = WebUtils.getCookie(request, PRNS_UUID);
|
||||
if (oldPrnsCookie != null) {
|
||||
prnsUUID = oldPrnsCookie.getValue();
|
||||
}
|
||||
String redirectUrl = esiaConfig.getRedirectUrl();
|
||||
String redirectUrlEncoded = redirectUrl.replaceAll(":", "%3A")
|
||||
.replaceAll("/", "%2F");
|
||||
|
|
@ -472,8 +477,11 @@ public class EsiaAuthService {
|
|||
ZoneId.systemDefault()
|
||||
);
|
||||
LocalDateTime currentTime = LocalDateTime.now();
|
||||
if (!currentTime.isAfter(iatTime) || !expTime.isAfter(iatTime)) {
|
||||
return "Token invalid. Token expired";
|
||||
if (currentTime.getNano() > 0) {
|
||||
currentTime = currentTime.plusSeconds(1).truncatedTo(ChronoUnit.SECONDS);
|
||||
}
|
||||
if (currentTime.isBefore(iatTime) || expTime.isBefore(iatTime) || currentTime.isAfter(expTime)) {
|
||||
return "Token invalid. Token expired, current: " + currentTime + " iat: " + iatTime + " exp: " + expTime;
|
||||
}
|
||||
HttpResponse<String> response = signVerify(accessToken);
|
||||
if (response.statusCode() != 200) {
|
||||
|
|
@ -509,8 +517,7 @@ public class EsiaAuthService {
|
|||
return "State invalid. Cookie not found";
|
||||
}
|
||||
String prnsUUID = cookie.getValue();
|
||||
String oldState = EsiaAuthInfoStore.getState(prnsUUID);
|
||||
if (oldState == null || !oldState.equals(state)) {
|
||||
if (!EsiaAuthInfoStore.containsState(prnsUUID, state)) {
|
||||
return "State invalid. State from ESIA not equals with state before";
|
||||
}
|
||||
EsiaAuthInfoStore.removeState(prnsUUID);
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue