From 888bdac220a5afd7662c11c13359a95cc11a8fd5 Mon Sep 17 00:00:00 2001 From: andrea Date: Thu, 24 Aug 2017 15:36:58 +0100 Subject: [PATCH 1/3] Implementing logout functionality for oidc --- .../components/navbar/navbar.controller.js | 20 ++++++++++++++----- 1 file changed, 15 insertions(+), 5 deletions(-) diff --git a/zeppelin-web/src/components/navbar/navbar.controller.js b/zeppelin-web/src/components/navbar/navbar.controller.js index 0ac2f18bb56..08508cc2144 100644 --- a/zeppelin-web/src/components/navbar/navbar.controller.js +++ b/zeppelin-web/src/components/navbar/navbar.controller.js @@ -90,22 +90,32 @@ function NavCtrl ($scope, $rootScope, $http, $routeParams, $location, // for firefox and safari logoutURL = logoutURL.replace('//', '//false:false@') - $http.post(logoutURL).error(function () { - // force authcBasic (if configured) to logout - $http.post(logoutURL).error(function () { + + let config = (process.env.PROD) ? {headers: { 'X-Requested-With': 'XMLHttpRequest' }} : {} + $http.post(logoutURL, config).then( + function (response) { + alert('ok response status ', response.status) + }, + function (errorResponse) { $rootScope.userName = '' $rootScope.ticket.principal = '' $rootScope.ticket.screenUsername = '' $rootScope.ticket.ticket = '' $rootScope.ticket.roles = '' + BootstrapDialog.show({ message: 'Logout Success' }) setTimeout(function () { - window.location = baseUrlSrv.getBase() + let redirect = errorResponse.headers('Location') + if (errorResponse.status === 403 && redirect !== undefined) { + // Handle page redirect + window.location.href = redirect + } else { + window.location = baseUrlSrv.getBase() + } }, 1000) }) - }) } function search (searchTerm) { From 145e5a4c70dffc815b4d9b964181255d4a17bae3 Mon Sep 17 00:00:00 2001 From: andrea Date: Fri, 25 Aug 2017 14:54:17 +0100 Subject: [PATCH 2/3] added documentation --- docs/setup/security/authentication_oidc.md | 151 ++++++++++++++++++++ docs/setup/security/shiro_authentication.md | 1 + 2 files changed, 152 insertions(+) create mode 100644 docs/setup/security/authentication_oidc.md diff --git a/docs/setup/security/authentication_oidc.md b/docs/setup/security/authentication_oidc.md new file mode 100644 index 00000000000..0cbfa69d6e4 --- /dev/null +++ b/docs/setup/security/authentication_oidc.md @@ -0,0 +1,151 @@ +--- +layout: page +title: "Authentication using Oidc" +description: "There are multiple ways to enable authentication in Apache Zeppelin. This page describes how to enable OIDC auth." +group: setup/security +--- + +{% include JB/setup %} + +# Authentication with OIDC + +
+ +[Build in authentication mechanism](./shiro_authentication.html) is recommended way for authentication. In case of you want authenticate using [OpenId Connect](https://en.wikipedia.org/wiki/OpenID_Connect), please read this document. + +## Enabling OpenId Connect + +You need to use a layer on top of Shiro to enable authentication/authorization feature with OIDC in Zeppelin. + +1. Add Pac4J and Buji to classpath + + Put on the classpath (e.g. ./zeppelin/lib)the following libraries and all the transitive dependencies: + ``` + +-io.buji:buji-pac4j:3.0.0 + | +-org.apache.shiro:shiro-web:1.4.0 + | + +-org.pac4j:pac4j-core:3.0.0-SNAPSHOT + | +-org.slf4j:slf4j-api:1.7.25 + | + +-org.pac4j:pac4j-oidc:3.0.0-SNAPSHOT + +-com.nimbusds:nimbus-jose-jwt:4.34.2 + | +-com.github.stephenc.jcip:jcip-annotations:1.0-1 + | +-net.minidev:json-smart:1.3.1 + | +-org.bouncycastle:bcpkix-jdk15on:1.55 + | +-org.bouncycastle:bcprov-jdk15on:1.55 + | + +-com.nimbusds:oauth2-oidc-sdk:5.24.2 + | +-com.github.stephenc.jcip:jcip-annotations:1.0-1 + | +-com.nimbusds:lang-tag:1.4.3 + | | +-net.minidev:json-smart:1.3.1 + | | + | +-javax.mail:mail:1.4.7 + | | +-javax.activation:activation:1.1 + | | + | +-net.minidev:json-smart:1.3.1 + | +-org.apache.commons:commons-collections4:4.1 + | +-org.apache.commons:commons-lang3:3.5 + | + +-org.pac4j:pac4j-core:3.0.0-SNAPSHOT + +-org.slf4j:slf4j-api:1.7.25 + ``` + +2. Configure your `shiro.ini` file + + In this example we will configure `shiro.ini` to perform auth through Google API endpoint, you can use a similar configuration with multiple other OIDC servers (Keycloak, Twitter, Facebook, ...) + To keep it working you need first to [create a Google API console project and client](https://developers.google.com/identity/sign-in/web/devconsole-project). + Additionally you will need to add to `Authorized redirect URI` your callback endpoint (i.e. `http://localhost:8080/api/callback`). + + Then edit your `shiro.ini` file: + + ``` + [main] + roleAdminAuthGenerator = org.pac4j.core.authorization.generator.FromAttributesAuthorizationGenerator + roleAdminAuthGenerator.roleAttributes = ROLE_ADMIN + + oidcConfig = org.pac4j.oidc.config.OidcConfiguration + oidcConfig.clientId = + oidcConfig.secret = + oidcConfig.useNonce = true + + oidcConfig.logoutUrl = https://www.google.com/accounts/Logout?continue=https://appengine.google.com/_ah/logout?continue=http://localhost:8080 + + oidcRedirectActionBuilder = org.pac4j.oidc.logout.OidcLogoutActionBuilder + oidcRedirectActionBuilder.configuration = $oidcConfig + + googleOidcClient = org.pac4j.oidc.client.GoogleOidcClient + googleOidcClient.configuration = $oidcConfig + googleOidcClient.authorizationGenerator = $roleAdminAuthGenerator + googleOidcClient.logoutActionBuilder = $oidcRedirectActionBuilder + googleOidcClient.includeClientNameInCallbackUrl = false + + clients = org.pac4j.core.client.Clients + clients.callbackUrl = http://localhost:8080/api/callback + clients.clients = $googleOidcClient + clients.defaultClient = $googleOidcClient + + requireRoleAdmin = org.pac4j.core.authorization.authorizer.RequireAnyRoleAuthorizer + requireRoleAdmin.elements = ROLE_ADMIN + + config = org.pac4j.core.config.Config + config.clients = $clients + config.authorizers = admin:$requireRoleAdmin + + pac4jRealm = io.buji.pac4j.realm.Pac4jRealm + pac4jSubjectFactory = io.buji.pac4j.subject.Pac4jSubjectFactory + securityManager.subjectFactory = $pac4jSubjectFactory + + oidcSecurityFilter = io.buji.pac4j.filter.SecurityFilter + oidcSecurityFilter.config = $config + oidcSecurityFilter.clients = googleOidcClient + + sessionManager = org.apache.shiro.web.session.mgt.DefaultWebSessionManager + + callbackFilter = io.buji.pac4j.filter.CallbackFilter + callbackFilter.defaultUrl = / + callbackFilter.config = $config + + logoutFilter = io.buji.pac4j.filter.LogoutFilter + #https://stackoverflow.com/questions/17050575/logout-link-with-return-url-oauth + logoutFilter.defaultUrl =https://www.google.com/accounts/Logout?continue=https://appengine.google.com/_ah/logout?continue=http://localhost:8080 + + logoutFilter.localLogout = true + logoutFilter.centralLogout = true + logoutFilter.config = $config + + ### If caching of user is required then uncomment below lines + #cacheManager = org.apache.shiro.cache.MemoryConstrainedCacheManager + #securityManager.cacheManager = $cacheManager + + securityManager.sessionManager = $sessionManager + # 86,400,000 milliseconds = 24 hour + securityManager.sessionManager.globalSessionTimeout = 86400000 + + [roles] + + [urls] + # This section is used for url-based security. + # You can secure interpreter, configuration and credential information by urls. Comment or uncomment the below urls that you want to hide. + # anon means the access is anonymous. + # authc means Form based Auth Security + /api/version = anon + /api/callback = callbackFilter + /api/login/logout = logoutFilter + /** = oidcSecurityFilter + ``` + + Substitute `` and `` with appropriate values. + + Restart zeppelin and enjoy your new Google login! diff --git a/docs/setup/security/shiro_authentication.md b/docs/setup/security/shiro_authentication.md index 0dcb722e316..8a1b6573633 100644 --- a/docs/setup/security/shiro_authentication.md +++ b/docs/setup/security/shiro_authentication.md @@ -254,3 +254,4 @@ anyofroles = org.apache.zeppelin.utils.AnyOfRolesAuthorizationFilter ## Other authentication methods - [HTTP Basic Authentication using NGINX](./authentication_nginx.html) +- [Authentication with OIDC](./authentication_oidc.html) From 3b8d3a7871cfc2e16c853468c12b7398872d5e2f Mon Sep 17 00:00:00 2001 From: andrea Date: Mon, 28 Aug 2017 20:18:24 +0100 Subject: [PATCH 3/3] remove alert --- zeppelin-web/src/components/navbar/navbar.controller.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/zeppelin-web/src/components/navbar/navbar.controller.js b/zeppelin-web/src/components/navbar/navbar.controller.js index 08508cc2144..c7ef601c922 100644 --- a/zeppelin-web/src/components/navbar/navbar.controller.js +++ b/zeppelin-web/src/components/navbar/navbar.controller.js @@ -93,9 +93,7 @@ function NavCtrl ($scope, $rootScope, $http, $routeParams, $location, let config = (process.env.PROD) ? {headers: { 'X-Requested-With': 'XMLHttpRequest' }} : {} $http.post(logoutURL, config).then( - function (response) { - alert('ok response status ', response.status) - }, + function (response) { }, function (errorResponse) { $rootScope.userName = '' $rootScope.ticket.principal = ''