Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Upgrade JHipster monolith to Spring Security 5.1 OIDC Support #1

Open
wants to merge 18 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
41 changes: 11 additions & 30 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 7 additions & 4 deletions pom.xml
Expand Up @@ -299,13 +299,16 @@
<groupId>org.zalando</groupId>
<artifactId>problem-spring-web</artifactId>
</dependency>
<!-- Spring Security OAuth 2.0 -->
<dependency>
<groupId>org.springframework.security.oauth</groupId>
<artifactId>spring-security-oauth2</artifactId>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-client</artifactId>
</dependency>
<!-- The dependency below is not used, but is required by Ignite JHipster and Ionic for JHipster. -->
<!-- If you want to set up your API as a resource server, this dependency is necessary. -->
<dependency>
<groupId>org.springframework.security.oauth.boot</groupId>
<artifactId>spring-security-oauth2-autoconfigure</artifactId>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
<!-- Spring Cloud -->
<dependency>
Expand Down
101 changes: 0 additions & 101 deletions src/main/java/com/mycompany/myapp/config/OAuth2Configuration.java

This file was deleted.

71 changes: 55 additions & 16 deletions src/main/java/com/mycompany/myapp/config/SecurityConfiguration.java
@@ -1,26 +1,37 @@
package com.mycompany.myapp.config;

import com.mycompany.myapp.security.*;

import com.mycompany.myapp.security.AuthoritiesConstants;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Import;
import org.springframework.http.HttpMethod;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.builders.WebSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.oauth2.client.OAuth2ClientContext;
import org.springframework.security.oauth2.client.OAuth2RestTemplate;
import org.springframework.security.oauth2.client.resource.OAuth2ProtectedResourceDetails;
import org.springframework.boot.autoconfigure.security.oauth2.client.EnableOAuth2Sso;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.authority.mapping.GrantedAuthoritiesMapper;
import org.springframework.security.oauth2.core.oidc.OidcUserInfo;
import org.springframework.security.oauth2.core.oidc.user.OidcUserAuthority;
import org.springframework.security.web.csrf.CookieCsrfTokenRepository;
import org.springframework.security.web.csrf.CsrfFilter;
import org.springframework.security.web.savedrequest.HttpSessionRequestCache;
import org.springframework.security.web.savedrequest.RequestCache;
import org.springframework.security.web.savedrequest.SimpleSavedRequest;
import org.springframework.web.filter.CorsFilter;
import org.zalando.problem.spring.web.advice.security.SecurityProblemSupport;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import java.util.stream.Collectors;

@Configuration
@EnableOAuth2Sso
@EnableWebSecurity
@EnableGlobalMethodSecurity(prePostEnabled = true, securedEnabled = true)
@Import(SecurityProblemSupport.class)
public class SecurityConfiguration extends WebSecurityConfigurerAdapter {
Expand Down Expand Up @@ -54,7 +65,7 @@ public void configure(HttpSecurity http) throws Exception {
.and()
.addFilterBefore(corsFilter, CsrfFilter.class)
.exceptionHandling()
.authenticationEntryPoint(problemSupport)
//.authenticationEntryPoint(problemSupport)
.accessDeniedHandler(problemSupport)
.and()
.headers()
Expand All @@ -63,19 +74,47 @@ public void configure(HttpSecurity http) throws Exception {
.and()
.authorizeRequests()
.antMatchers("/api/**").authenticated()
.antMatchers("/authorize").authenticated()
.antMatchers("/management/health").permitAll()
.antMatchers("/management/info").permitAll()
.antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN);

.antMatchers("/management/**").hasAuthority(AuthoritiesConstants.ADMIN)
.and()
.oauth2Login();
}

/**
* This OAuth2RestTemplate is only used by AuthorizationHeaderUtil that is currently used by TokenRelayRequestInterceptor
*/

@Bean
public OAuth2RestTemplate oAuth2RestTemplate(OAuth2ProtectedResourceDetails oAuth2ProtectedResourceDetails,
OAuth2ClientContext oAuth2ClientContext) {
return new OAuth2RestTemplate(oAuth2ProtectedResourceDetails, oAuth2ClientContext);
@SuppressWarnings("unchecked")
public GrantedAuthoritiesMapper userAuthoritiesMapper() {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hey @mraible,

Thanks for giving this example, I love looking at your work as a point of reference.

Question for you around converting the groups claim to the authorities in the security context. Any reason for not just using a custom mapper in keycloak to map the groups/client-roles/realm-roles to a claim labelled as one of the WELL_KNOWN_SCOPE_ATTRIBUTE_NAMES[1] and letting spring do its conversion?

[1] https://github.com/spring-projects/spring-security/blob/master/oauth2/oauth2-resource-server/src/main/java/org/springframework/security/oauth2/server/resource/authentication/JwtGrantedAuthoritiesConverter.java#L40

return (authorities) -> {
Set<GrantedAuthority> mappedAuthorities = new HashSet<>();

authorities.forEach(authority -> {
OidcUserAuthority oidcUserAuthority = (OidcUserAuthority) authority;
OidcUserInfo userInfo = oidcUserAuthority.getUserInfo();
Collection<String> groups = (Collection<String>) userInfo.getClaims().get("groups");
if (groups == null) {
groups = (Collection<String>) userInfo.getClaims().get("roles");
}
mappedAuthorities.addAll(groups.stream()
.filter(group -> group.startsWith("ROLE_"))
.map(SimpleGrantedAuthority::new).collect(Collectors.toList()));
});

return mappedAuthorities;
};
}

//@Bean
public RequestCache refererRequestCache() {
return new HttpSessionRequestCache() {
@Override
public void saveRequest(HttpServletRequest request, HttpServletResponse response) {
String referrer = request.getHeader("referer");
if (referrer != null) {
request.getSession().setAttribute("SPRING_SECURITY_SAVED_REQUEST", new SimpleSavedRequest(referrer));
}
}
};
}
}