From 8bfbd2052506e27f7080518d020621edb75fe831 Mon Sep 17 00:00:00 2001 From: Eduard Tihomirov Date: Tue, 19 Nov 2024 09:51:26 +0300 Subject: [PATCH] SUPPORT-8682: Fix --- .../esia/controller/EsiaController.java | 4 +- .../esia/service/EsiaAuthService.java | 51 ++++++++++++++++--- .../ts/modules/security/guard/auth.guard.ts | 22 ++++---- 3 files changed, 57 insertions(+), 20 deletions(-) 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 2a3ab21..dac63e2 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 @@ -39,8 +39,8 @@ public class EsiaController { } @GetMapping(value = "/esia/auth", params = "code") - public ResponseEntity esiaAuth(@RequestParam("code") String code, HttpServletRequest request, HttpServletResponse response) { - return esiaAuthService.getEsiaTokensByCode(code, request, response); + public ResponseEntity esiaAuth(@RequestParam("code") String code, @RequestParam("error") String error, HttpServletRequest request, HttpServletResponse response) { + return esiaAuthService.getEsiaTokensByCode(code, error, request, response); } @RequestMapping(value = "/esia/refresh") 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 302eef4..57c44f2 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 @@ -1,6 +1,7 @@ package ru.micord.ervu.security.esia.service; import java.io.UnsupportedEncodingException; +import java.lang.invoke.MethodHandles; import java.net.URI; import java.net.URL; import java.net.URLEncoder; @@ -11,19 +12,19 @@ import java.nio.charset.StandardCharsets; import java.time.Duration; import java.time.ZonedDateTime; import java.time.format.DateTimeFormatter; -import java.util.Base64; -import java.util.LinkedHashMap; -import java.util.Map; -import java.util.UUID; +import java.util.*; import javax.servlet.http.Cookie; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import com.fasterxml.jackson.databind.ObjectMapper; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; +import org.springframework.security.core.Authentication; import org.springframework.security.core.context.SecurityContext; import ru.micord.ervu.kafka.model.Document; import ru.micord.ervu.kafka.model.Person; @@ -50,6 +51,7 @@ import ru.micord.ervu.security.webbpm.jwt.model.Token; */ @Service public class EsiaAuthService { + private static final Logger LOGGER = LoggerFactory.getLogger(MethodHandles.lookup().lookupClass()); @Autowired private ObjectMapper objectMapper; @@ -146,8 +148,12 @@ public class EsiaAuthService { return uriBuilder.toString(); } - public ResponseEntity getEsiaTokensByCode(String esiaAuthCode, HttpServletRequest request, HttpServletResponse response) { +public ResponseEntity getEsiaTokensByCode(String esiaAuthCode, String error, + HttpServletRequest request, HttpServletResponse response) { try { + if (error != null) { + throw new RuntimeException(error); + } String clientId = esiaConfig.getClientId(); DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy.MM.dd HH:mm:ss xx"); ZonedDateTime dt = ZonedDateTime.now(); @@ -229,7 +235,25 @@ public class EsiaAuthService { return ResponseEntity.ok("Authentication successful"); } catch (Exception e) { - throw new RuntimeException(e); + Token token = jwtTokenService.createAccessToken(null, 3600L, null); + Cookie accessCookie = securityHelper.createAccessCookie(token.getValue(), 3600); + response.addCookie(accessCookie); + UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = + new UsernamePasswordAuthenticationToken(token.getUserAccountId(), null); + SecurityContext context = SecurityContextHolder.createEmptyContext(); + JwtAuthentication authentication = new JwtAuthentication(usernamePasswordAuthenticationToken, + null, token.getValue()); + context.setAuthentication(authentication); + SecurityContextHolder.setContext(context); + Cookie authMarkerCookie = securityHelper.createAuthMarkerCookie("true", 3600); + response.addCookie(authMarkerCookie); + String messageId = getMessageId(e); + String messageWithId = String.format("[%s] %s", messageId, e.getMessage()); + LOGGER.error(messageWithId, e); + return new ResponseEntity<>( + "Произошла ошибка " + messageId + ". Обратитесь к системному администратору", + HttpStatus.FORBIDDEN + ); } } @@ -385,4 +409,19 @@ public class EsiaAuthService { person.setDocument(document); return person; } + + private String getMessageId(Exception exception) { + return Integer.toUnsignedString(Objects + .hashCode(getCurrentUsername()), 36) + + "-" + + Integer.toUnsignedString(exception.hashCode(), 36); + } + + private String getCurrentUsername() { + Authentication auth = SecurityContextHolder.getContext().getAuthentication(); + if (auth != null && auth.isAuthenticated()) { + return auth.getName(); + } + return null; + } } diff --git a/frontend/src/ts/modules/security/guard/auth.guard.ts b/frontend/src/ts/modules/security/guard/auth.guard.ts index c65b84a..ed18f16 100644 --- a/frontend/src/ts/modules/security/guard/auth.guard.ts +++ b/frontend/src/ts/modules/security/guard/auth.guard.ts @@ -29,18 +29,8 @@ export abstract class AuthGuard implements CanActivate { if (isAccess) { return true; } - else if (error) { - let userErrorMessage = 'Произошла неизвестная ошибка. Обратитесь к системному администратору'; - let errorCode = this.extractCode(errorDescription); - if (errorCode) { - userErrorMessage = EsiaErrorDetail.getDescription(errorCode); - } - let errorMessage = error + ', error description = ' + errorDescription; - this.messageService.error(userErrorMessage) - throw new Error(errorMessage); - } - else if (code) { - const params = new HttpParams().set('code', code); + if (code || error) { + const params = new HttpParams().set('code', code).set('error', error); this.httpClient.get("esia/auth", { params: params, responseType: 'text', observe: 'response', headers: { @@ -56,6 +46,14 @@ export abstract class AuthGuard implements CanActivate { let errorMessage = reason.error.messages != null ? reason.error.messages : reason.error.replaceAll('\\', ''); + if (error) { + reason = 'Произошла неизвестная ошибка. Обратитесь к системному администратору'; + let errorCode = this.extractCode(errorDescription); + if (errorCode) { + reason = EsiaErrorDetail.getDescription(errorCode); + } + errorMessage = error + ', error description = ' + errorDescription; + } this.messageService.error(errorMessage); console.error(reason); });