diff --git a/dqops/src/main/frontend/src/components/UserProfile/index.tsx b/dqops/src/main/frontend/src/components/UserProfile/index.tsx
index 42a5422fa7..b79a633f62 100644
--- a/dqops/src/main/frontend/src/components/UserProfile/index.tsx
+++ b/dqops/src/main/frontend/src/components/UserProfile/index.tsx
@@ -255,6 +255,14 @@ export default function UserProfile({ name, email }: UserProfile) {
>
)}
+ {userProfile.can_logout === true && (
+
+ Logout
+
+ )}
filter(ServerWebExchange exchange, WebFilterChain chain) {
.then();
}
+ if (Objects.equals(requestPath, LOGOUT_PATH)) {
+ String hostHeader = request.getHeaders().getHost().getHostString();
+
+ int portPrefixIndex = hostHeader.indexOf(':');
+ if (portPrefixIndex > 0) {
+ hostHeader = hostHeader.substring(0, portPrefixIndex);
+ }
+
+ ResponseCookie dqoAccessTokenCookie = ResponseCookie.from(AUTHENTICATION_TOKEN_COOKIE, "")
+ .maxAge(0L)
+ .path("/")
+ .domain(hostHeader)
+ .build();
+ exchange.getResponse().getCookies().add(AUTHENTICATION_TOKEN_COOKIE, dqoAccessTokenCookie);
+
+ try {
+ String returnUrl = exchange.getRequest().getURI().resolve("/").toString();
+ String dqoCloudLoginUrl = this.instanceCloudLoginService.makeDqoLogoutUrl(returnUrl);
+
+ if (log.isDebugEnabled()) {
+ log.debug("Redirecting the user to logout and authenticate with DQOps Cloud federated authentication at " + dqoCloudLoginUrl);
+ }
+
+ exchange.getResponse().setStatusCode(HttpStatusCode.valueOf(303));
+ exchange.getResponse().getHeaders().add("Location", dqoCloudLoginUrl);
+ return exchange.getResponse().writeAndFlushWith(Mono.empty());
+ }
+ catch (Exception ex) {
+ log.error("Cannot create a DQOps Cloud login url: " + ex.getMessage(), ex);
+ exchange.getResponse().setStatusCode(HttpStatusCode.valueOf(500));
+ return exchange.getResponse().writeAndFlushWith(Mono.empty());
+ }
+ }
+
if (Objects.equals(requestPath, ISSUE_TOKEN_REQUEST_PATH)) {
exchange.getResponse().setStatusCode(HttpStatusCode.valueOf(303));
String returnUrl = exchange.getRequest().getQueryParams().getFirst("returnUrl");
diff --git a/dqops/src/main/resources/application.yml b/dqops/src/main/resources/application.yml
index 142d1ef74f..b50a2384ee 100644
--- a/dqops/src/main/resources/application.yml
+++ b/dqops/src/main/resources/application.yml
@@ -115,6 +115,7 @@ dqo:
#ui-base-url: http://localhost:8080
#rest-api-base-url: http://localhost:8080
api-key-request-url: ${dqo.cloud.ui-base-url}/requestapikey/
+ logout-url: ${dqo.cloud.ui-base-url}/login?logout=true
api-key-pickup-timeout-seconds: 600
api-key-pickup-retry-delay-millis: 1000
parallel-file-uploads: 500
diff --git a/dqops/src/main/resources/static/swagger-api/dqops-api-swagger-2.json b/dqops/src/main/resources/static/swagger-api/dqops-api-swagger-2.json
index 8799d9b79e..0b607a729f 100644
--- a/dqops/src/main/resources/static/swagger-api/dqops-api-swagger-2.json
+++ b/dqops/src/main/resources/static/swagger-api/dqops-api-swagger-2.json
@@ -39351,6 +39351,10 @@
"can_use_ai_anomaly_detection" : {
"type" : "boolean",
"description" : "The DQOps instance is a paid version with advanced AI anomaly prediction."
+ },
+ "can_logout" : {
+ "type" : "boolean",
+ "description" : "This instance uses federated authentication and the user can log out."
}
},
"description" : "The model that describes the current user and his access rights."
diff --git a/dqops/src/main/resources/static/swagger-api/dqops-api-swagger-2.yaml b/dqops/src/main/resources/static/swagger-api/dqops-api-swagger-2.yaml
index dcc9226188..059c2e3aa0 100644
--- a/dqops/src/main/resources/static/swagger-api/dqops-api-swagger-2.yaml
+++ b/dqops/src/main/resources/static/swagger-api/dqops-api-swagger-2.yaml
@@ -38080,6 +38080,10 @@ definitions:
type: "boolean"
description: "The DQOps instance is a paid version with advanced AI anomaly\
\ prediction."
+ can_logout:
+ type: "boolean"
+ description: "This instance uses federated authentication and the user can\
+ \ log out."
description: "The model that describes the current user and his access rights."
DqoUserRolesModel:
type: "object"