Use user from keycloak

6.19.x
Max Shaposhnik 2017-06-21 17:03:57 +03:00
parent 5b54b45aa2
commit 0ebf0e8aaa
18 changed files with 250 additions and 27 deletions

View File

@ -35,7 +35,6 @@ import org.eclipse.che.api.factory.server.FactoryCreateValidator;
import org.eclipse.che.api.factory.server.FactoryEditValidator;
import org.eclipse.che.api.factory.server.FactoryParametersResolver;
import org.eclipse.che.api.machine.shared.Constants;
import org.eclipse.che.api.user.server.TokenValidator;
import org.eclipse.che.api.workspace.server.WorkspaceConfigMessageBodyAdapter;
import org.eclipse.che.api.workspace.server.WorkspaceMessageBodyAdapter;
import org.eclipse.che.api.workspace.server.stack.StackMessageBodyAdapter;
@ -86,8 +85,6 @@ public class WsMasterModule extends AbstractModule {
bind(org.eclipse.che.api.user.server.CheUserCreator.class);
bind(TokenValidator.class).to(org.eclipse.che.api.local.DummyTokenValidator.class);
bind(org.eclipse.che.api.core.rest.ApiInfoService.class);
bind(org.eclipse.che.api.project.server.template.ProjectTemplateDescriptionLoader.class).asEagerSingleton();
bind(org.eclipse.che.api.project.server.template.ProjectTemplateRegistry.class);

View File

@ -48,7 +48,6 @@ public class WsMasterServletModule extends ServletModule {
filter("/*").through(CorsFilter.class, corsFilterParams);
filter("/api/*").through(org.eclipse.che.api.local.filters.EnvironmentInitializationFilter.class);
serveRegex("^/api((?!(/(ws|eventbus)($|/.*)))/.*)").with(GuiceEverrestServlet.class);
install(new org.eclipse.che.swagger.deploy.BasicSwaggerConfigurationModule());
}

View File

@ -7,8 +7,8 @@
+ <script type="text/javascript" language="javascript" src="/_app/keycloak/keycloak.js"></script>
+ <script>
+ window.keycloak = Keycloak({
+ url: 'http://172.19.20.18:5050/auth',
+ realm: 'Che',
+ url: 'http://172.17.0.1:5050/auth',
+ realm: 'che',
+ clientId: 'che-public',
+ });
+ window.keycloak.init({ onLoad: 'check-sso', checkLoginIframe: false, }).success(function(authenticated) {
@ -30,4 +30,4 @@
+ </script>
<script type="text/javascript" language="javascript" src="/_app/browserNotSupported.js"></script>
<script type="text/javascript" language="javascript" async="true" src="/_app/_app.nocache.js"></script>
</head>
</head>

View File

@ -1,7 +1,7 @@
{
"realm" : "Che",
"realm" : "che",
"resource" : "che-public",
"auth-server-url" : "http://172.19.20.18:5050/auth",
"auth-server-url" : "http://172.17.0.1:5050/auth",
"ssl-required" : "external",
"enable-cors" : true,
"bearer-only" : false,

View File

@ -80,15 +80,15 @@
<packagingExcludes>WEB-INF/lib/*gwt*.jar,
WEB-INF/lib/gin-*.jar,
WEB-INF/lib/jsr305*.jar</packagingExcludes>
<webResources>
<resource>
<directory>${basedir}/src/main/webapp/WEB-INF</directory>
<targetPath>WEB-INF</targetPath>
<includes>
<include>**/*</include>
</includes>
</resource>
</webResources>
<webResources>
<resource>
<directory>${basedir}/src/main/webapp/WEB-INF</directory>
<targetPath>WEB-INF</targetPath>
<includes>
<include>**/*</include>
</includes>
</resource>
</webResources>
</configuration>
</plugin>
</plugins>

View File

@ -1,7 +1,7 @@
{
"realm" : "Che",
"realm" : "che",
"resource" : "che-public",
"auth-server-url" : "http://172.19.20.18:5050/auth",
"auth-server-url" : "http://172.17.0.1:5050/auth",
"ssl-required" : "external",
"enable-cors" : true,
"bearer-only" : true,

View File

@ -80,6 +80,9 @@
</includes>
</resource>
</webResources>
<packagingExcludes>
WEB-INF/lib/wsmaster-local*.jar,
</packagingExcludes>
</configuration>
</plugin>
</plugins>

View File

@ -1,9 +1,9 @@
{
"realm": "Che",
"auth-server-url": "http://172.19.20.18:5050/auth",
"realm": "che",
"auth-server-url": "http://172.17.0.1:5050/auth",
"ssl-required": "external",
"resource": "che",
"credentials": {
"secret": "f5967907-9a29-4713-971a-9776b830caa2"
"secret": "7be16729-d151-46d4-97cd-5e6d5205b567"
}
}
}

View File

@ -8,8 +8,8 @@
+
+
+let keycloakConfig = {
+ "url": "http://172.19.20.18:5050/auth",
+ "realm": "Che",
+ "url": "http://172.17.0.1:5050/auth",
+ "realm": "che",
+ "clientId": "che-public",
+};

View File

@ -42,10 +42,22 @@
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-core</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-model</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-user</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-inject</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-servlet-filter-adapter</artifactId>

View File

@ -0,0 +1,109 @@
/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* 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:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.keycloak.server;
import org.eclipse.che.api.core.ConflictException;
import org.eclipse.che.api.core.NotFoundException;
import org.eclipse.che.api.core.ServerException;
import org.eclipse.che.api.core.model.user.User;
import org.eclipse.che.api.user.server.UserManager;
import org.eclipse.che.api.user.server.model.impl.UserImpl;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.subject.Subject;
import org.eclipse.che.commons.subject.SubjectImpl;
import org.keycloak.KeycloakSecurityContext;
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;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletRequestWrapper;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.security.Principal;
import static java.util.Collections.emptyList;
/**
* @author Max Shaposhnik (mshaposhnik@redhat.com)
*/
@Singleton
public class KeycloakEnvironmentInitalizationFilter implements Filter {
@Inject
private UserManager userManager;
@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 HttpSession session = httpRequest.getSession();
final KeycloakSecurityContext context = (KeycloakSecurityContext)session.getAttribute(KeycloakSecurityContext.class.getName());
User user;
try {
user = userManager.getById(context.getIdToken().getSubject());
} catch (NotFoundException ex) {
try {
final UserImpl cheUser = new UserImpl(context.getIdToken().getSubject(),
context.getIdToken().getEmail(),
context.getIdToken().getPreferredUsername(),
"secret",
emptyList());
user = userManager.create(cheUser, false);
} catch (ServerException | ConflictException e) {
throw new ServletException("Unable to create new user");
}
} catch (ServerException e) {
throw new ServletException("Unable to get user");
}
final Subject subject =
new SubjectImpl(user.getName(), user.getId(), context.getTokenString(), false);
session.setAttribute("codenvy_user", subject);
final EnvironmentContext environmentContext = EnvironmentContext.getCurrent();
try {
environmentContext.setSubject(subject);
filterChain.doFilter(addUserInRequest(httpRequest, subject), response);
} finally {
EnvironmentContext.reset();
}
}
private HttpServletRequest addUserInRequest(final HttpServletRequest httpRequest, final Subject subject) {
return new HttpServletRequestWrapper(httpRequest) {
@Override
public String getRemoteUser() {
return subject.getUserName();
}
@Override
public Principal getUserPrincipal() {
return subject::getUserName;
}
};
}
@Override
public void destroy() {
}
}

View File

@ -0,0 +1,29 @@
/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* 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:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.keycloak.server;
import org.eclipse.che.api.core.ConflictException;
import org.eclipse.che.api.core.model.user.User;
import org.eclipse.che.api.user.server.TokenValidator;
import org.eclipse.che.api.user.server.model.impl.UserImpl;
import org.eclipse.che.commons.env.EnvironmentContext;
import org.eclipse.che.commons.subject.Subject;
/**
* @author Max Shaposhnik (mshaposhnik@redhat.com)
*/
public class KeycloakTokenValidator implements TokenValidator {
@Override
public User validateToken(String token) throws ConflictException {
final Subject subject = EnvironmentContext.getCurrent().getSubject();
return new UserImpl(subject.getUserId(), "", subject.getUserName());
}
}

View File

@ -13,7 +13,9 @@ package org.eclipse.che.keycloak.server.deploy;
import com.google.inject.AbstractModule;
import org.eclipse.che.api.core.rest.HttpJsonRequestFactory;
import org.eclipse.che.api.user.server.TokenValidator;
import org.eclipse.che.inject.DynaModule;
import org.eclipse.che.keycloak.server.KeycloakTokenValidator;
@DynaModule
@ -21,6 +23,6 @@ public class KeycloakModule extends AbstractModule {
@Override
protected void configure() {
bind(HttpJsonRequestFactory.class).to(org.eclipse.che.keycloak.server.KeycloakHttpJsonRequestFactory.class);
bind(TokenValidator.class).to(KeycloakTokenValidator.class);
}
}

View File

@ -14,6 +14,7 @@ import com.google.inject.servlet.ServletModule;
import org.eclipse.che.inject.DynaModule;
import org.eclipse.che.keycloak.server.KeycloakAuthenticationFilter;
import org.eclipse.che.keycloak.server.KeycloakEnvironmentInitalizationFilter;
import javax.inject.Singleton;
@ -24,5 +25,6 @@ public class KeycloakServletModule extends ServletModule {
protected void configureServlets() {
bind(KeycloakAuthenticationFilter.class).in(Singleton.class);
filter("/*").through(KeycloakAuthenticationFilter.class);
filter("/*").through(KeycloakEnvironmentInitalizationFilter.class);
}
}

View File

@ -1174,6 +1174,11 @@
<artifactId>che-sample-plugin-wizard-shared</artifactId>
<version>${che.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-core</artifactId>
<version>${org.keycloak.version}</version>
</dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-servlet-filter-adapter</artifactId>

View File

@ -24,6 +24,14 @@
<findbugs.failonerror>false</findbugs.failonerror>
</properties>
<dependencies>
<dependency>
<groupId>com.google.inject</groupId>
<artifactId>guice</artifactId>
</dependency>
<dependency>
<groupId>com.google.inject.extensions</groupId>
<artifactId>guice-servlet</artifactId>
</dependency>
<dependency>
<groupId>javax.inject</groupId>
<artifactId>javax.inject</artifactId>
@ -40,6 +48,10 @@
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-api-user</artifactId>
</dependency>
<dependency>
<groupId>org.eclipse.che.core</groupId>
<artifactId>che-core-commons-inject</artifactId>
</dependency>
<dependency>
<groupId>javax.servlet</groupId>
<artifactId>javax.servlet-api</artifactId>

View File

@ -0,0 +1,27 @@
/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* 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:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.api.local;
import com.google.inject.AbstractModule;
import org.eclipse.che.api.user.server.TokenValidator;
import org.eclipse.che.inject.DynaModule;
/**
* @author Max Shaposhnik (mshaposhnik@redhat.com)
*/
@DynaModule
public class LocalModule extends AbstractModule {
@Override
protected void configure() {
bind(TokenValidator.class).to(org.eclipse.che.api.local.DummyTokenValidator.class);
}
}

View File

@ -0,0 +1,26 @@
/*******************************************************************************
* Copyright (c) 2012-2017 Codenvy, S.A.
* 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:
* Codenvy, S.A. - initial API and implementation
*******************************************************************************/
package org.eclipse.che.api.local;
import com.google.inject.servlet.ServletModule;
import org.eclipse.che.inject.DynaModule;
/**
* @author Max Shaposhnik (mshaposhnik@redhat.com)
*/
@DynaModule
public class LocalServletModule extends ServletModule {
@Override
protected void configureServlets() {
filter("/api/*").through(org.eclipse.che.api.local.filters.EnvironmentInitializationFilter.class);
}
}