Skip to content

Commit 9104231

Browse files
committed
[ELY-2534] OIDC logout support
1 parent d6804de commit 9104231

9 files changed

Lines changed: 40 additions & 21 deletions

File tree

http/oidc/src/main/java/org/wildfly/security/http/oidc/LogoutHandler.java

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -63,19 +63,24 @@ protected boolean removeEldestEntry(Map.Entry<String, OidcClientConfiguration> e
6363
});
6464

6565
boolean tryLogout(OidcHttpFacade facade) {
66+
log.trace("tryLogout entered");
6667
RefreshableOidcSecurityContext securityContext = getSecurityContext(facade);
6768
if (securityContext == null) {
6869
// no active session
70+
log.trace("tryLogout securityContext == null");
6971
return false;
7072
}
7173

7274
if (isRpInitiatedLogoutPath(facade)) {
75+
log.trace("isRpInitiatedLogoutPath");
7376
redirectEndSessionEndpoint(facade);
7477
return true;
7578
}
7679

7780
if (isLogoutCallbackPath(facade)) {
81+
log.trace("isLogoutCallbackPath");
7882
if (isFrontChannel(facade)) {
83+
log.trace("isFrontChannel");
7984
handleFrontChannelLogoutRequest(facade);
8085
return true;
8186
} else {
@@ -84,7 +89,6 @@ boolean tryLogout(OidcHttpFacade facade) {
8489
facade.authenticationFailed();
8590
}
8691
}
87-
8892
return false;
8993
}
9094

@@ -119,6 +123,7 @@ private void redirectEndSessionEndpoint(OidcHttpFacade facade) {
119123
}
120124

121125
logoutUri = redirectUriBuilder.build().toString();
126+
log.trace("redirectEndSessionEndpoint path: " + redirectUriBuilder.toString());
122127
} catch (URISyntaxException e) {
123128
throw new RuntimeException(e);
124129
}
@@ -129,8 +134,11 @@ private void redirectEndSessionEndpoint(OidcHttpFacade facade) {
129134
}
130135

131136
boolean tryBackChannelLogout(OidcHttpFacade facade) {
137+
log.trace("tryBackChannelLogout entered");
132138
if (isLogoutCallbackPath(facade)) {
139+
log.trace("isLogoutCallbackPath");
133140
if (isBackChannel(facade)) {
141+
log.trace("isBackChannel");
134142
handleBackChannelLogoutRequest(facade);
135143
return true;
136144
}
@@ -219,7 +227,7 @@ private String getRedirectUri(OidcHttpFacade facade) {
219227
return uri;
220228
}
221229

222-
boolean isLogoutCallbackPath(OidcHttpFacade facade) {
230+
private boolean isLogoutCallbackPath(OidcHttpFacade facade) {
223231
String path = facade.getRequest().getRelativePath();
224232
return path.endsWith(getLogoutCallbackPath(facade));
225233
}

http/oidc/src/main/java/org/wildfly/security/http/oidc/OidcAuthenticationMechanism.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ public String getMechanismName() {
6060

6161
@Override
6262
public void evaluateRequest(HttpServerRequest request) throws HttpAuthenticationException {
63-
String tmpURI = request.getRequestURI().toString();
63+
log.debug("evaluateRequest uri: " + request.getRequestURI().toString());
6464
OidcClientContext oidcClientContext = getOidcClientContext(request);
6565
if (oidcClientContext == null) {
6666
log.debugf("Ignoring request for path [%s] from mechanism [%s]. No client configuration context found.", request.getRequestURI(), getMechanismName());

http/oidc/src/main/java/org/wildfly/security/http/oidc/OidcClientConfigurationBuilder.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -200,6 +200,7 @@ protected OidcClientConfiguration internalBuild(final OidcJsonConfiguration oidc
200200
oidcClientConfiguration.setTokenSignatureAlgorithm(oidcJsonConfiguration.getTokenSignatureAlgorithm());
201201

202202
String tmpLogoutPath = System.getProperty(LOGOUT_PATH);
203+
log.debug("sysProp LOGOUT_PATH: " + (tmpLogoutPath == null ? "NULL" : tmpLogoutPath));
203204
if (tmpLogoutPath != null) {
204205
if (isValidPath(tmpLogoutPath)) {
205206
oidcClientConfiguration.setLogoutPath(tmpLogoutPath);
@@ -210,6 +211,7 @@ protected OidcClientConfiguration internalBuild(final OidcJsonConfiguration oidc
210211

211212

212213
String tmpLogoutCallbackPath = System.getProperty(LOGOUT_CALLBACK_PATH);
214+
log.debug("sysProp LOGOUT_CALLBACK_PATH: " + (tmpLogoutCallbackPath == null ? "NULL" : tmpLogoutCallbackPath));
213215
if (tmpLogoutCallbackPath != null) {
214216
if (isValidPath(tmpLogoutCallbackPath)
215217
&& !tmpLogoutCallbackPath.endsWith(oidcClientConfiguration.getLogoutPath())) {
@@ -225,6 +227,7 @@ protected OidcClientConfiguration internalBuild(final OidcJsonConfiguration oidc
225227
}
226228

227229
String tmpPostLogoutPath = System.getProperty(POST_LOGOUT_PATH);
230+
log.debug("sysProp POST_LOGOUT_PATH: " + (tmpPostLogoutPath == null ? "NULL" : tmpPostLogoutPath));
228231
if (tmpPostLogoutPath != null) {
229232
if (isValidPath(tmpPostLogoutPath)) {
230233
oidcClientConfiguration.setPostLogoutPath(tmpPostLogoutPath);

http/oidc/src/main/java/org/wildfly/security/http/oidc/OidcRequestAuthenticator.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,6 @@ protected String getCode() {
190190
protected String getRedirectUri(String state, String sessionRandomValueHash) {
191191
String url = getRequestUrl();
192192
log.debugf("callback uri: %s", url);
193-
194193
try {
195194
if (! facade.getRequest().isSecure() && deployment.getSSLRequired().isRequired(facade.getRequest().getRemoteAddr())) {
196195
int port = getSSLRedirectPort();

http/oidc/src/main/java/org/wildfly/security/http/oidc/OidcSessionTokenStore.java

Lines changed: 12 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -45,21 +45,29 @@ public OidcSessionTokenStore(OidcHttpFacade httpFacade) {
4545
@Override
4646
public void checkCurrentToken() {
4747
HttpScope session = httpFacade.getScope(Scope.SESSION);
48-
if (session == null || ! session.exists()) return;
48+
if (session == null || ! session.exists()) {
49+
return;
50+
}
4951
RefreshableOidcSecurityContext securityContext = (RefreshableOidcSecurityContext) session.getAttachment(OidcSecurityContext.class.getName());
50-
if (securityContext == null) return;
52+
if (securityContext == null) {
53+
return;
54+
}
5155

5256
// just in case session got serialized
5357
if (securityContext.getOidcClientConfiguration() == null) {
5458
securityContext.setCurrentRequestInfo(httpFacade.getOidcClientConfiguration(), this);
5559
}
5660

57-
if (securityContext.isActive() && ! securityContext.getOidcClientConfiguration().isAlwaysRefreshToken()) return;
61+
if (securityContext.isActive() && ! securityContext.getOidcClientConfiguration().isAlwaysRefreshToken()) {
62+
return;
63+
}
5864

5965
// FYI: A refresh requires same scope, so same roles will be set. Otherwise, refresh will fail and token will
6066
// not be updated
6167
boolean success = securityContext.refreshToken(false);
62-
if (success && securityContext.isActive()) return;
68+
if (success && securityContext.isActive()) {
69+
return;
70+
}
6371

6472
// Refresh failed, so user is already logged out from keycloak. Cleanup and expire our session
6573
session.setAttachment(OidcSecurityContext.class.getName(), null);
@@ -132,7 +140,6 @@ public void saveAccountInfo(OidcAccount account) {
132140
}
133141
});
134142
}
135-
136143
session.setAttachment(OidcAccount.class.getName(), account);
137144
session.setAttachment(OidcSecurityContext.class.getName(), account.getOidcSecurityContext());
138145

http/oidc/src/test/java/org/wildfly/security/http/oidc/AbstractLogoutTest.java

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -77,7 +77,9 @@ public void onBefore() throws Exception {
7777
OidcBaseTest.client = new MockWebServer();
7878
OidcBaseTest.client.start(new InetSocketAddress(0).getAddress(), CLIENT_PORT);
7979
configureDispatcher();
80-
RealmRepresentation realm = KeycloakConfiguration.getRealmRepresentation(TEST_REALM, CLIENT_ID, CLIENT_SECRET, CLIENT_HOST_NAME, CLIENT_PORT, CLIENT_APP, false);
80+
RealmRepresentation realm = KeycloakConfiguration.getRealmRepresentation(
81+
TEST_REALM, CLIENT_ID, CLIENT_SECRET, CLIENT_HOST_NAME, CLIENT_PORT,
82+
CLIENT_APP, false);
8183

8284
realm.setAccessTokenLifespan(100);
8385
realm.setSsoSessionMaxLifespan(100);
@@ -161,7 +163,6 @@ public ElytronDispatcher(HttpServerAuthenticationMechanism mechanism, Dispatcher
161163
public MockResponse dispatch(RecordedRequest serverRequest) throws InterruptedException {
162164
if (beforeDispatcher != null) {
163165
MockResponse response = beforeDispatcher.dispatch(serverRequest);
164-
165166
if (response != null) {
166167
return response;
167168
}
@@ -225,7 +226,7 @@ protected void configureDispatcher(OidcClientConfiguration clientConfig, Dispatc
225226
}
226227

227228
protected void assertUserNotAuthenticated() {
228-
assertNull(getCurrentSession().getAttachment(OidcAccount.class.getName()));
229+
assertNull(getCurrentSession());
229230
}
230231

231232
protected void assertUserAuthenticated() {

http/oidc/src/test/java/org/wildfly/security/http/oidc/BackChannelLogoutTest.java

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,9 +55,10 @@ private static String rewriteHost(String redirectUri) {
5555
}
5656

5757
@Test
58-
public void testRPInitiatedLogout() throws Exception {
58+
public void testBackChannelLogout() throws Exception {
5959
URI requestUri = new URI(getClientUrl());
6060
WebClient webClient = getWebClient();
61+
6162
webClient.getPage(getClientUrl());
6263
TestingHttpServerResponse response = getCurrentResponse();
6364
assertEquals(HttpStatus.SC_MOVED_TEMPORARILY, response.getStatusCode());
@@ -73,8 +74,6 @@ public void testRPInitiatedLogout() throws Exception {
7374
// logged out after finishing the redirections during frontchannel logout
7475
assertUserAuthenticated();
7576
webClient.getPage(getClientUrl() + getClientConfig().getLogoutPath());
76-
assertUserAuthenticated();
77-
webClient.getPage(getClientUrl());
7877
assertUserNotAuthenticated();
7978
}
80-
}
79+
}

http/oidc/src/test/java/org/wildfly/security/http/oidc/FrontChannelLogoutTest.java

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -49,10 +49,9 @@ protected void doConfigureClient(ClientRepresentation client) {
4949
client.setFrontchannelLogout(true);
5050
List<String> redirectUris = client.getRedirectUris();
5151
String redirectUri = redirectUris.get(0);
52-
53-
OidcClientConfiguration ocConfig = new OidcClientConfiguration();
52+
OidcClientConfiguration config = new OidcClientConfiguration();
5453
client.getAttributes().put("frontchannel.logout.url", redirectUri
55-
+ ocConfig.getLogoutCallbackPath());
54+
+ config.getLogoutCallbackPath());
5655
}
5756

5857
@Test
@@ -101,7 +100,7 @@ public MockResponse dispatch(RecordedRequest request) {
101100
assertTrue(page.getWebResponse().getContentAsString().contains("Welcome, authenticated user"));
102101

103102
assertUserAuthenticated();
104-
HtmlPage continueLogout = webClient.getPage(getClientUrl() + "/logout");
103+
HtmlPage continueLogout = webClient.getPage(getClientUrl() + getClientConfig().getLogoutPath());
105104
page = continueLogout.getElementById("continue").click();
106105
assertUserNotAuthenticated();
107106
assertTrue(page.getWebResponse().getContentAsString().contains("you are logged out from app"));
@@ -126,4 +125,4 @@ public void testFrontChannelLogout() throws Exception {
126125
client.setDispatcher(new QueueDispatcher());
127126
}
128127
}
129-
}
128+
}

tests/base/src/test/java/org/wildfly/security/http/impl/AbstractBaseHttpTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,9 @@ public boolean resumeRequest() {
376376
}
377377

378378
public HttpScope getScope(Scope scope) {
379+
if (requestURI != null && "/clientApp/logout/callback".equals(requestURI.getPath())){
380+
return null;
381+
}
379382

380383
if (scope.equals(Scope.SSL_SESSION)) {
381384
return null;

0 commit comments

Comments
 (0)