Cherry pick marker verify
This commit is contained in:
parent
b61e82dbd6
commit
fbff1ec766
5 changed files with 157 additions and 4 deletions
|
|
@ -47,6 +47,12 @@ public class EsiaConfig {
|
|||
@Value("${esia.token.url:aas/oauth2/v3/te}")
|
||||
private String esiaTokenUrl;
|
||||
|
||||
@Value("${sign.verify.url}")
|
||||
private String signVerifyUrl;
|
||||
|
||||
@Value("${esia.issuer.url}")
|
||||
private String esiaIssuerUrl;
|
||||
|
||||
public String getEsiaScopes() {
|
||||
String[] scopeItems = esiaScopes.split(",");
|
||||
return String.join(" ", Arrays.stream(scopeItems).map(String::trim).toArray(String[]::new));
|
||||
|
|
@ -93,4 +99,12 @@ public class EsiaConfig {
|
|||
public String getLogoutRedirectUrl() {
|
||||
return logoutRedirectUrl;
|
||||
}
|
||||
|
||||
public String getSignVerifyUrl() {
|
||||
return signVerifyUrl;
|
||||
}
|
||||
|
||||
public String getEsiaIssuerUrl() {
|
||||
return esiaIssuerUrl;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,54 @@
|
|||
package ru.micord.ervu.security.esia.model;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
|
||||
|
||||
/**
|
||||
* @author Eduard Tihomirov
|
||||
*/
|
||||
@JsonIgnoreProperties(ignoreUnknown = true)
|
||||
public class EsiaHeader implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private String alg;
|
||||
|
||||
private String ver;
|
||||
|
||||
private String sbt;
|
||||
|
||||
private String typ;
|
||||
|
||||
public String getAlg() {
|
||||
return alg;
|
||||
}
|
||||
|
||||
public void setAlg(String alg) {
|
||||
this.alg = alg;
|
||||
}
|
||||
|
||||
public String getVer() {
|
||||
return ver;
|
||||
}
|
||||
|
||||
public void setVer(String ver) {
|
||||
this.ver = ver;
|
||||
}
|
||||
|
||||
public String getSbt() {
|
||||
return sbt;
|
||||
}
|
||||
|
||||
public void setSbt(String sbt) {
|
||||
this.sbt = sbt;
|
||||
}
|
||||
|
||||
public String getTyp() {
|
||||
return typ;
|
||||
}
|
||||
|
||||
public void setTyp(String typ) {
|
||||
this.typ = typ;
|
||||
}
|
||||
}
|
||||
|
|
@ -31,12 +31,13 @@ import ru.micord.ervu.kafka.model.Person;
|
|||
import ru.micord.ervu.kafka.model.Response;
|
||||
import ru.micord.ervu.kafka.service.ReplyingKafkaService;
|
||||
import ru.micord.ervu.security.esia.exception.EsiaException;
|
||||
import ru.micord.ervu.security.esia.model.EsiaAccessToken;
|
||||
import ru.micord.ervu.security.esia.model.EsiaHeader;
|
||||
import ru.micord.ervu.security.esia.model.EsiaTokenResponse;
|
||||
import ru.micord.ervu.security.esia.model.FormUrlencoded;
|
||||
import ru.micord.ervu.security.esia.model.PersonModel;
|
||||
import ru.micord.ervu.security.esia.token.EsiaTokensStore;
|
||||
import ru.micord.ervu.security.esia.config.EsiaConfig;
|
||||
import ru.micord.ervu.security.esia.model.FormUrlencoded;
|
||||
import ru.micord.ervu.security.esia.model.EsiaAccessToken;
|
||||
import ru.micord.ervu.security.esia.model.EsiaTokenResponse;
|
||||
import ru.micord.ervu.security.esia.model.PersonModel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.http.HttpHeaders;
|
||||
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
|
||||
|
|
@ -211,6 +212,10 @@ public class EsiaAuthService {
|
|||
throw new IllegalStateException("Esia response error. " + errMsg);
|
||||
}
|
||||
esiaAccessTokenStr = tokenResponse.getAccess_token();
|
||||
String verifyResult = verifyToken(esiaAccessTokenStr);
|
||||
if (verifyResult != null) {
|
||||
throw new EsiaException(verifyResult);
|
||||
}
|
||||
String esiaRefreshTokenStr = tokenResponse.getRefresh_token();
|
||||
EsiaAccessToken esiaAccessToken = personalDataService.readToken(esiaAccessTokenStr);
|
||||
prnOid = esiaAccessToken.getSbj_id();
|
||||
|
|
@ -287,6 +292,10 @@ public class EsiaAuthService {
|
|||
throw new IllegalStateException("Esia response error. " + errMsg);
|
||||
}
|
||||
String esiaAccessTokenStr = tokenResponse.getAccess_token();
|
||||
String verifyResult = verifyToken(esiaAccessTokenStr);
|
||||
if (verifyResult != null) {
|
||||
throw new EsiaException(verifyResult);
|
||||
}
|
||||
String esiaNewRefreshTokenStr = tokenResponse.getRefresh_token();
|
||||
EsiaAccessToken esiaAccessToken = personalDataService.readToken(esiaAccessTokenStr);
|
||||
String prnOid = esiaAccessToken.getSbj_id();
|
||||
|
|
@ -400,4 +409,57 @@ public class EsiaAuthService {
|
|||
context.setAuthentication(authentication);
|
||||
SecurityContextHolder.setContext(context);
|
||||
}
|
||||
|
||||
private String verifyToken(String accessToken) {
|
||||
EsiaAccessToken esiaAccessToken = personalDataService.readToken(accessToken);
|
||||
EsiaHeader esiaHeader = personalDataService.readHeader(accessToken);
|
||||
if (!esiaHeader.getSbt().equals("access")) {
|
||||
return "Token invalid. Token sbt: " + esiaHeader.getSbt() + " invalid";
|
||||
}
|
||||
if (!esiaHeader.getTyp().equals("JWT")) {
|
||||
return "Token invalid. Token type: " + esiaHeader.getTyp() + " invalid";
|
||||
}
|
||||
if (!esiaAccessToken.getClient_id().equals(esiaConfig.getClientId())) {
|
||||
return "Token invalid. Token clientId: " + esiaAccessToken.getClient_id() + " invalid";
|
||||
}
|
||||
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";
|
||||
// }
|
||||
HttpResponse<String> response = signVerify(accessToken);
|
||||
if (response.statusCode() != 200) {
|
||||
if (response.statusCode() == 401) {
|
||||
return "Token invalid. " + response.body();
|
||||
}
|
||||
return "Error in verify module. Error status " + response.statusCode();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private HttpResponse<String> signVerify(String accessToken) {
|
||||
try {
|
||||
HttpRequest request = HttpRequest.newBuilder()
|
||||
.uri(URI.create(esiaConfig.getSignVerifyUrl()))
|
||||
.header("Content-Type", "text/plain")
|
||||
.POST(HttpRequest.BodyPublishers.ofString(accessToken, StandardCharsets.UTF_8))
|
||||
.build();
|
||||
return HttpClient.newBuilder()
|
||||
.connectTimeout(Duration.ofSeconds(esiaConfig.getConnectionTimeout()))
|
||||
.build()
|
||||
.send(request, HttpResponse.BodyHandlers.ofString());
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new EsiaException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -8,8 +8,10 @@ import java.time.Duration;
|
|||
import java.util.Base64;
|
||||
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import ru.micord.ervu.security.esia.exception.EsiaException;
|
||||
import ru.micord.ervu.security.esia.config.EsiaConfig;
|
||||
import ru.micord.ervu.security.esia.model.EsiaAccessToken;
|
||||
import ru.micord.ervu.security.esia.model.EsiaHeader;
|
||||
import ru.micord.ervu.security.esia.model.PassportModel;
|
||||
import ru.micord.ervu.security.esia.model.PersonModel;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
|
|
@ -103,4 +105,23 @@ public class EsiaPersonalDataService implements PersonalDataService {
|
|||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public EsiaHeader readHeader(String accessToken) {
|
||||
try {
|
||||
byte[] decodedBytes = Base64.getDecoder()
|
||||
.decode(
|
||||
accessToken.substring(0, accessToken.indexOf('.'))
|
||||
.replace('-', '+')
|
||||
.replace('_', '/'));
|
||||
String decodedString = new String(decodedBytes);
|
||||
EsiaHeader esiaHeader = objectMapper.readValue(decodedString,
|
||||
EsiaHeader.class
|
||||
);
|
||||
return esiaHeader;
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new EsiaException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,6 +1,7 @@
|
|||
package ru.micord.ervu.security.esia.service;
|
||||
|
||||
import ru.micord.ervu.security.esia.model.EsiaAccessToken;
|
||||
import ru.micord.ervu.security.esia.model.EsiaHeader;
|
||||
import ru.micord.ervu.security.esia.model.PersonModel;
|
||||
|
||||
/**
|
||||
|
|
@ -10,4 +11,5 @@ public interface PersonalDataService {
|
|||
|
||||
PersonModel getPersonModel(String accessToken);
|
||||
EsiaAccessToken readToken(String accessToken);
|
||||
EsiaHeader readHeader(String accessToken);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue