mirror of
https://github.com/OpenBankProject/OBP-Hydra-Identity-Provider.git
synced 2026-02-06 10:48:13 +00:00
Merge branch 'develop' into hydra-2.2.0
# Conflicts: # src/main/java/com/openbankproject/oauth2/controller/LoginController.java
This commit is contained in:
commit
c522ca53b1
4
pom.xml
4
pom.xml
@ -84,6 +84,10 @@
|
||||
<artifactId>bcpkix-jdk15on</artifactId>
|
||||
<version>1.62</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-data-redis</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-test</artifactId>
|
||||
|
||||
11
src/main/java/com/openbankproject/DateTimeUtils.java
Normal file
11
src/main/java/com/openbankproject/DateTimeUtils.java
Normal file
@ -0,0 +1,11 @@
|
||||
package com.openbankproject;
|
||||
|
||||
// DateTimeUtils.java
|
||||
import java.time.Instant;
|
||||
|
||||
public class DateTimeUtils {
|
||||
public static String printUtcDateTime() {
|
||||
Instant now = Instant.now();
|
||||
return "at UTC Time: " + now.toString();
|
||||
}
|
||||
}
|
||||
20
src/main/java/com/openbankproject/RedisConfig.java
Normal file
20
src/main/java/com/openbankproject/RedisConfig.java
Normal file
@ -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<String, Object> redisTemplate(RedisConnectionFactory connectionFactory) {
|
||||
RedisTemplate<String, Object> template = new RedisTemplate<>();
|
||||
template.setConnectionFactory(connectionFactory);
|
||||
template.setKeySerializer(new StringRedisSerializer());
|
||||
template.setValueSerializer(new StringRedisSerializer());
|
||||
return template;
|
||||
}
|
||||
}
|
||||
67
src/main/java/com/openbankproject/RedisService.java
Normal file
67
src/main/java/com/openbankproject/RedisService.java
Normal file
@ -0,0 +1,67 @@
|
||||
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.List;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@Service
|
||||
public class RedisService {
|
||||
|
||||
@Autowired
|
||||
private RedisTemplate<String, Object> 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 saveLogToRedis(String key, String value) {
|
||||
System.out.println("Saving to Redis...");
|
||||
appendToListWithTTL(key, value, 300);
|
||||
}
|
||||
public void readLogFromRedis(HttpSession session, Model model) {
|
||||
String key = "log-entry-for-session-id: " + session.getId();
|
||||
List<Object> logEntries = getStringList(key);
|
||||
List<Object> logEntriesAsStrings = logEntries.stream().map(Object::toString).collect(Collectors.toList());
|
||||
model.addAttribute("logEntriesForHtml", logEntriesAsStrings);
|
||||
}
|
||||
|
||||
|
||||
public void appendToListWithTTL(String key, String value, long timeoutInSeconds) {
|
||||
// Add each string in the list to Redis list
|
||||
redisTemplate.opsForList().rightPush(key, value);
|
||||
// Set TTL for the key
|
||||
redisTemplate.expire(key, timeoutInSeconds, TimeUnit.SECONDS);
|
||||
}
|
||||
|
||||
public List<Object> getStringList(String key) {
|
||||
// Retrieve the entire list from Redis
|
||||
return redisTemplate.opsForList().range(key, 0, -1);
|
||||
}
|
||||
}
|
||||
53
src/main/java/com/openbankproject/RequestResponseLogger.java
Normal file
53
src/main/java/com/openbankproject/RequestResponseLogger.java
Normal file
@ -0,0 +1,53 @@
|
||||
package com.openbankproject;
|
||||
|
||||
// RequestResponseLogger.java
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Component;
|
||||
|
||||
@Component
|
||||
public class RequestResponseLogger {
|
||||
|
||||
@Autowired
|
||||
private RedisService redisService;
|
||||
|
||||
public StringBuilder saveRequestInfoToRedis(HttpRequest request, String body) {
|
||||
StringBuilder logEntry = buildRequestInfo(request, body);
|
||||
String key = "log-entry-for-session-id: " + SessionUtils.getSessionId();
|
||||
String value = logEntry.toString();
|
||||
redisService.saveLogToRedis(key, value);
|
||||
return logEntry;
|
||||
}
|
||||
|
||||
private StringBuilder buildRequestInfo(HttpRequest request, String body) {
|
||||
StringBuilder logEntry = new StringBuilder();
|
||||
logEntry.append("============= Request begin ").append(DateTimeUtils.printUtcDateTime()).append(" =============\n")
|
||||
.append("=== Session ID: ").append(SessionUtils.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 ").append(DateTimeUtils.printUtcDateTime()).append(" =============\n");
|
||||
return logEntry;
|
||||
}
|
||||
|
||||
public StringBuilder saveResponseInfoToRedis(HttpResponse response, String body) {
|
||||
StringBuilder logEntry = buildResponseInfo(response, body);
|
||||
String key = "log-entry-for-session-id: " + SessionUtils.getSessionId();
|
||||
String value = logEntry.toString();
|
||||
redisService.saveLogToRedis(key, value);
|
||||
return logEntry;
|
||||
}
|
||||
|
||||
private StringBuilder buildResponseInfo(HttpResponse response, String body) {
|
||||
StringBuilder logEntry = new StringBuilder();
|
||||
logEntry.append("============= Response begin ").append(DateTimeUtils.printUtcDateTime()).append(" =============\n")
|
||||
.append("=== Session ID: ").append(SessionUtils.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 ").append(DateTimeUtils.printUtcDateTime()).append(" =============\n");
|
||||
return logEntry;
|
||||
}
|
||||
}
|
||||
16
src/main/java/com/openbankproject/SessionUtils.java
Normal file
16
src/main/java/com/openbankproject/SessionUtils.java
Normal file
@ -0,0 +1,16 @@
|
||||
package com.openbankproject;
|
||||
|
||||
// SessionUtils.java
|
||||
import org.springframework.web.context.request.RequestContextHolder;
|
||||
import org.springframework.web.context.request.ServletRequestAttributes;
|
||||
|
||||
public class SessionUtils {
|
||||
public static String getSessionId() {
|
||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
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 "";
|
||||
}
|
||||
}
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -6,6 +6,8 @@ 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 com.openbankproject.RequestResponseLogger;
|
||||
import org.apache.commons.codec.binary.Base64;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
@ -17,6 +19,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;
|
||||
@ -46,6 +49,8 @@ import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
|
||||
import static com.openbankproject.SessionUtils.getSessionId;
|
||||
|
||||
@Configuration
|
||||
public class RestTemplateConfig {
|
||||
private static final Logger logger = LoggerFactory.getLogger(RestTemplateConfig.class);
|
||||
@ -63,6 +68,10 @@ public class RestTemplateConfig {
|
||||
@Value("${force_jws}")
|
||||
private String forceJws;
|
||||
|
||||
@Autowired
|
||||
private RequestResponseLogger requestResponseLogger;
|
||||
|
||||
|
||||
@Bean
|
||||
public RestTemplate restTemplate(SSLContext sslContext) {
|
||||
SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext);
|
||||
@ -118,26 +127,25 @@ public class RestTemplateConfig {
|
||||
}
|
||||
}
|
||||
|
||||
private String getSessionId() {
|
||||
ServletRequestAttributes attributes = (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
|
||||
if (attributes != null) {
|
||||
return attributes.getRequest().getSession(false).getId(); // Get the existing session, don't create a new one
|
||||
}
|
||||
return "";
|
||||
}
|
||||
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
|
||||
requestResponseLogger.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
|
||||
requestResponseLogger.saveResponseInfoToRedis(response, body);
|
||||
}
|
||||
private void responseIntercept(org.apache.http.HttpResponse response, HttpContext httpContext) throws IOException {
|
||||
HttpRequest req = (HttpRequest)httpContext.getAttribute("http.request");
|
||||
|
||||
@ -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<String, List<Map<String, String>>> 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<Map> 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<Map> authorizationIds = restTemplate.exchange(getConsentAuthorisation.replace("CONSENT_ID", consentId), HttpMethod.GET, entity, Map.class);
|
||||
ArrayList<String> list = (ArrayList<String>)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) {
|
||||
|
||||
@ -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,7 +70,10 @@ public class LoginController implements ServletContextAware {
|
||||
private String showBankLogo;
|
||||
@Value("${logo.bank.url:#}")
|
||||
private String bankLogoUrl;
|
||||
|
||||
|
||||
@Autowired
|
||||
private RedisService redisService;
|
||||
|
||||
/**
|
||||
* initiate global variable
|
||||
* @param servletContext
|
||||
@ -179,8 +184,10 @@ public class LoginController implements ServletContextAware {
|
||||
AcceptOAuth2LoginRequest acceptLoginRequest = new AcceptOAuth2LoginRequest();
|
||||
acceptLoginRequest.setSubject(loginRequest.getSubject());
|
||||
OAuth2RedirectTo response = hydraAdmin.acceptOAuth2LoginRequest(login_challenge, acceptLoginRequest);
|
||||
redisService.readLogFromRedis(session, model);
|
||||
return "redirect:" + response.getRedirectTo();
|
||||
} else {
|
||||
redisService.readLogFromRedis(session, model);
|
||||
return "login";
|
||||
}
|
||||
} catch (ApiException e) {
|
||||
|
||||
@ -105,6 +105,8 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div th:include="redis-log-widget :: redisLogWidget"></div>
|
||||
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" th:src="@{/js/jquery-1.12.4.min.js}" ></script>
|
||||
|
||||
@ -51,6 +51,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:include="redis-log-widget :: redisLogWidget"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" th:src="@{/js/jquery-1.12.4.min.js}" ></script>
|
||||
|
||||
@ -53,6 +53,7 @@
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<div th:include="redis-log-widget :: redisLogWidget"></div>
|
||||
</div>
|
||||
|
||||
<script type="text/javascript" th:src="@{/js/jquery-1.12.4.min.js}" ></script>
|
||||
|
||||
@ -32,6 +32,7 @@
|
||||
<span id="warning_msg" th:utext="${errorMsg}">He show some error message.</span>
|
||||
</div>
|
||||
</div>
|
||||
<div th:include="redis-log-widget :: redisLogWidget"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" th:src="@{/js/jquery-1.12.4.min.js}" ></script>
|
||||
|
||||
@ -58,6 +58,7 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:include="redis-log-widget :: redisLogWidget"></div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" th:src="@{/js/jquery-1.12.4.min.js}" ></script>
|
||||
|
||||
21
src/main/resources/templates/redis-log-widget.html
Normal file
21
src/main/resources/templates/redis-log-widget.html
Normal file
@ -0,0 +1,21 @@
|
||||
<!-- redis-log-widget.html -->
|
||||
<div th:fragment="redisLogWidget">
|
||||
<hr>
|
||||
<div class="text-center">
|
||||
<button class="btn btn-info" type="button" data-toggle="collapse" data-target="#logEntriesContent" aria-expanded="false" aria-controls="logEntriesContent">
|
||||
Show/Hide log of Hydra Identity Provider app
|
||||
</button>
|
||||
</div>
|
||||
<br>
|
||||
<div class="collapse mt-3" id="logEntriesContent">
|
||||
<div th:if="${logEntriesForHtml}">
|
||||
<!-- Iterate over each log entry in the list and display it as a dismissible alert -->
|
||||
<div th:each="logEntry : ${logEntriesForHtml}" class="alert alert-info alert-dismissible col-md-12" role="alert">
|
||||
<button type="button" class="close" data-dismiss="alert" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
<span th:text="${logEntry}" style="white-space: pre-wrap;"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -64,6 +64,8 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div th:include="redis-log-widget :: redisLogWidget"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<script type="text/javascript" th:src="@{/js/jquery-1.12.4.min.js}" ></script>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user