Repository: cxf-fediz Updated Branches: refs/heads/master cc6a5e0ec -> 0154f6606
Prototyping the initial back channel logout code Project: http://git-wip-us.apache.org/repos/asf/cxf-fediz/repo Commit: http://git-wip-us.apache.org/repos/asf/cxf-fediz/commit/0154f660 Tree: http://git-wip-us.apache.org/repos/asf/cxf-fediz/tree/0154f660 Diff: http://git-wip-us.apache.org/repos/asf/cxf-fediz/diff/0154f660 Branch: refs/heads/master Commit: 0154f6606224661a372df5dd92ed80e2f691ce91 Parents: cc6a5e0 Author: Sergey Beryozkin <sberyoz...@gmail.com> Authored: Fri Jun 2 13:22:45 2017 +0100 Committer: Sergey Beryozkin <sberyoz...@gmail.com> Committed: Fri Jun 2 13:22:45 2017 +0100 ---------------------------------------------------------------------- .../oidc/logout/BackChannelLogoutHandler.java | 96 ++++++++++++++++++++ .../service/oidc/logout/LogoutService.java | 15 ++- 2 files changed, 109 insertions(+), 2 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/0154f660/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/logout/BackChannelLogoutHandler.java ---------------------------------------------------------------------- diff --git a/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/logout/BackChannelLogoutHandler.java b/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/logout/BackChannelLogoutHandler.java new file mode 100644 index 0000000..2c01b71 --- /dev/null +++ b/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/logout/BackChannelLogoutHandler.java @@ -0,0 +1,96 @@ +/** + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.cxf.fediz.service.oidc.logout; + +import java.util.Collections; +import java.util.List; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import javax.ws.rs.core.Form; + +import org.apache.cxf.common.util.Base64UrlUtility; +import org.apache.cxf.jaxrs.client.WebClient; +import org.apache.cxf.rs.security.jose.jwt.JoseJwtProducer; +import org.apache.cxf.rs.security.jose.jwt.JwtClaims; +import org.apache.cxf.rs.security.jose.jwt.JwtToken; +import org.apache.cxf.rs.security.oauth2.common.Client; +import org.apache.cxf.rs.security.oauth2.common.ServerAccessToken; +import org.apache.cxf.rs.security.oauth2.provider.OAuthDataProvider; +import org.apache.cxf.rs.security.oidc.idp.OidcUserSubject; +import org.apache.cxf.rt.security.crypto.CryptoUtils; + +public class BackChannelLogoutHandler extends JoseJwtProducer { + private static final String BACK_CHANNEL_LOGOUT_URI = "backchannel_logout_uri"; + private static final String LOGOUT_TOKEN = "logout_token"; + private static final String BACK_CHANNEL_LOGOUT_EVENT = + "http://schemas.openid.net/event/backchannel-logout"; + private ExecutorService executorService = Executors.newCachedThreadPool(); + private OAuthDataProvider dataProvider; + + public void handleLogout(Client client, OidcUserSubject subject) { + // At the moment the only to find out which RPs a given User is logged in is + // to check the access tokens - it can not offer a complete solution, for ex + // in cases when ATs have expired or been revoked or Implicit id_token flow is used. + // Most likely a 'visited sites' cookie as suggested by the spec will need to be used. + List<ServerAccessToken> accessTokens = dataProvider.getAccessTokens(client, subject); + for (ServerAccessToken at : accessTokens) { + if (client.getClientId().equals(at.getClient().getClientId())) { + continue; + } + String uri = client.getProperties().get(BACK_CHANNEL_LOGOUT_URI); + if (uri != null) { + submitBackChannelLogoutRequest(client, subject, uri); + } + } + + } + + private void submitBackChannelLogoutRequest(Client client, OidcUserSubject subject, String uri) { + // Application context is expected to contain HttpConduit HTTPS configuration + final WebClient wc = WebClient.create(uri); + + JwtClaims claims = new JwtClaims(); + claims.setIssuer(subject.getIdToken().getIssuer()); + claims.setSubject(subject.getIdToken().getSubject()); + claims.setAudience(client.getClientId()); + claims.setIssuedAt(System.currentTimeMillis() / 1000); + claims.setTokenId(Base64UrlUtility.encode(CryptoUtils.generateSecureRandomBytes(16))); + claims.setProperty("events", + Collections.singletonMap(BACK_CHANNEL_LOGOUT_EVENT, Collections.emptyMap())); + final String logoutToken = super.processJwt(new JwtToken(claims)); + executorService.submit(new Runnable() { + + @Override + public void run() { + wc.form(new Form().param(LOGOUT_TOKEN, logoutToken)); + } + + }); + + } + + public void setDataProvider(OAuthDataProvider dataProvider) { + this.dataProvider = dataProvider; + } + + public void close() { + executorService.shutdownNow(); + } +} http://git-wip-us.apache.org/repos/asf/cxf-fediz/blob/0154f660/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/logout/LogoutService.java ---------------------------------------------------------------------- diff --git a/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/logout/LogoutService.java b/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/logout/LogoutService.java index 20ad51f..2a67192 100644 --- a/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/logout/LogoutService.java +++ b/services/oidc/src/main/java/org/apache/cxf/fediz/service/oidc/logout/LogoutService.java @@ -56,7 +56,7 @@ public class LogoutService extends JoseJwtConsumer { private String relativeIdpLogoutUri; private OAuthDataProvider dataProvider; private FedizSubjectCreator subjectCreator = new FedizSubjectCreator(); - + private BackChannelLogoutHandler backChannelLogoutHandler; private List<LogoutHandler> logoutHandlers; @POST @@ -74,7 +74,9 @@ public class LogoutService extends JoseJwtConsumer { OidcUserSubject subject = subjectCreator.createUserSubject(mc, params); Client client = getClient(params, idTokenHint); - + if (backChannelLogoutHandler != null) { + backChannelLogoutHandler.handleLogout(client, subject); + } if (logoutHandlers != null) { for (LogoutHandler handler : logoutHandlers) { @@ -171,4 +173,13 @@ public class LogoutService extends JoseJwtConsumer { public void setSubjectCreator(FedizSubjectCreator subjectCreator) { this.subjectCreator = subjectCreator; } + public void setBackChannelLogoutHandler(BackChannelLogoutHandler handler) { + this.backChannelLogoutHandler = handler; + } + + public void close() { + if (backChannelLogoutHandler != null) { + backChannelLogoutHandler.close(); + } + } }