You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cxf.apache.org by se...@apache.org on 2017/06/02 12:22:59 UTC

cxf-fediz git commit: Prototyping the initial back channel logout code

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 <sb...@gmail.com>
Authored: Fri Jun 2 13:22:45 2017 +0100
Committer: Sergey Beryozkin <sb...@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();
+        }
+    }
 }