From b9c39afad262a24df91f023b78081b96c039b1d0 Mon Sep 17 00:00:00 2001 From: Milton Ch <86965029+Milton-Ch@users.noreply.github.com> Date: Thu, 13 Jan 2022 05:01:23 -0400 Subject: [PATCH] feat: add correlation id in pages and rest endpoints to track logs (#410) --- .../io/jans/as/model/config/Constants.java | 2 + .../as/model/error/ErrorResponseFactory.java | 11 +++- .../as/server/filter/CorrelationIdFilter.java | 56 +++++++++++++++++++ .../server/par/ws/rs/ParRestWebService.java | 16 +++++- server/src/main/resources/log4j2.xml | 12 ++-- .../main/webapp/auth/otp_sms/otp_sms.xhtml | 6 ++ .../main/webapp/auth/register/register.xhtml | 6 ++ .../webapp/auth/thumbsignin/tsLogin.xhtml | 6 ++ server/src/main/webapp/casa/login.xhtml | 8 ++- server/src/main/webapp/casa/otp.xhtml | 6 ++ server/src/main/webapp/ciba/home.xhtml | 7 +++ .../main/webapp/device_authorization.xhtml | 7 +++ server/src/main/webapp/error.xhtml | 6 ++ server/src/main/webapp/error_service.xhtml | 7 +++ server/src/main/webapp/error_session.xhtml | 7 +++ server/src/main/webapp/login.xhtml | 6 ++ 16 files changed, 159 insertions(+), 10 deletions(-) create mode 100644 server/src/main/java/io/jans/as/server/filter/CorrelationIdFilter.java diff --git a/model/src/main/java/io/jans/as/model/config/Constants.java b/model/src/main/java/io/jans/as/model/config/Constants.java index a440c4324d1..57a7cdfa679 100644 --- a/model/src/main/java/io/jans/as/model/config/Constants.java +++ b/model/src/main/java/io/jans/as/model/config/Constants.java @@ -57,4 +57,6 @@ private Constants() { public static final String AUTHORIZATION_BASIC = "Authorization: Basic "; public static final String REASON_CLIENT_NOT_AUTHORIZED = "The client is not authorized."; + + public static final String CORRELATION_ID_HEADER = "X-Correlation-Id"; } diff --git a/model/src/main/java/io/jans/as/model/error/ErrorResponseFactory.java b/model/src/main/java/io/jans/as/model/error/ErrorResponseFactory.java index 8566712d2f1..7a127da72c1 100644 --- a/model/src/main/java/io/jans/as/model/error/ErrorResponseFactory.java +++ b/model/src/main/java/io/jans/as/model/error/ErrorResponseFactory.java @@ -12,6 +12,7 @@ import io.jans.as.model.ciba.BackchannelAuthenticationErrorResponseType; import io.jans.as.model.clientinfo.ClientInfoErrorResponseType; import io.jans.as.model.common.ComponentType; +import io.jans.as.model.config.Constants; import io.jans.as.model.configuration.AppConfiguration; import io.jans.as.model.configuration.Configuration; import io.jans.as.model.fido.u2f.U2fErrorResponseType; @@ -22,6 +23,8 @@ import io.jans.as.model.uma.UmaErrorResponseType; import io.jans.as.model.userinfo.UserInfoErrorResponseType; import io.jans.as.model.util.Util; +import org.apache.commons.lang.StringUtils; +import org.apache.logging.log4j.ThreadContext; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.slf4j.Logger; @@ -32,6 +35,7 @@ import javax.ws.rs.core.Response; import java.io.IOException; import java.util.List; +import java.util.Optional; import java.util.Set; /** @@ -190,7 +194,12 @@ public DefaultErrorResponse getErrorResponse(IErrorType type) { if (list != null) { final ErrorMessage m = getError(list, type); - response.setErrorDescription(m.getDescription()); + + String description = Optional.ofNullable(ThreadContext.get(Constants.CORRELATION_ID_HEADER)) + .map(id -> m.getDescription().concat(" CorrelationId: " + id)) + .orElse(m.getDescription()); + + response.setErrorDescription(description); response.setErrorUri(m.getUri()); } } diff --git a/server/src/main/java/io/jans/as/server/filter/CorrelationIdFilter.java b/server/src/main/java/io/jans/as/server/filter/CorrelationIdFilter.java new file mode 100644 index 00000000000..8c6e2c3a5ca --- /dev/null +++ b/server/src/main/java/io/jans/as/server/filter/CorrelationIdFilter.java @@ -0,0 +1,56 @@ +package io.jans.as.server.filter; + +import io.jans.as.server.uma.authorization.UmaWebException; +import org.apache.commons.lang.StringUtils; +import org.apache.logging.log4j.ThreadContext; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import javax.servlet.*; +import javax.servlet.annotation.WebFilter; +import javax.servlet.http.Cookie; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.util.UUID; +import java.util.stream.Stream; + +import static io.jans.as.model.config.Constants.CORRELATION_ID_HEADER; + +@WebFilter(filterName = "CorrelationIdFilter", asyncSupported = true, urlPatterns = {"/*"}) +public class CorrelationIdFilter implements Filter { + + private static final Logger log = LoggerFactory.getLogger(UmaWebException.class); + + @Override + public void init(FilterConfig filterConfig) throws ServletException { + } + + @Override + public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain) throws IOException, ServletException { + HttpServletRequest httpRequest = (HttpServletRequest) request; + HttpServletResponse httpResponse = (HttpServletResponse) response; + + String correlationId = httpRequest.getHeader(CORRELATION_ID_HEADER); + if (StringUtils.isBlank(correlationId)) { + correlationId = UUID.randomUUID().toString(); + + Cookie[] cookies = httpRequest.getCookies(); + if (cookies == null || Stream.of(cookies).noneMatch(cookie -> cookie.getName().contains(CORRELATION_ID_HEADER))) { + Cookie cookie = new Cookie(CORRELATION_ID_HEADER, correlationId); + cookie.setSecure(true); + cookie.setHttpOnly(true); + httpResponse.addCookie(cookie); + } + } + + ThreadContext.put(CORRELATION_ID_HEADER, correlationId); + + chain.doFilter(request, response); + } + + @Override + public void destroy() { + } + +} diff --git a/server/src/main/java/io/jans/as/server/par/ws/rs/ParRestWebService.java b/server/src/main/java/io/jans/as/server/par/ws/rs/ParRestWebService.java index 5f2124f4d30..e1134a46c54 100644 --- a/server/src/main/java/io/jans/as/server/par/ws/rs/ParRestWebService.java +++ b/server/src/main/java/io/jans/as/server/par/ws/rs/ParRestWebService.java @@ -7,6 +7,7 @@ import io.jans.as.model.common.ComponentType; import io.jans.as.model.common.ResponseMode; import io.jans.as.model.common.ResponseType; +import io.jans.as.model.config.Constants; import io.jans.as.model.configuration.AppConfiguration; import io.jans.as.model.error.ErrorResponse; import io.jans.as.model.error.ErrorResponseFactory; @@ -19,6 +20,7 @@ import io.jans.as.server.util.QueryStringDecoder; import io.jans.as.server.util.ServerUtil; import org.apache.commons.lang3.StringUtils; +import org.apache.logging.log4j.ThreadContext; import org.jetbrains.annotations.NotNull; import org.slf4j.Logger; @@ -40,6 +42,8 @@ import javax.ws.rs.core.SecurityContext; import java.net.URI; import java.util.List; +import java.util.Objects; +import java.util.Optional; /** * Implementation based on https://datatracker.ietf.org/doc/html/draft-ietf-oauth-par-08 @@ -199,8 +203,16 @@ private ErrorResponse createErrorResponseFromRedirectErrorUri(@NotNull URI locat locationRedirect.parseQueryString(location.getQuery()); final ErrorResponse response = new ErrorResponse(); - response.setErrorCode(locationRedirect.getResponseParameter("error")); - response.setErrorDescription(locationRedirect.getResponseParameter("error_description")); + + String errorDescription = locationRedirect.getResponseParameter("error_description"); + errorDescription = Optional.ofNullable(errorDescription) + .map(description -> Optional.ofNullable(ThreadContext.get(Constants.CORRELATION_ID_HEADER)) + .map(id -> description.concat(" CorrelationId: " + id)) + .orElse(description)) + .orElse(null); + + response.setErrorCode(errorDescription); + response.setErrorDescription(errorDescription); return response; } diff --git a/server/src/main/resources/log4j2.xml b/server/src/main/resources/log4j2.xml index 752189af9a8..9c45202bcd9 100644 --- a/server/src/main/resources/log4j2.xml +++ b/server/src/main/resources/log4j2.xml @@ -19,7 +19,7 @@ - + @@ -30,7 +30,7 @@ - + @@ -41,7 +41,7 @@ - + @@ -53,7 +53,7 @@ - + @@ -64,7 +64,7 @@ - + @@ -75,7 +75,7 @@ - + diff --git a/server/src/main/webapp/auth/otp_sms/otp_sms.xhtml b/server/src/main/webapp/auth/otp_sms/otp_sms.xhtml index f1d6b55535f..88a255ba54d 100644 --- a/server/src/main/webapp/auth/otp_sms/otp_sms.xhtml +++ b/server/src/main/webapp/auth/otp_sms/otp_sms.xhtml @@ -120,6 +120,12 @@ input.btn.btn-done { #{msgs['otp_sms.termsPrivacy']}

+ +
+

+ Correlation Id: +

+
+ +
+

+ Correlation Id: +

+
diff --git a/server/src/main/webapp/casa/login.xhtml b/server/src/main/webapp/casa/login.xhtml index b5c5abf9f1a..1d81892c414 100644 --- a/server/src/main/webapp/casa/login.xhtml +++ b/server/src/main/webapp/casa/login.xhtml @@ -30,7 +30,13 @@ - + + +
+

+ Correlation Id: +

+
diff --git a/server/src/main/webapp/casa/otp.xhtml b/server/src/main/webapp/casa/otp.xhtml index 4e550cf6c06..7b33659f003 100644 --- a/server/src/main/webapp/casa/otp.xhtml +++ b/server/src/main/webapp/casa/otp.xhtml @@ -33,6 +33,12 @@ + +
+

+ Correlation Id: +

+
diff --git a/server/src/main/webapp/ciba/home.xhtml b/server/src/main/webapp/ciba/home.xhtml index d8c69c27d99..465ea03817e 100644 --- a/server/src/main/webapp/ciba/home.xhtml +++ b/server/src/main/webapp/ciba/home.xhtml @@ -72,6 +72,13 @@ + +
+

+ Correlation Id: +

+
+ diff --git a/server/src/main/webapp/device_authorization.xhtml b/server/src/main/webapp/device_authorization.xhtml index d2760222208..5b5f7fc3c18 100644 --- a/server/src/main/webapp/device_authorization.xhtml +++ b/server/src/main/webapp/device_authorization.xhtml @@ -95,6 +95,13 @@
+ + +
+

+ Correlation Id: +

+