diff --git a/pom.xml b/pom.xml index 9eb7c39..b7bc8e6 100644 --- a/pom.xml +++ b/pom.xml @@ -71,6 +71,10 @@ bcpkix-jdk15on 1.62 + + org.springframework.boot + spring-boot-starter-data-redis + org.springframework.boot spring-boot-starter-test diff --git a/src/main/java/com/openbankproject/RedisConfig.java b/src/main/java/com/openbankproject/RedisConfig.java new file mode 100644 index 0000000..a6fd01b --- /dev/null +++ b/src/main/java/com/openbankproject/RedisConfig.java @@ -0,0 +1,20 @@ +package com.openbankproject; + +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.data.redis.connection.RedisConnectionFactory; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.data.redis.serializer.StringRedisSerializer; + +@Configuration +public class RedisConfig { + + @Bean + public RedisTemplate redisTemplate(RedisConnectionFactory connectionFactory) { + RedisTemplate template = new RedisTemplate<>(); + template.setConnectionFactory(connectionFactory); + template.setKeySerializer(new StringRedisSerializer()); + template.setValueSerializer(new StringRedisSerializer()); + return template; + } +} diff --git a/src/main/java/com/openbankproject/RedisService.java b/src/main/java/com/openbankproject/RedisService.java new file mode 100644 index 0000000..b7277e3 --- /dev/null +++ b/src/main/java/com/openbankproject/RedisService.java @@ -0,0 +1,47 @@ +package com.openbankproject; + +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.data.redis.core.RedisTemplate; +import org.springframework.stereotype.Service; +import org.springframework.ui.Model; + +import javax.servlet.http.HttpSession; +import java.util.concurrent.TimeUnit; + +@Service +public class RedisService { + + @Autowired + private RedisTemplate redisTemplate; + + public void save(String key, String value) { + redisTemplate.opsForValue().set(key, value); + } + + // Save a value with a TTL (Time-to-Live) + public void saveWithTTL(String key, String value, long timeoutInSeconds) { + save(key, value); + // Set TTL for the key + redisTemplate.expire(key, timeoutInSeconds, TimeUnit.SECONDS); + } + + // Save a value with a TTL (Time-to-Live) + public void appendWithTTL(String key, String value, long timeoutInSeconds) { + String currentValue = get(key); + String currentValuePrintFriendly = currentValue != null ? currentValue : ""; + save(key, currentValuePrintFriendly + value); + // Set TTL for the key + redisTemplate.expire(key, timeoutInSeconds, TimeUnit.SECONDS); + } + + + public String get(String key) { + return (String) redisTemplate.opsForValue().get(key); + } + + public void readLogFromRedis(HttpSession session, Model model) { + String key = "log-entry-for-session-id: " + session.getId(); + String logEntries = get(key); + model.addAttribute("logEntriesForHtml", logEntries); + } +} diff --git a/src/main/java/com/openbankproject/oauth2/Oauth2Application.java b/src/main/java/com/openbankproject/oauth2/Oauth2Application.java index 08339f1..d376d54 100644 --- a/src/main/java/com/openbankproject/oauth2/Oauth2Application.java +++ b/src/main/java/com/openbankproject/oauth2/Oauth2Application.java @@ -14,6 +14,7 @@ import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.ComponentScan; import org.springframework.http.*; import org.springframework.web.client.HttpClientErrorException; import org.springframework.web.client.RestTemplate; @@ -33,6 +34,7 @@ import java.util.function.Function; import static com.openbankproject.oauth2.util.ControllerUtils.buildDirectLoginHeader; @SpringBootApplication +@ComponentScan(basePackages = "com.openbankproject") // Ensure this package is scanned public class Oauth2Application { private static final Logger logger = LoggerFactory.getLogger(Oauth2Application.class); diff --git a/src/main/java/com/openbankproject/oauth2/RestTemplateConfig.java b/src/main/java/com/openbankproject/oauth2/RestTemplateConfig.java index 49309b6..3ac6c53 100644 --- a/src/main/java/com/openbankproject/oauth2/RestTemplateConfig.java +++ b/src/main/java/com/openbankproject/oauth2/RestTemplateConfig.java @@ -6,6 +6,7 @@ import com.fasterxml.jackson.databind.ObjectMapper; import com.nimbusds.jose.JWSObject; import com.nimbusds.jose.jwk.RSAKey; import com.openbankproject.JwsUtil; +import com.openbankproject.RedisService; import org.apache.commons.codec.binary.Base64; import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; @@ -17,6 +18,7 @@ import org.apache.http.impl.client.HttpClients; import org.apache.http.protocol.HttpContext; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -41,6 +43,7 @@ import java.security.cert.CertificateException; import java.security.cert.X509Certificate; import java.security.interfaces.RSAPublicKey; import java.text.ParseException; +import java.time.Instant; import java.util.Arrays; import java.util.HashMap; import java.util.Map; @@ -120,24 +123,78 @@ public class RestTemplateConfig { private String getSessionId() { ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes(); - if (attributes != null) { + if (attributes != null && attributes.getRequest() != null && attributes.getRequest().getSession(false) != null ) { return attributes.getRequest().getSession(false).getId(); // Get the existing session, don't create a new one } return ""; } + + @Autowired + private RedisService redisService; + + public String printUtcDateTime() { + Instant now = Instant.now(); + return "at UTC Time: " + now.toString(); + } + + private StringBuilder saveRequestInfoToRedis(HttpRequest request, String body) { + System.out.println("Saving to Redis..."); + StringBuilder logEntry = buildRequestInfo(request, body); + String key = "log-entry-for-session-id: " + getSessionId(); + String value = logEntry.toString(); + redisService.appendWithTTL(key, value, 300); + return logEntry; + } + + private StringBuilder buildRequestInfo(HttpRequest request, String body) { + StringBuilder logEntry = new StringBuilder(); + logEntry.append("============= Request begin " + printUtcDateTime() + " =============\n") + .append("=== Session ID: ").append(getSessionId()).append("\n") + .append("=== Status Line : ").append(request.getRequestLine()).append("\n") + .append("=== Headers : ").append(StringUtils.join(request.getAllHeaders(), "; ")).append("\n") + .append("=== Request body: ").append(body).append("\n") + .append("============= Request end " + printUtcDateTime() + " =============\n"); + return logEntry; + } + + private StringBuilder saveResponseInfoTRedis(HttpResponse response, String body) { + System.out.println("Saving to Redis..."); + StringBuilder logEntry = buildResponseInfo(response, body); + String key = "log-entry-for-session-id: " + getSessionId(); + String value = logEntry.toString(); + redisService.appendWithTTL(key, value, 300); + return logEntry; + } + + private StringBuilder buildResponseInfo(HttpResponse response, String body) { + StringBuilder logEntry = new StringBuilder(); + logEntry.append("============= Response begin " + printUtcDateTime() + " =============\n") + .append("=== Session ID: ").append(getSessionId()).append("\n") + .append("=== Status Line : ").append(response.getStatusLine()).append("\n") + .append("=== Headers : ").append(StringUtils.join(response.getAllHeaders(), "; ")).append("\n") + .append("=== Response body: ").append(body).append("\n") + .append("============= Response end " + printUtcDateTime() + " =============\n"); + return logEntry; + } private void traceRequest(HttpRequest request, String body) throws IOException { + // Standard output logger.info("=========================== request begin ================================================ Session ID : {}", getSessionId()); logger.info("=== Request Line : {}, Session ID : {}", request.getRequestLine(), getSessionId()); logger.info("=== Headers : {}, Session ID : {}", StringUtils.join(request.getAllHeaders(), "; "), getSessionId()); logger.info("=== Request body: {}, Session ID : {}", body, getSessionId()); logger.info("============================= request end ================================================ Session ID : {}", getSessionId()); + // Save to Redis + saveRequestInfoToRedis(request, body).toString(); } private void traceResponse(HttpResponse response, String body) throws IOException { + // Standard output logger.info("=========================== response begin ================================================ Session ID : {}", getSessionId()); logger.info("=== Status Line : {}, Session ID : {}", response.getStatusLine(), getSessionId()); logger.info("=== Headers : {}, Session ID : {}", StringUtils.join(response.getAllHeaders(), "; "), getSessionId()); logger.info("=== Response body: {}, Session ID : {}", body, getSessionId()); logger.info("=========================== response end =================================================== Session ID : {}", getSessionId()); + // Save to Redis + saveResponseInfoTRedis(response, body); } private void responseIntercept(org.apache.http.HttpResponse response, HttpContext httpContext) throws IOException { HttpRequest req = (HttpRequest)httpContext.getAttribute("http.request"); diff --git a/src/main/java/com/openbankproject/oauth2/controller/ConsentController.java b/src/main/java/com/openbankproject/oauth2/controller/ConsentController.java index 6481ceb..549a56a 100644 --- a/src/main/java/com/openbankproject/oauth2/controller/ConsentController.java +++ b/src/main/java/com/openbankproject/oauth2/controller/ConsentController.java @@ -1,6 +1,7 @@ package com.openbankproject.oauth2.controller; import com.nimbusds.jose.util.X509CertUtils; +import com.openbankproject.RedisService; import com.openbankproject.oauth2.model.AccessToViewRequest; import com.openbankproject.oauth2.model.AccountMini; import com.openbankproject.oauth2.model.Accounts; @@ -9,6 +10,7 @@ import org.apache.commons.lang3.ArrayUtils; import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -95,6 +97,9 @@ public class ConsentController { private String idTokenSignHashAlg; + @Autowired + private RedisService redisService; + @PostConstruct private void initiate() { final Map>> keySet = restTemplate.getForObject(keySetUrl, Map.class); @@ -228,7 +233,8 @@ public class ConsentController { } } } - + + redisService.readLogFromRedis(session, model); model.addAttribute("consents", consents); model.addAttribute("showBankLogo", showBankLogo); model.addAttribute("obpBaseUrl", obpBaseUrl); @@ -280,6 +286,9 @@ public class ConsentController { ResponseEntity response2 = restTemplate.exchange(url, method, entity2, Map.class); String redirect = (String) session.getAttribute("acceptConsentResponse.getRedirectTo()"); logger.info("redirect:" + redirect); + + redisService.readLogFromRedis(session, model); + return "redirect:" + redirect; } catch (Exception e) { String error = "Sorry! The one time password (OTP) you supplied is incorrect."; @@ -294,8 +303,8 @@ public class ConsentController { return "error"; } } - - + + @PostMapping(value="/revoke_consents", params = "consent_challenge") public String revokeConsents(@RequestParam String consent_challenge, @RequestParam(value="consents", required = false) String[] consentIds, @@ -325,6 +334,7 @@ public class ConsentController { return "error"; } model.addAttribute("errorMsg", "All selected consents have been deleted!"); + redisService.readLogFromRedis(session, model); return "error"; } @@ -489,7 +499,9 @@ public class ConsentController { ResponseEntity authorizationIds = restTemplate.exchange(getConsentAuthorisation.replace("CONSENT_ID", consentId), HttpMethod.GET, entity, Map.class); ArrayList list = (ArrayList)authorizationIds.getBody().get("authorisationIds"); model.addAttribute("authorization_ids", String.join(", ", list)); - + + redisService.readLogFromRedis(session, model); + model.addAttribute("consent_challenge", consent_challenge); session.setAttribute("acceptConsentResponse.getRedirectTo()", acceptConsentResponse.getRedirectTo()); logger.info("acceptConsentResponse.getRedirectTo():" + acceptConsentResponse.getRedirectTo()); @@ -498,8 +510,13 @@ public class ConsentController { model.addAttribute("consent_challenge", consent_challenge); session.setAttribute("acceptConsentResponse.getRedirectTo()", acceptConsentResponse.getRedirectTo()); logger.info("acceptConsentResponse.getRedirectTo():" + acceptConsentResponse.getRedirectTo()); + + redisService.readLogFromRedis(session, model); + return "sca_modal"; } else { + redisService.readLogFromRedis(session, model); + return "redirect:" + acceptConsentResponse.getRedirectTo(); } } catch (Exception unhandledException) { diff --git a/src/main/java/com/openbankproject/oauth2/controller/LoginController.java b/src/main/java/com/openbankproject/oauth2/controller/LoginController.java index d2f06f4..98b4978 100644 --- a/src/main/java/com/openbankproject/oauth2/controller/LoginController.java +++ b/src/main/java/com/openbankproject/oauth2/controller/LoginController.java @@ -1,8 +1,10 @@ package com.openbankproject.oauth2.controller; +import com.openbankproject.RedisService; import com.openbankproject.oauth2.model.DirectLoginResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.http.HttpEntity; import org.springframework.http.HttpHeaders; @@ -68,6 +70,9 @@ public class LoginController implements ServletContextAware { private String showBankLogo; @Value("${logo.bank.url:#}") private String bankLogoUrl; + + @Autowired + private RedisService redisService; /** * initiate global variable @@ -179,8 +184,10 @@ public class LoginController implements ServletContextAware { AcceptLoginRequest acceptLoginRequest = new AcceptLoginRequest(); acceptLoginRequest.setSubject(loginRequest.getSubject()); CompletedRequest response = hydraAdmin.acceptLoginRequest(login_challenge, acceptLoginRequest); + redisService.readLogFromRedis(session, model); return "redirect:" + response.getRedirectTo(); } else { + redisService.readLogFromRedis(session, model); return "login"; } } catch (ApiException e) { diff --git a/src/main/resources/templates/accounts.html b/src/main/resources/templates/accounts.html index 7a10264..72eab8b 100644 --- a/src/main/resources/templates/accounts.html +++ b/src/main/resources/templates/accounts.html @@ -105,6 +105,8 @@ +
+ diff --git a/src/main/resources/templates/consent.html b/src/main/resources/templates/consent.html index 43bffa6..7c7c3a5 100644 --- a/src/main/resources/templates/consent.html +++ b/src/main/resources/templates/consent.html @@ -51,6 +51,7 @@ +
diff --git a/src/main/resources/templates/consents.html b/src/main/resources/templates/consents.html index fcbd8bc..7e0ffc3 100644 --- a/src/main/resources/templates/consents.html +++ b/src/main/resources/templates/consents.html @@ -53,6 +53,7 @@ +
diff --git a/src/main/resources/templates/error.html b/src/main/resources/templates/error.html index ecf7088..151f02d 100644 --- a/src/main/resources/templates/error.html +++ b/src/main/resources/templates/error.html @@ -32,6 +32,7 @@ He show some error message. +
diff --git a/src/main/resources/templates/login.html b/src/main/resources/templates/login.html index bcc6911..708c755 100644 --- a/src/main/resources/templates/login.html +++ b/src/main/resources/templates/login.html @@ -58,6 +58,7 @@ +
diff --git a/src/main/resources/templates/redis-log-widget.html b/src/main/resources/templates/redis-log-widget.html new file mode 100644 index 0000000..d19c09f --- /dev/null +++ b/src/main/resources/templates/redis-log-widget.html @@ -0,0 +1,15 @@ + +
+
+
+ +
+
+ +
+
diff --git a/src/main/resources/templates/sca_modal.html b/src/main/resources/templates/sca_modal.html index 5556096..e25881f 100644 --- a/src/main/resources/templates/sca_modal.html +++ b/src/main/resources/templates/sca_modal.html @@ -64,6 +64,8 @@ +
+