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
