Springsecurity 181008152249
Springsecurity 181008152249
Who am I?
Besides work…
› Enjoying a lot with my family
› Two children
Jesus Perez Franco › Doing sport
https://www.linkedin.com/in/jpefranco/ › Running, Fitness, Footboll...
› Planting vegetables
› Ecological Orchard
Application Architect › Drinking Belgium beer
› With colleagues better ;)
› Agile DevOps Enthusiast
› I have been an all-purpose Software
Engineer for over 17 years' experience.
› I worked at Gfi Spain for 12 years
› I arrived in GfiBelux in January 2018
› I’m currently working for Toyota Motors
Europe in the CAST Team
GfiBelux | 04/09/2018 3
Spring Security
Summary
I. Introduction: Spring Framework vs. Spring Boot vs. Spring Security
II. What is Spring Security?
Session 1
In-Memory Authentication
III. Spring Security Fundamentals I JDBC Authentication
IV. Spring Security Workflow LDAP Authentication
V. Spring Security Architecture UserDetailsService
VI. Spring Security Configuration AuthenticationProvider
VII. Spring Security Fundamentals II
Session 2
Spring Boot 2
Spring
Security 5 Spring Framework
Spring MVC Spring Data Etc...
GfiBeLux | 04/09/2018 5
Spring Security
import
username UserID AuthorisationID domain Java module
(Spring Data JPA)
GfiBeLux | 04/09/2018 10
Spring Security Configuration: Spring Security
Project structure
› You can use start.spring.io to generate
a basic project.
› You can create the project web+spring
Dependency
Dependency security from IDE
Database
Spring Security
provides a variety
of options for
performing
authentication.
We are going to
see the most
frequently used.
GfiBeLux | 04/09/2018 11
Spring Security
...
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception
{
› Configure the authentication
auth method
.inMemoryAuthentication()
.withUser("user").password("{noop}password")
.roles("Consultant", "Teamlead", "Hr");
}
...
be.gfi.academy.password=${database.password}
You must store encrypted credentials,
I use Spring Boot CLI to encrypt it: so would NOT allow everybody with
# spring encrypt secret --key root access to the repository to use these
1a5f8bbf59c7290ec5b99fe91e05dd02d692cc07bb1d7bd931f7b4c27679a391 credentials.
# set ENCRYPT_KEY=secret You have to provide the key via the property encrypt.key
# mvn clean install –DskiptTests=true or ENCRYPT_KEY variable environment
# cd security
To automate this process, you can add the encryption key to your
# mvn spring-boot:run deployment infrastructure like Jenkins, Bamboo, etc.
In-Memory Authentication
JDBC Authentication
LDAP Authentication - AuthenticationManagerBuilder LDAP Authentication
UserDetailsService
<dependency> AuthenticationProvider
<groupId>org.springframework.ldap</groupId> Use the configurations files, either
<artifactId>spring-ldap-core</artifactId>
</dependency> application.properties or application.yml
<dependency>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-ldap</artifactId>
</dependency>
@Autowired
private UserDetailsServiceImpl userDetailsService;
@Autowired
private PasswordEncoderImpl passwordEncoder;
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationProvider(userDetailsService);
.passwordEncoder(passwordEncoder);
}
The standard scenario uses a simple UserDetailsService where I usually store the
password in database and spring security framework performs a check on the
password. What happens when you are using a different authentication system,
and the password is not provided in your own database/data model?
GfiBeLux | 04/09/2018 19
Spring Security
@Autowired
private IUserDao userDAO; It’s defined in Domain module
@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {
if (user == null) {
throw new UsernameNotFoundException(username);
}
This User Details Service only has access to the username in order to retrieve the
full user entity – and in a large number of scenarios, this is enough.
GfiBeLux | 04/09/2018 20
Spring Security
@Override
public Collection<GrantedAuthority> getAuthorities() {
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
List<AuthorisationVO> roles = user.getRoles();
@Autowired
private AuthenticationProviderImpl authProvider;
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception {
auth
.authenticationProvider(authProvider);
}
More custom scenarios will still need to access the full Authentication request to be able to
perform the authentication process – for example when authenticating against some external,
third party service (e.g. CAS/IS - Centralized Authentication System/Identity Server, so my
system have no idea about the password) – both the username and the password from the
authentication request will be necessary.
For these more advanced scenarios we’ll need to define a custom Authentication Provider:
GfiBeLux | 04/09/2018 22
Spring Security Configuration: Spring Security
@Autowired
private IUserDao userDAO;
@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {
Summary
I. Introduction: Spring Framework vs. Spring Boot vs. Spring Security
II. What is Spring Security?
Session 1
In-Memory Authentication
III. Spring Security Fundamentals I JDBC Authentication
IV. Spring Security Workflow LDAP Authentication
V. Spring Security Architecture UserDetailsService
VI. Spring Security Configuration AuthenticationProvider
VII. Spring Security Fundamentals II
Session 2
› OAuth2
› OAuth2 is a framework that solves a problem when a user wants to access
the data using a client software like browser-based web apps, native
mobile apps or desktop apps. OAuth2 is just for authorization, client
software can be authorized to access the resources on behalf of the
end user by using an access token.
› OpenID Connect
› OpenID Connect builds on top of OAuth2 and adds authentication. OpenID
Connect adds some constraints to OAuth2 like UserInfo Endpoint, ID
Token, discovery and dynamic registration of OpenID Connect providers
and session management. JWT is the mandatory format for the token.
GfiBeLux | 04/09/2018 25
Spring Security
spring.security.oauth2.client.registration.google.client-id=277735095424......
spring.security.oauth2.client.registration.google.client-secret=XGksESFC01e58.....
<dependency> @Override
<groupId>org.springframework.security</groupId> protected void configure(HttpSecurity http) {
<artifactId>spring-security-oauth2-client</artifactId> http
<version>${spring-security-version}</version> .authorizeRequests()
</dependency> .antMatchers("/", "/index")
<dependency> .permitAll()
<groupId>org.springframework.security</groupId> .antMatchers("/user/**")
<artifactId>spring-security-oauth2-jose</artifactId> .authenticated()
<version>${spring-security-version}</version> .and()
</dependency> .oauth2Login()
.loginPage("/login");
Use the Google's OAuth 2.0 endpoints to authorize access to Google APIs. Call
Google
API
<a href="/oauth2/authorization/google">Google account</a>
Token Check
token
SSO
Frontend response Backend I
(Node)
Browser/APP Call Backend API Backend II
<token> ...
GfiBeLux | 04/09/2018 30
Spring Security
Configuration
<dependency>
<groupId>io.jsonwebtoken</groupId>
<artifactId>jjwt</artifactId>
<version>0.9.0</version>
</dependency>
@Override
protected void configure(HttpSecurity http) throws Exception {
http
.authorizeRequests()
.antMatchers(HttpMethod.POST,"/api/login")
.permitAll()
.anyRequest()
.authenticated()
.and()
// We filter the api/login requests
.addFilterBefore(new JWTLoginFilter("/api/login", authenticationManager()),
UsernamePasswordAuthenticationFilter.class)
// And filter other requests to check the presence of JWT in header
.addFilterBefore(new JWTAuthenticationFilter(),
UsernamePasswordAuthenticationFilter.class);
GfiBeLux | 04/09/2018 32
JSON Web Token (JWT) with REST API Spring Security
JWTLoginFilter
public class JWTLoginFilter extends AbstractAuthenticationProcessingFilter{
@Override
public Authentication attemptAuthentication(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse)
throws AuthenticationException, IOException, ServletException {
AccountCredentials credentials = new ObjectMapper().readValue(httpServletRequest.getInputStream(),AccountCredentials.class);
UsernamePasswordAuthenticationToken token = new UsernamePasswordAuthenticationToken(credentials.getUsername(),
credentials.getPassword());
return getAuthenticationManager().authenticate(token);
}
@Override
protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response, FilterChain chain, Authentication
authentication)
throws IOException, ServletException{
String name = authentication.getName();
tokenAuthenticationService.addAuthentication(response,name);
}
}
GfiBeLux | 04/09/2018 33
JSON Web Token (JWT) with REST API Spring Security
TokenAuthenticationService
public class TokenAuthenticationService {
AuthenticatedUserImpl
public class AuthenticatedUserImpl implements Authentication {
@Autowired
private IUserDao userDAO;
AuthenticatedUserImpl(String name){
this.name = name;
}
@Override
public Collection<GrantedAuthority> getAuthorities() {
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
return grantedAuthorities;
}
....
....
GfiBeLux | 04/09/2018 35
JSON Web Token (JWT) with REST API Spring Security
@Override
public void doFilter(ServletRequest request, ServletResponse response, FilterChain filterChain) throws IOException, ServletException {
Authentication authentication = new TokenAuthenticationService().getAuthentication((HttpServletRequest)request);
SecurityContextHolder.getContext().setAuthentication(authentication);
filterChain.doFilter(request,response);
}
}
Registered office
Square de Meeûs 28/40 – 1000 Brussels
Tel: +32(0)16381111
Fax: +32(0)16381100
[email protected]