Skip to content

Commit 8e1b3e8

Browse files
committed
Improve SAML Logout
1. add property proxy.saml.logout-method to decide between local and SAML logout. Local logout will simply clear the cookies and redirect the user to the proxy.saml.logout-url (see later). SAML logout will first go to the `/saml/logout` endpoint, which redirects you to the IDP. The IDP should redirect you then back to proxy.saml.logout-url. 2. ensure proxy.saml.logout-url is also used by the `/saml/logout` endpoint.
1 parent cbfec34 commit 8e1b3e8

File tree

5 files changed

+121
-9
lines changed

5 files changed

+121
-9
lines changed

src/main/java/eu/openanalytics/containerproxy/auth/impl/SAMLAuthenticationBackend.java

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,9 @@ public class SAMLAuthenticationBackend implements IAuthenticationBackend {
4343

4444
public static final String NAME = "saml";
4545

46-
private static final String PROP_LOGOUT_URL = "proxy.saml.logout-url";
47-
46+
private static final String PROP_SUCCESS_LOGOUT_URL = "proxy.saml.logout-url";
47+
private static final String PROP_SAML_LOGOUT_METHOD = "proxy.saml.logout-method";
48+
4849
@Autowired(required = false)
4950
private SAMLEntryPoint samlEntryPoint;
5051

@@ -90,17 +91,29 @@ public void configureAuthenticationManagerBuilder(AuthenticationManagerBuilder a
9091

9192
@Override
9293
public String getLogoutURL() {
93-
if (environment.getProperty(PROP_LOGOUT_URL) != null) {
94+
LogoutMethod logoutMethod = environment.getProperty(PROP_SAML_LOGOUT_METHOD, LogoutMethod.class, LogoutMethod.LOCAL);
95+
if (logoutMethod == LogoutMethod.LOCAL) {
9496
return "/logout";
9597
}
96-
return "/saml/logout";
98+
return "/saml/logout"; // LogoutMethod.SAML
9799
}
98100

99101
@Override
100102
public String getLogoutSuccessURL() {
101-
String logoutURL = environment.getProperty(PROP_LOGOUT_URL);
102-
System.out.println("LogoutURL: " + logoutURL);
103-
if (logoutURL == null || logoutURL.trim().isEmpty()) logoutURL = "/";
103+
return determineLogoutSuccessURL(environment);
104+
}
105+
106+
public static String determineLogoutSuccessURL(Environment environment) {
107+
String logoutURL = environment.getProperty(PROP_SUCCESS_LOGOUT_URL);
108+
if (logoutURL == null || logoutURL.trim().isEmpty()) {
109+
logoutURL = "/";
110+
}
104111
return logoutURL;
105112
}
113+
114+
private enum LogoutMethod {
115+
LOCAL,
116+
SAML
117+
}
118+
106119
}

src/main/java/eu/openanalytics/containerproxy/auth/impl/saml/SAMLConfiguration.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@
3131

3232
import javax.inject.Inject;
3333

34+
import eu.openanalytics.containerproxy.auth.impl.SAMLAuthenticationBackend;
3435
import org.apache.commons.httpclient.HttpClient;
3536
import org.apache.logging.log4j.LogManager;
3637
import org.apache.logging.log4j.Logger;
@@ -157,7 +158,7 @@ public SecurityContextLogoutHandler securityContextLogoutHandler() {
157158
@Bean
158159
public SimpleUrlLogoutSuccessHandler successLogoutHandler() {
159160
SimpleUrlLogoutSuccessHandler successLogoutHandler = new SimpleUrlLogoutSuccessHandler();
160-
successLogoutHandler.setDefaultTargetUrl("/");
161+
successLogoutHandler.setDefaultTargetUrl(SAMLAuthenticationBackend.determineLogoutSuccessURL(environment));
161162
return successLogoutHandler;
162163
}
163164

src/main/java/eu/openanalytics/containerproxy/security/WebSecurityConfig.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ protected void configure(HttpSecurity http) throws Exception {
128128

129129
if (auth.hasAuthorization()) {
130130
http.authorizeRequests().antMatchers(
131-
"/login", "/signin/**", "/auth-error",
131+
"/login", "/signin/**", "/auth-error", "/logout-success",
132132
"/favicon.ico", "/css/**", "/img/**", "/js/**", "/assets/**", "/webjars/**").permitAll();
133133
http
134134
.formLogin()
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
/**
2+
* ContainerProxy
3+
*
4+
* Copyright (C) 2016-2020 Open Analytics
5+
*
6+
* ===========================================================================
7+
*
8+
* This program is free software: you can redistribute it and/or modify
9+
* it under the terms of the Apache License as published by
10+
* The Apache Software Foundation, either version 2 of the License, or
11+
* (at your option) any later version.
12+
*
13+
* This program is distributed in the hope that it will be useful,
14+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
15+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16+
* Apache License for more details.
17+
*
18+
* You should have received a copy of the Apache License
19+
* along with this program. If not, see <http://www.apache.org/licenses/>
20+
*/
21+
package eu.openanalytics.containerproxy.ui;
22+
23+
import eu.openanalytics.containerproxy.api.BaseController;
24+
import org.springframework.core.env.Environment;
25+
import org.springframework.stereotype.Controller;
26+
import org.springframework.ui.ModelMap;
27+
import org.springframework.web.bind.annotation.RequestMapping;
28+
import org.springframework.web.bind.annotation.RequestMethod;
29+
30+
import javax.inject.Inject;
31+
import javax.servlet.http.HttpServletRequest;
32+
33+
@Controller
34+
public class LogoutSuccessController extends BaseController {
35+
36+
@Inject
37+
private Environment environment;
38+
39+
@RequestMapping(value = "/logout-success", method = RequestMethod.GET)
40+
public String getAuthErrorPage() {
41+
return "logout-success";
42+
}
43+
44+
}
Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,54 @@
1+
<!--
2+
3+
ContainerProxy
4+
5+
Copyright (C) 2016-2020 Open Analytics
6+
7+
===========================================================================
8+
9+
This program is free software: you can redistribute it and/or modify
10+
it under the terms of the Apache License as published by
11+
The Apache Software Foundation, either version 2 of the License, or
12+
(at your option) any later version.
13+
14+
This program is distributed in the hope that it will be useful,
15+
but WITHOUT ANY WARRANTY; without even the implied warranty of
16+
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17+
Apache License for more details.
18+
19+
You should have received a copy of the Apache License
20+
along with this program. If not, see <http://www.apache.org/licenses/>
21+
22+
-->
23+
<!DOCTYPE html>
24+
<html
25+
xmlns:th="http://www.thymeleaf.org"
26+
xmlns:sec="http://www.thymeleaf.org/thymeleaf-extras-springsecurity4">
27+
28+
<head lang="en">
29+
<title th:text="${title}"></title>
30+
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
31+
<link rel="stylesheet" media="screen" th:href="@{/webjars/bootstrap/3.4.1/css/bootstrap.min.css}"/>
32+
<link rel="stylesheet" media="screen" th:href="@{/css/login.css}"/>
33+
<link rel="stylesheet" media="screen" type="text/css" href="https://cdn.jsdelivr.net/bootstrap-social/5.1.1/bootstrap-social.css"/>
34+
<link rel="stylesheet" media="screen" type="text/css" href="https://cdn.jsdelivr.net/fontawesome/4.7.0/css/font-awesome.min.css"/>
35+
<script th:src="@{/webjars/jquery/3.5.0/jquery.min.js}"></script>
36+
<script th:src="@{/webjars/bootstrap/3.4.1/js/bootstrap.min.js}"></script>
37+
</head>
38+
39+
<body>
40+
<div class="container">
41+
<h2>You have been logged out successfully.</h2>
42+
<p><a th:href="@{/}"><b>Login again</b></a></p>
43+
</div>
44+
45+
<style>
46+
h2 {
47+
margin-bottom: 20px;
48+
margin-top: 20px;
49+
}
50+
</style>
51+
52+
</body>
53+
54+
</html>

0 commit comments

Comments
 (0)