Merge pull request #6096 from davidfestal/che-multiuser

Changes required to have the `che-multiuser` run on Minishift
6.19.x
David Festal 2017-09-07 13:33:43 +02:00 committed by GitHub
commit 9bace3cbd7
7 changed files with 88 additions and 64 deletions

View File

@ -8,9 +8,9 @@
+
+function buildKeycloakConfig(keycloakSettings) {
+ return {
+ url: keycloakSettings['che.keycloak.auth-server-url'],
+ url: keycloakSettings['che.keycloak.auth_server_url'],
+ realm: keycloakSettings['che.keycloak.realm'],
+ clientId: keycloakSettings['che.keycloak.client-id']
+ clientId: keycloakSettings['che.keycloak.client_id']
+ };
+}
+
@ -30,7 +30,7 @@
+ new Promise((resolve, reject) => {
+ const script = document.createElement('script');
+ script.async = true;
+ script.src = keycloakSettings['che.keycloak.auth-server-url'] + '/js/keycloak.js';
+ script.src = keycloakSettings['che.keycloak.auth_server_url'] + '/js/keycloak.js';
+ script.addEventListener('load', resolve);
+ script.addEventListener('error', () => reject('Error loading script.'));
+ script.addEventListener('abort', () => reject('Script loading aborted.'));

View File

@ -468,11 +468,11 @@ CHE_SINGLE_PORT=false
#
CHE_KEYCLOAK_OSO_ENDPOINT=NULL
CHE_KEYCLOAK_GITHUB.ENDPOINT=NULL
CHE_KEYCLOAK_AUTH-SERVER-URL=http://172.17.0.1:5050/auth
CHE_KEYCLOAK_GITHUB_ENDPOINT=NULL
CHE_KEYCLOAK_AUTH__SERVER__URL=http://172.17.0.1:5050/auth
CHE_KEYCLOAK_REALM=che
CHE_KEYCLOAK_CLIENT-ID=che-public
CHE_KEYCLOAK_CLIENT__ID=che-public
CHE_KEYCLOAK_PRIVATE_REALM=che
CHE_KEYCLOAK_PRIVATE_CLIENT-ID=che
CHE_KEYCLOAK_PRIVATE_CLIENT-SECRET=2c1b2621-d251-4701-82c4-a7dd447faa97
CHE_KEYCLOAK_PRIVATE_CLIENT__ID=che
CHE_KEYCLOAK_PRIVATE_CLIENT__SECRET=2c1b2621-d251-4701-82c4-a7dd447faa97

View File

@ -0,0 +1,35 @@
/*
* Copyright (c) 2012-2017 Red Hat, Inc.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Red Hat, Inc. - initial API and implementation
*/
package org.eclipse.che.keycloak.server;
import javax.servlet.Filter;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
/**
* Base abstract class for the Keycloak-related servlet filters.
*
* <p>In particular it defines commnon use-cases when the authentication / multi-user logic should
* be skipped
*/
public abstract class AbstractKeycloakFilter implements Filter {
protected boolean shouldSkipAuthentication(HttpServletRequest request, String token) {
return request.getScheme().startsWith("ws") || (token != null && token.startsWith("machine"));
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void destroy() {}
}

View File

@ -29,9 +29,8 @@ import java.util.Base64;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Named;
import javax.servlet.Filter;
import javax.inject.Singleton;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
@ -42,7 +41,8 @@ import org.eclipse.che.keycloak.shared.KeycloakConstants;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class KeycloakAuthenticationFilter implements Filter {
@Singleton
public class KeycloakAuthenticationFilter extends AbstractKeycloakFilter {
private static final Logger LOG = LoggerFactory.getLogger(KeycloakAuthenticationFilter.class);
@ -61,54 +61,52 @@ public class KeycloakAuthenticationFilter implements Filter {
this.tokenExtractor = tokenExtractor;
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain)
throws IOException, ServletException {
HttpServletRequest request = (HttpServletRequest) req;
final String token = tokenExtractor.getToken(request);
if (request.getScheme().startsWith("ws") || (token != null && token.startsWith("machine"))) {
if (shouldSkipAuthentication(request, token)) {
chain.doFilter(req, res);
return;
} else {
final String requestURI = request.getRequestURI();
if (token == null) {
LOG.debug("No 'Authorization' header for {}", requestURI);
send403(res);
return;
}
}
Jws<Claims> jwt;
final String requestURI = request.getRequestURI();
if (token == null) {
LOG.debug("No 'Authorization' header for {}", requestURI);
send403(res);
return;
}
Jws<Claims> jwt;
try {
jwt = Jwts.parser().setSigningKey(getJwtPublicKey(false)).parseClaimsJws(token);
LOG.debug("JWT = ", jwt);
//OK, we can trust this JWT
} catch (SignatureException
| NoSuchAlgorithmException
| InvalidKeySpecException
| IllegalArgumentException e) {
//don't trust the JWT!
LOG.error("Failed verifying the JWT token", e);
try {
jwt = Jwts.parser().setSigningKey(getJwtPublicKey(false)).parseClaimsJws(token);
LOG.debug("JWT = " + jwt.toString());
LOG.info("Retrying after updating the public key", e);
jwt = Jwts.parser().setSigningKey(getJwtPublicKey(true)).parseClaimsJws(token);
LOG.debug("JWT = ", jwt);
//OK, we can trust this JWT
} catch (SignatureException
| NoSuchAlgorithmException
| InvalidKeySpecException
| IllegalArgumentException e) {
| IllegalArgumentException ee) {
//don't trust the JWT!
LOG.error("Failed verifying the JWT token", e);
try {
LOG.info("Retrying after updating the public key", e);
jwt = Jwts.parser().setSigningKey(getJwtPublicKey(true)).parseClaimsJws(token);
LOG.debug("JWT = " + jwt.toString());
//OK, we can trust this JWT
} catch (SignatureException
| NoSuchAlgorithmException
| InvalidKeySpecException
| IllegalArgumentException ee) {
//don't trust the JWT!
LOG.error("Failed verifying the JWT token after public key update", e);
send403(res);
return;
}
LOG.error("Failed verifying the JWT token after public key update", e);
send403(res);
return;
}
request.setAttribute("token", jwt);
chain.doFilter(req, res);
}
request.setAttribute("token", jwt);
chain.doFilter(req, res);
}
private synchronized PublicKey getJwtPublicKey(boolean reset)
@ -146,7 +144,4 @@ public class KeycloakAuthenticationFilter implements Filter {
HttpServletResponse response = (HttpServletResponse) res;
response.sendError(403);
}
@Override
public void destroy() {}
}

View File

@ -18,9 +18,7 @@ import java.io.IOException;
import java.security.Principal;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.servlet.Filter;
import javax.servlet.FilterChain;
import javax.servlet.FilterConfig;
import javax.servlet.ServletException;
import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
@ -47,7 +45,7 @@ import org.eclipse.che.commons.subject.SubjectImpl;
* @author Max Shaposhnik (mshaposhnik@redhat.com)
*/
@Singleton
public class KeycloakEnvironmentInitalizationFilter implements Filter {
public class KeycloakEnvironmentInitalizationFilter extends AbstractKeycloakFilter {
private final UserManager userManager;
private final AccountManager accountManager;
@ -63,16 +61,13 @@ public class KeycloakEnvironmentInitalizationFilter implements Filter {
this.tokenExtractor = tokenExtractor;
}
@Override
public void init(FilterConfig filterConfig) throws ServletException {}
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain)
throws IOException, ServletException {
final HttpServletRequest httpRequest = (HttpServletRequest) request;
final String token = tokenExtractor.getToken(httpRequest);
if (request.getScheme().startsWith("ws") || (token != null && token.startsWith("machine"))) {
if (shouldSkipAuthentication(httpRequest, token)) {
filterChain.doFilter(request, response);
return;
}
@ -153,7 +148,4 @@ public class KeycloakEnvironmentInitalizationFilter implements Filter {
}
};
}
@Override
public void destroy() {}
}

View File

@ -20,10 +20,12 @@ public class KeycloakServletModule extends ServletModule {
protected void configureServlets() {
bind(KeycloakAuthenticationFilter.class).in(Singleton.class);
// Not contains '/websocket', /docs/ (for swagger) and not ends with '/ws' or '/eventbus' or '/settings/'
filterRegex("^(?!.*(/websocket/?|/docs/))(?!.*(/ws/?|/eventbus/?|/settings/?)$).*")
// Not contains '/websocket', /docs/ (for swagger) and not ends with '/ws' or '/eventbus' or '/settings/' or '/api/system/state' or '/api/stack/[^/]+/icon/'
filterRegex(
"^(?!.*(/websocket/?|/docs/))(?!.*(/ws/?|/eventbus/?|/settings/?|/api/system/state/?|/api/stack/[^/]+/icon/?)$).*")
.through(KeycloakAuthenticationFilter.class);
filterRegex("^(?!.*(/websocket/?|/docs/))(?!.*(/ws/?|/eventbus/?|/settings/?)$).*")
filterRegex(
"^(?!.*(/websocket/?|/docs/))(?!.*(/ws/?|/eventbus/?|/settings/?|/api/system/state/?|/api/stack/[^/]+/icon/?)$).*")
.through(KeycloakEnvironmentInitalizationFilter.class);
}
}

View File

@ -17,18 +17,18 @@ public class KeycloakConstants {
private static final String PRIVATE_PREFIX = "private.";
private static final String KEYCLOAK_SETTINGS_ENDPOINT_PATH = "/keycloak/settings";
public static final String AUTH_SERVER_URL_SETTING = KEYCLOAK_SETTING_PREFIX + "auth-server-url";
public static final String AUTH_SERVER_URL_SETTING = KEYCLOAK_SETTING_PREFIX + "auth_server_url";
public static final String REALM_SETTING = KEYCLOAK_SETTING_PREFIX + "realm";
public static final String CLIENT_ID_SETTING = KEYCLOAK_SETTING_PREFIX + "client-id";
public static final String CLIENT_ID_SETTING = KEYCLOAK_SETTING_PREFIX + "client_id";
public static final String REWRITE_RULE_SETTING =
KEYCLOAK_SETTING_PREFIX + "redirect-rewrite-rules";
KEYCLOAK_SETTING_PREFIX + "redirect_rewrite_rules";
public static final String PRIVATE_REALM_SETTING =
KEYCLOAK_SETTING_PREFIX + PRIVATE_PREFIX + "realm";
public static final String PRIVATE_CLIENT_ID_SETTING =
KEYCLOAK_SETTING_PREFIX + PRIVATE_PREFIX + "client-id";
KEYCLOAK_SETTING_PREFIX + PRIVATE_PREFIX + "client_id";
public static final String PRIVATE_CLIENT_SECRET_SETTING =
KEYCLOAK_SETTING_PREFIX + PRIVATE_PREFIX + "client-secret";
KEYCLOAK_SETTING_PREFIX + PRIVATE_PREFIX + "client_secret";
public static final String OSO_ENDPOINT_SETTING = KEYCLOAK_SETTING_PREFIX + "oso.endpoint";
public static final String PROFILE_ENDPOINT_SETTING =