Skip to content
Snippets Groups Projects
Commit 2b708492 authored by jerrypan44's avatar jerrypan44
Browse files

WIP committed working features roles and keycloak integration

parent 0f2f8bf0
No related branches found
No related tags found
2 merge requests!7Features/keycloak integration,!6Features/keycloak integration
...@@ -30,11 +30,11 @@ hbp: ...@@ -30,11 +30,11 @@ hbp:
clientSecret: {{ .Env.CLIENT_SECRET }} clientSecret: {{ .Env.CLIENT_SECRET }}
accessTokenUri: {{ default .Env.TOKEN_URI "https://services.humanbrainproject.eu/oidc/token" }} accessTokenUri: {{ default .Env.TOKEN_URI "https://services.humanbrainproject.eu/oidc/token" }}
userAuthorizationUri: {{ default .Env.AUTH_URI "https://services.humanbrainproject.eu/oidc/authorize" }} userAuthorizationUri: {{ default .Env.AUTH_URI "https://services.humanbrainproject.eu/oidc/authorize" }}
tokenName: oauth_token tokenName: access_token
authenticationScheme: query authenticationScheme: query
clientAuthenticationScheme: form clientAuthenticationScheme: form
useCurrentUri: false useCurrentUri: false
preEstablishedRedirectUri: {{ default .Env.FRONTEND_LOGIN_URL "http://frontend/services/login/hbp" }} preEstablishedRedirectUri: {{ default .Env.FRONTEND_LOGIN_URL "http://localhost:8080/services/login/hbp" }}
resource: resource:
userInfoUri: {{ default .Env.USER_INFO_URI "https://services.humanbrainproject.eu/oidc/userinfo" }} userInfoUri: {{ default .Env.USER_INFO_URI "https://services.humanbrainproject.eu/oidc/userinfo" }}
revokeTokenUri: {{ default .Env.REVOKE_TOKEN_URI "https://services.humanbrainproject.eu/oidc/slo" }} revokeTokenUri: {{ default .Env.REVOKE_TOKEN_URI "https://services.humanbrainproject.eu/oidc/slo" }}
...@@ -52,6 +52,7 @@ logging: ...@@ -52,6 +52,7 @@ logging:
root: {{ default .Env.LOG_LEVEL "INFO" }} root: {{ default .Env.LOG_LEVEL "INFO" }}
org: org:
springframework: springframework:
security: DEBUG
web: {{ default .Env.LOGGING_LEVEL_WEB "WARN" }} web: {{ default .Env.LOGGING_LEVEL_WEB "WARN" }}
web.servlet.handler.BeanNameUrlHandlerMapping: WARN web.servlet.handler.BeanNameUrlHandlerMapping: WARN
hibernate: {{ default .Env.LOGGING_LEVEL_HIBERNATE "WARN" }} hibernate: {{ default .Env.LOGGING_LEVEL_HIBERNATE "WARN" }}
......
...@@ -255,12 +255,6 @@ ...@@ -255,12 +255,6 @@
<artifactId>java-jwt</artifactId> <artifactId>java-jwt</artifactId>
<version>3.8.3</version> <version>3.8.3</version>
</dependency> </dependency>
<dependency>
<groupId>org.keycloak</groupId>
<artifactId>keycloak-spring-boot-starter</artifactId>
</dependency>
</dependencies> </dependencies>
<build> <build>
......
package eu.hbp.mip.configuration;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import org.keycloak.KeycloakSecurityContext;
public class KeycloakConfiguration {
@Autowired
private HttpServletRequest request;
public KeycloakSecurityContext getKeycloakSecurityContext() {
return (KeycloakSecurityContext) request.getAttribute(KeycloakSecurityContext.class.getName());
}
}
\ No newline at end of file
...@@ -8,6 +8,7 @@ import org.slf4j.Logger; ...@@ -8,6 +8,7 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value; import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.security.oauth2.resource.AuthoritiesExtractor;
import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties; import org.springframework.boot.autoconfigure.security.oauth2.resource.ResourceServerProperties;
import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices; import org.springframework.boot.autoconfigure.security.oauth2.resource.UserInfoTokenServices;
import org.springframework.boot.context.embedded.FilterRegistrationBean; import org.springframework.boot.context.embedded.FilterRegistrationBean;
...@@ -34,6 +35,10 @@ import org.springframework.security.web.csrf.CsrfTokenRepository; ...@@ -34,6 +35,10 @@ import org.springframework.security.web.csrf.CsrfTokenRepository;
import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository; import org.springframework.security.web.csrf.HttpSessionCsrfTokenRepository;
import org.springframework.web.filter.OncePerRequestFilter; import org.springframework.web.filter.OncePerRequestFilter;
import org.springframework.web.util.WebUtils; import org.springframework.web.util.WebUtils;
import org.springframework.security.oauth2.client.resource.BaseOAuth2ProtectedResourceDetails;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.AuthorityUtils;
import javax.servlet.Filter; import javax.servlet.Filter;
import javax.servlet.FilterChain; import javax.servlet.FilterChain;
...@@ -42,223 +47,217 @@ import javax.servlet.http.Cookie; ...@@ -42,223 +47,217 @@ import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
import java.io.IOException; import java.io.IOException;
import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
// See https://spring.io/guides/tutorials/spring-boot-oauth2/ for reference about configuring OAuth2 login // See https://spring.io/guides/tutorials/spring-boot-oauth2/ for reference about configuring OAuth2 login
// also http://cscarioni.blogspot.ch/2013/04/pro-spring-security-and-oauth-2.html // also http://cscarioni.blogspot.ch/2013/04/pro-spring-security-and-oauth-2.html
/** @Configuration
* Configuration for security. @EnableOAuth2Client
*/ public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
@KeycloakConfiguration
public class SecurityConfiguration extends KeycloakWebSecurityConfigurerAdapter {
@Autowired
public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
auth.authenticationProvider(keycloakAuthenticationProvider());
}
/** private static final Logger LOGGER = LoggerFactory.getLogger(SecurityConfiguration.class);
* Defines the session authentication strategy.
*/
@Bean
@Override
protected SessionAuthenticationStrategy sessionAuthenticationStrategy() {
return new NullAuthenticatedSessionStrategy();
}
@Override @Autowired
protected void configure(HttpSecurity http) throws Exception private OAuth2ClientContext oauth2ClientContext;
{
super.configure(http);
http
.authorizeRequests()
.antMatchers("/user*").authenticated()
.antMatchers("/public1*").hasAuthority("public13")
.antMatchers("/public2*").hasAuthority("public2")
.antMatchers("/public3*").hasAuthority("public3")
.antMatchers("/admin*").authenticated()
.anyRequest().permitAll()
.and()
.logout()
.addLogoutHandler(keycloakLogoutHandler())//.logoutRequestMatcher(new AntPathRequestMatcher("/logout"))
.logoutUrl("/logout").permitAll()
.logoutSuccessUrl("/");
// .anyRequest().permitAll().and().logout().addLogoutHandler(new KeycloakLogoutHandler(new RestTemplate())).logoutRequestMatcher(new AntPathRequestMatcher("/logout"));
;
}
} /**
* Enable HBP collab authentication (1) or disable it (0). Default is 1
*/
@Value("#{'${hbp.authentication.enabled:1}'}")
private boolean authentication;
/**
* Absolute URL to redirect to when login is required
*/
@Value("#{'${frontend.loginUrl:/login/hbp}'}")
private String loginUrl;
/**
* Absolute URL to redirect to after successful login
*/
@Value("#{'${frontend.redirectAfterLoginUrl:http://frontend/home}'}")
private String frontendRedirectAfterLogin;
/**
* Absolute URL to redirect to after logout has occurred
*/
@Value("#{'${frontend.redirectAfterLogoutUrl:/login/hbp}'}")
private String redirectAfterLogoutUrl;
/**
* URL to revoke auth token
*/
@Value("#{'${hbp.resource.revokeTokenUri:https://services.humanbrainproject.eu/oidc/revoke}'}")
private String revokeTokenURI;
//@Configuration
//@EnableOAuth2Client
//public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
//
// private static final Logger LOGGER = LoggerFactory.getLogger(SecurityConfiguration.class);
//
// @Autowired // @Autowired
// private OAuth2ClientContext oauth2ClientContext; // private HttpServletRequest request;
//
// /** @Override
// * Enable HBP collab authentication (1) or disable it (0). Default is 1 protected void configure(HttpSecurity http) throws Exception {
// */ // @formatter:off
// @Value("#{'${hbp.authentication.enabled:1}'}") http.addFilterBefore(new CORSFilter(), ChannelProcessingFilter.class);
// private boolean authentication;
// if (authentication) {
// /** http.antMatcher("/**")
// * Absolute URL to redirect to when login is required .authorizeRequests()
// */ .antMatchers(
// @Value("#{'${frontend.loginUrl:/login/hbp}'}") "/", "/login/**", "/health/**", "/info/**", "/metrics/**", "/trace/**", "/frontend/**", "/webjars/**", "/v2/api-docs", "/swagger-ui.html", "/swagger-resources/**"
// private String loginUrl; )
// .permitAll()
// /** .antMatchers("/galaxy*","/galaxy/*").hasRole("Data Manager")
// * Absolute URL to redirect to after successful login //.anyRequest().authenticated()
// */ .anyRequest().hasRole("Researcher")
// @Value("#{'${frontend.redirectAfterLoginUrl:http://frontend/home}'}") .and().exceptionHandling().authenticationEntryPoint(new CustomLoginUrlAuthenticationEntryPoint(loginUrl))
// private String frontendRedirectAfterLogin; .and().logout().addLogoutHandler(new CustomLogoutHandler()).logoutSuccessUrl(redirectAfterLogoutUrl)
// .and().logout().permitAll()
// /** .and().csrf().ignoringAntMatchers("/logout").csrfTokenRepository(csrfTokenRepository())
// * Absolute URL to redirect to after logout has occurred .and().addFilterAfter(csrfHeaderFilter(), CsrfFilter.class)
// */ .addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class);
// @Value("#{'${frontend.redirectAfterLogoutUrl:/login/hbp}'}") }
// private String redirectAfterLogoutUrl; else {
// //keycloak
// /** //KeycloakConfiguration.getKeycloakSecurityContext();
// * URL to revoke auth token
// */
// @Value("#{'${hbp.resource.revokeTokenUri:https://services.humanbrainproject.eu/oidc/revoke}'}")
// private String revokeTokenURI;
//
//// @Autowired
//// private HttpServletRequest request;
//
// @Override
// protected void configure(HttpSecurity http) throws Exception {
// // @formatter:off
// http.addFilterBefore(new CORSFilter(), ChannelProcessingFilter.class);
//
// if (authentication) {
// http.antMatcher("/**") // http.antMatcher("/**")
// .authorizeRequests() // .authorizeRequests()
// .antMatchers( // .antMatchers("/**").permitAll().and().csrf().disable();
// "/", "/login/**", "/health/**", "/info/**", "/metrics/**", "/trace/**", "/frontend/**", "/webjars/**", "/v2/api-docs", "/swagger-ui.html", "/swagger-resources/**" }
// ).permitAll() }
// .anyRequest().authenticated()
// .and().exceptionHandling().authenticationEntryPoint(new CustomLoginUrlAuthenticationEntryPoint(loginUrl)) private Filter ssoFilter() {
// .and().logout().addLogoutHandler(new CustomLogoutHandler()).logoutSuccessUrl(redirectAfterLogoutUrl) OAuth2ClientAuthenticationProcessingFilter hbpFilter = new OAuth2ClientAuthenticationProcessingFilter("/login/hbp");
// .and().logout().permitAll() OAuth2RestTemplate hbpTemplate = new OAuth2RestTemplate(hbp(), oauth2ClientContext);
// .and().csrf().ignoringAntMatchers("/logout").csrfTokenRepository(csrfTokenRepository()) hbpFilter.setAuthenticationSuccessHandler(new SimpleUrlAuthenticationSuccessHandler(frontendRedirectAfterLogin));
// .and().addFilterAfter(csrfHeaderFilter(), CsrfFilter.class) hbpFilter.setRestTemplate(hbpTemplate);
// .addFilterBefore(ssoFilter(), BasicAuthenticationFilter.class); hbpFilter.setTokenServices(new UserInfoTokenServices(hbpResource().getUserInfoUri(), hbp().getClientId()));
// } return hbpFilter;
// else { }
// //keycloak
// //KeycloakConfiguration.getKeycloakSecurityContext(); @Bean
//// http.antMatcher("/**") public FilterRegistrationBean oauth2ClientFilterRegistration(
//// .authorizeRequests() OAuth2ClientContextFilter filter) {
//// .antMatchers("/**").permitAll().and().csrf().disable(); FilterRegistrationBean registration = new FilterRegistrationBean();
// } registration.setFilter(filter);
// } registration.setOrder(-100);
// return registration;
// private Filter ssoFilter() { }
// OAuth2ClientAuthenticationProcessingFilter hbpFilter = new OAuth2ClientAuthenticationProcessingFilter("/login/hbp");
// OAuth2RestTemplate hbpTemplate = new OAuth2RestTemplate(hbp(), oauth2ClientContext); @Bean(name="hbp")
// hbpFilter.setAuthenticationSuccessHandler(new SimpleUrlAuthenticationSuccessHandler(frontendRedirectAfterLogin)); @ConfigurationProperties("hbp.client")
// hbpFilter.setRestTemplate(hbpTemplate); public BaseOAuth2ProtectedResourceDetails hbp() {
// hbpFilter.setTokenServices(new UserInfoTokenServices(hbpResource().getUserInfoUri(), hbp().getClientId())); return new AuthorizationCodeResourceDetails();
// return hbpFilter; }
// }
// @Bean(name="hbpResource")
// @Bean @ConfigurationProperties("hbp.resource")
// public FilterRegistrationBean oauth2ClientFilterRegistration( public ResourceServerProperties hbpResource() {
// OAuth2ClientContextFilter filter) { return new ResourceServerProperties();
// FilterRegistrationBean registration = new FilterRegistrationBean(); }
// registration.setFilter(filter);
// registration.setOrder(-100); public boolean isAuthentication() {
// return registration; return authentication;
// } }
//
// @Bean(name="hbp") public String getFrontendRedirectAfterLogin() {
// @ConfigurationProperties("hbp.client") return frontendRedirectAfterLogin;
// public OAuth2ProtectedResourceDetails hbp() { }
// return new AuthorizationCodeResourceDetails();
// } private Filter csrfHeaderFilter() {
// return new OncePerRequestFilter() {
// @Bean(name="hbpResource") @Override
// @ConfigurationProperties("hbp.resource") protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
// public ResourceServerProperties hbpResource() { FilterChain filterChain) throws ServletException, IOException {
// return new ResourceServerProperties(); CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
// } if (csrf != null) {
// Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN");
// public boolean isAuthentication() { String token = csrf.getToken();
// return authentication; if (cookie == null || token != null && !token.equals(cookie.getValue())) {
// } cookie = new Cookie("XSRF-TOKEN", token);
// cookie.setPath("/");
// public String getFrontendRedirectAfterLogin() { response.addCookie(cookie);
// return frontendRedirectAfterLogin; }
// } }
// filterChain.doFilter(request, response);
// private Filter csrfHeaderFilter() { }
// return new OncePerRequestFilter() { };
// @Override }
// protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response,
// FilterChain filterChain) throws ServletException, IOException { private CsrfTokenRepository csrfTokenRepository() {
// CsrfToken csrf = (CsrfToken) request.getAttribute(CsrfToken.class.getName()); HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository();
// if (csrf != null) { repository.setHeaderName("X-XSRF-TOKEN");
// Cookie cookie = WebUtils.getCookie(request, "XSRF-TOKEN"); return repository;
// String token = csrf.getToken(); }
// if (cookie == null || token != null && !token.equals(cookie.getValue())) {
// cookie = new Cookie("XSRF-TOKEN", token); private class CustomLogoutHandler implements LogoutHandler {
// cookie.setPath("/"); @Override
// response.addCookie(cookie); public void logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) {
// }
// } // Hackish way of accessing to this information...
// filterChain.doFilter(request, response); final UserInfo userInfo = (UserInfo) httpServletRequest.getSession().getAttribute("userInfo");
// } if (userInfo != null) {
// }; userInfo.setFakeAuth(false);
// } }
//
// private CsrfTokenRepository csrfTokenRepository() { if (oauth2ClientContext == null || oauth2ClientContext.getAccessToken() == null)
// HttpSessionCsrfTokenRepository repository = new HttpSessionCsrfTokenRepository(); {
// repository.setHeaderName("X-XSRF-TOKEN"); return;
// return repository; }
// }
// String idToken = oauth2ClientContext.getAccessToken().getAdditionalInformation().get("id_token").toString();
// private class CustomLogoutHandler implements LogoutHandler {
// @Override StringBuilder query = new StringBuilder();
// public void logout(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Authentication authentication) { query.append("{");
// query.append("\"token\":");
// // Hackish way of accessing to this information... query.append("\"").append(idToken).append("\"");
// final UserInfo userInfo = (UserInfo) httpServletRequest.getSession().getAttribute("userInfo"); query.append("}");
// if (userInfo != null) {
// userInfo.setFakeAuth(false); try {
// } int responseCode = HTTPUtil.sendPost(revokeTokenURI, query.toString(), new StringBuilder());
// if (responseCode != 200)
// if (oauth2ClientContext == null || oauth2ClientContext.getAccessToken() == null) {
// { LOGGER.warn("Cannot send request to OIDC server for revocation ! ");
// return; }
// } else{
// LOGGER.info("Should be logged out");
// String idToken = oauth2ClientContext.getAccessToken().getAdditionalInformation().get("id_token").toString(); }
// } catch (IOException e) {
// StringBuilder query = new StringBuilder(); LOGGER.warn("Cannot notify logout to OIDC server !");
// query.append("{"); LOGGER.trace("Cannot notify logout", e);
// query.append("\"token\":"); }
// query.append("\"").append(idToken).append("\"");
// query.append("}"); }
// }
// try {
// int responseCode = HTTPUtil.sendPost(revokeTokenURI, query.toString(), new StringBuilder()); @Bean
// if (responseCode != 200) public AuthoritiesExtractor keycloakAuthoritiesExtractor() {
// { return new KeycloakAuthoritiesExtractor();
// LOGGER.warn("Cannot send request to OIDC server for revocation ! "); }
// }
// else{
// LOGGER.info("Should be logged out"); public class KeycloakAuthoritiesExtractor
// } implements AuthoritiesExtractor {
// } catch (IOException e) {
// LOGGER.warn("Cannot notify logout to OIDC server !"); @Override
// LOGGER.trace("Cannot notify logout", e); public List<GrantedAuthority> extractAuthorities
// } (Map<String, Object> map) {
// return AuthorityUtils
// } .commaSeparatedStringToAuthorityList(asAuthorities(map));
// } }
//}
private String asAuthorities(Map<String, Object> map) {
List<String> authorities = new ArrayList<>();
// authorities.add("BAELDUNG_USER");
List<LinkedHashMap<String, String>> authz;
authz = (List<LinkedHashMap<String, String>>) map.get("authorities");
for (LinkedHashMap<String, String> entry : authz) {
authorities.add(entry.get("authority"));
}
return String.join(",", authorities);
}
}
}
...@@ -17,6 +17,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression; ...@@ -17,6 +17,7 @@ import org.springframework.boot.autoconfigure.condition.ConditionalOnExpression;
import org.springframework.http.HttpStatus; import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity; import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*; import org.springframework.web.bind.annotation.*;
import org.springframework.security.access.prepost.PreAuthorize;
import javax.servlet.http.Cookie; import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
...@@ -102,6 +103,7 @@ public class SecurityApi { ...@@ -102,6 +103,7 @@ public class SecurityApi {
*/ */
@RequestMapping(path = "/galaxy", method = RequestMethod.GET, produces = "application/json") @RequestMapping(path = "/galaxy", method = RequestMethod.GET, produces = "application/json")
@PreAuthorize("hasRole('Data Manager')")
@ResponseStatus(value = HttpStatus.OK) @ResponseStatus(value = HttpStatus.OK)
public ResponseEntity getGalaxyConfiguration(){ public ResponseEntity getGalaxyConfiguration(){
String stringEncoded = Base64.getEncoder().encodeToString((galaxyUsername + ":" + galaxyPassword).getBytes()); String stringEncoded = Base64.getEncoder().encodeToString((galaxyUsername + ":" + galaxyPassword).getBytes());
......
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment