Repository: nifi
Updated Branches:
  refs/heads/master 31bb89514 -> ec7f13160


NIFI-4889: Logout not working properly with OIDC

- Redirect user agent to end session endpoint on the OIDC provider
- This closes #2830


Project: http://git-wip-us.apache.org/repos/asf/nifi/repo
Commit: http://git-wip-us.apache.org/repos/asf/nifi/commit/ec7f1316
Tree: http://git-wip-us.apache.org/repos/asf/nifi/tree/ec7f1316
Diff: http://git-wip-us.apache.org/repos/asf/nifi/diff/ec7f1316

Branch: refs/heads/master
Commit: ec7f1316021841a67303a56218eb61d5828eda2e
Parents: 31bb895
Author: Damian Czaja <[email protected]>
Authored: Mon Jul 2 13:35:03 2018 +0200
Committer: Matt Gilman <[email protected]>
Committed: Mon Jul 16 10:14:31 2018 -0400

----------------------------------------------------------------------
 .../org/apache/nifi/web/api/AccessResource.java | 44 ++++++++++++++
 .../web/security/oidc/OidcIdentityProvider.java |  7 +++
 .../nifi/web/security/oidc/OidcService.java     |  9 +++
 .../oidc/StandardOidcIdentityProvider.java      |  8 +++
 .../apache/nifi/web/filter/LogoutFilter.java    | 60 ++++++++++++++++++++
 .../nifi-web-ui/src/main/webapp/WEB-INF/web.xml | 10 ++++
 .../nf-ng-canvas-header-controller.js           |  2 +-
 .../src/main/webapp/js/nf/nf-common.js          |  3 +-
 8 files changed, 141 insertions(+), 2 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/nifi/blob/ec7f1316/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java
index c1c93a1..236e14e 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/web/api/AccessResource.java
@@ -318,6 +318,37 @@ public class AccessResource extends ApplicationResource {
     @GET
     @Consumes(MediaType.WILDCARD)
     @Produces(MediaType.WILDCARD)
+    @Path("oidc/logout")
+    @ApiOperation(
+            value = "Performs a logout in the OpenId Provider.",
+            notes = NON_GUARANTEED_ENDPOINT
+    )
+    public void oidcLogout(@Context HttpServletRequest httpServletRequest, 
@Context HttpServletResponse httpServletResponse) throws Exception {
+        if (!httpServletRequest.isSecure()) {
+            throw new IllegalStateException("User authentication/authorization 
is only supported when running over HTTPS.");
+        }
+
+        if (!oidcService.isOidcEnabled()) {
+            throw new IllegalStateException("OpenId Connect is not 
configured.");
+        }
+
+        URI endSessionEndpoint = oidcService.getEndSessionEndpoint();
+        String postLogoutRedirectUri = generateResourceUri("..", "nifi");
+
+        if (endSessionEndpoint == null) {
+            // handle the case, where the OpenID Provider does not have an end 
session endpoint
+            httpServletResponse.sendRedirect(postLogoutRedirectUri);
+        } else {
+            URI logoutUri = UriBuilder.fromUri(endSessionEndpoint)
+                .queryParam("post_logout_redirect_uri", postLogoutRedirectUri)
+                .build();
+            httpServletResponse.sendRedirect(logoutUri.toString());
+        }
+    }
+
+    @GET
+    @Consumes(MediaType.WILDCARD)
+    @Produces(MediaType.WILDCARD)
     @Path("knox/request")
     @ApiOperation(
             value = "Initiates a request to authenticate through Apache Knox.",
@@ -372,6 +403,19 @@ public class AccessResource extends ApplicationResource {
         httpServletResponse.sendRedirect(getNiFiUri());
     }
 
+    @GET
+    @Consumes(MediaType.WILDCARD)
+    @Produces(MediaType.WILDCARD)
+    @Path("knox/logout")
+    @ApiOperation(
+            value = "Performs a logout in the Apache Knox.",
+            notes = NON_GUARANTEED_ENDPOINT
+    )
+    public void knoxLogout(@Context HttpServletRequest httpServletRequest, 
@Context HttpServletResponse httpServletResponse) throws Exception {
+        String redirectPath = generateResourceUri("..", "nifi", "login");
+        httpServletResponse.sendRedirect(redirectPath.toString());
+    }
+
     /**
      * Gets the status the client's access.
      *

http://git-wip-us.apache.org/repos/asf/nifi/blob/ec7f1316/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/OidcIdentityProvider.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/OidcIdentityProvider.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/OidcIdentityProvider.java
index 4cc5ba1..f51be91 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/OidcIdentityProvider.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/OidcIdentityProvider.java
@@ -50,6 +50,13 @@ public interface OidcIdentityProvider {
     URI getAuthorizationEndpoint();
 
     /**
+     * Returns the URI for the end session endpoint.
+     *
+     * @return uri for the end session endpoint
+     */
+    URI getEndSessionEndpoint();
+
+    /**
      * Returns the scopes supported by the OIDC provider.
      *
      * @return support scopes

http://git-wip-us.apache.org/repos/asf/nifi/blob/ec7f1316/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/OidcService.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/OidcService.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/OidcService.java
index 427fbdf..4b0ec7c 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/OidcService.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/OidcService.java
@@ -90,6 +90,15 @@ public class OidcService {
     }
 
     /**
+     * Returns the OpenId Connect end session endpoint.
+     *
+     * @return the end session endpoint
+     */
+    public URI getEndSessionEndpoint() {
+        return identityProvider.getEndSessionEndpoint();
+    }
+
+    /**
      * Returns the OpenId Connect scope.
      *
      * @return scope

http://git-wip-us.apache.org/repos/asf/nifi/blob/ec7f1316/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/StandardOidcIdentityProvider.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/StandardOidcIdentityProvider.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/StandardOidcIdentityProvider.java
index 02ed1ff..b35bc07 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/StandardOidcIdentityProvider.java
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-security/src/main/java/org/apache/nifi/web/security/oidc/StandardOidcIdentityProvider.java
@@ -245,6 +245,14 @@ public class StandardOidcIdentityProvider implements 
OidcIdentityProvider {
     }
 
     @Override
+    public URI getEndSessionEndpoint() {
+        if (!isOidcEnabled()) {
+            throw new 
IllegalStateException(OPEN_ID_CONNECT_SUPPORT_IS_NOT_CONFIGURED);
+        }
+        return oidcProviderMetadata.getEndSessionEndpointURI();
+    }
+
+    @Override
     public Scope getScope() {
         if (!isOidcEnabled()) {
             throw new 
IllegalStateException(OPEN_ID_CONNECT_SUPPORT_IS_NOT_CONFIGURED);

http://git-wip-us.apache.org/repos/asf/nifi/blob/ec7f1316/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/java/org/apache/nifi/web/filter/LogoutFilter.java
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/java/org/apache/nifi/web/filter/LogoutFilter.java
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/java/org/apache/nifi/web/filter/LogoutFilter.java
new file mode 100644
index 0000000..9039612
--- /dev/null
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/java/org/apache/nifi/web/filter/LogoutFilter.java
@@ -0,0 +1,60 @@
+/*
+ * 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.nifi.web.filter;
+
+import javax.servlet.Filter;
+import javax.servlet.FilterChain;
+import javax.servlet.FilterConfig;
+import javax.servlet.ServletContext;
+import javax.servlet.ServletException;
+import javax.servlet.ServletRequest;
+import javax.servlet.ServletResponse;
+import javax.servlet.http.HttpServletResponse;
+import java.io.IOException;
+
+/**
+ * Filter for determining appropriate logout location.
+ */
+public class LogoutFilter implements Filter {
+
+    private ServletContext servletContext;
+
+    @Override
+    public void init(FilterConfig filterConfig) throws ServletException {
+        servletContext = filterConfig.getServletContext();
+    }
+
+    @Override
+    public void doFilter(ServletRequest request, ServletResponse response, 
FilterChain filterChain) throws IOException, ServletException {
+        final boolean supportsOidc = 
Boolean.parseBoolean(servletContext.getInitParameter("oidc-supported"));
+        final boolean supportsKnoxSso = 
Boolean.parseBoolean(servletContext.getInitParameter("knox-supported"));
+
+        if (supportsOidc) {
+            final ServletContext apiContext = 
servletContext.getContext("/nifi-api");
+            
apiContext.getRequestDispatcher("/access/oidc/logout").forward(request, 
response);
+        } else if (supportsKnoxSso) {
+            final ServletContext apiContext = 
servletContext.getContext("/nifi-api");
+            
apiContext.getRequestDispatcher("/access/knox/logout").forward(request, 
response);
+        } else {
+            ((HttpServletResponse) response).sendRedirect("../login");
+        }
+    }
+
+    @Override
+    public void destroy() {
+    }
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/ec7f1316/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/web.xml
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/web.xml
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/web.xml
index b758a67..3a0ce25 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/web.xml
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/WEB-INF/web.xml
@@ -136,6 +136,16 @@
         <url-pattern>/login</url-pattern>
     </filter-mapping>
 
+    <!-- logout filter -->
+    <filter>
+        <filter-name>LogoutFilter</filter-name>
+        <filter-class>org.apache.nifi.web.filter.LogoutFilter</filter-class>
+    </filter>
+    <filter-mapping>
+        <filter-name>LogoutFilter</filter-name>
+        <url-pattern>/logout</url-pattern>
+    </filter-mapping>
+
     <welcome-file-list>
         <welcome-file>canvas.jsp</welcome-file>
         <welcome-file>/WEB-INF/pages/canvas.jsp</welcome-file>

http://git-wip-us.apache.org/repos/asf/nifi/blob/ec7f1316/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-header-controller.js
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-header-controller.js
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-header-controller.js
index 2c515eb..c81ec9a 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-header-controller.js
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/canvas/controllers/nf-ng-canvas-header-controller.js
@@ -118,7 +118,7 @@
             this.logoutCtrl = {
                 logout: function () {
                     nfStorage.removeItem("jwt");
-                    window.location = '../nifi/login';
+                    window.location = '../nifi/logout';
                 }
             };
         }

http://git-wip-us.apache.org/repos/asf/nifi/blob/ec7f1316/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
----------------------------------------------------------------------
diff --git 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
index 6b31fe9..83fba59 100644
--- 
a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
+++ 
b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-ui/src/main/webapp/js/nf/nf-common.js
@@ -70,6 +70,7 @@
             $(e.target).parent().find('.nf-checkbox').click();
         });
 
+
         // show the loading icon when appropriate
         $(document).ajaxStart(function () {
             // show the loading indicator
@@ -88,7 +89,7 @@
         // handle logout
         $('#user-logout').on('click', function () {
             nfStorage.removeItem('jwt');
-            window.location = '../nifi/login';
+            window.location = '../nifi/logout';
         });
 
         // handle home

Reply via email to