0% found this document useful (0 votes)
580 views36 pages

Springsecurity 181008152249

The document provides a comprehensive guide on implementing Spring Security 5 in existing Spring Boot 2 applications, detailing the differences between Spring Framework, Spring Boot, and Spring Security. It covers various authentication methods including in-memory, JDBC, and LDAP, as well as configuration steps and best practices for securing web applications. Additionally, it discusses the use of BCrypt for password encoding and the integration of security features with REST APIs and OAuth2.

Uploaded by

Zakaria Zhr
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
580 views36 pages

Springsecurity 181008152249

The document provides a comprehensive guide on implementing Spring Security 5 in existing Spring Boot 2 applications, detailing the differences between Spring Framework, Spring Boot, and Spring Security. It covers various authentication methods including in-memory, JDBC, and LDAP, as well as configuration steps and best practices for securing web applications. Additionally, it discusses the use of BCrypt for password encoding and the integration of security features with REST APIs and OAuth2.

Uploaded by

Zakaria Zhr
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 36

Spring Security 5

Implementing Spring Security 5 in an existing Spring


Boot 2 application

gfi.be - gfi.lu - gfi.world


GfiBelux | 04/09/2018
2

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

VIII. Spring Security with REST API or RESTful Web Services


IX. Spring Security OAuth2
X. JSON Web Token (JWT) with REST API
XI. Practice: Impl Security
GfiBeLux | 04/09/2018 4
Spring Security
Introduction:
Spring Framework vs. Spring Boot vs. Spring Security
› Spring Framework is a Java platform that provides comprehensive infrastructure
support for developing Java applications.
› Spring Boot is based on the Spring Framework, providing auto-configuration
features to your Spring applications and is designed to get you up and running as
quickly as possible.
› Spring Security provides comprehensive security services for Java EE-
based software applications. There is a particular emphasis on supporting
projects built using the Spring Framework.

Spring Boot 2
Spring
Security 5 Spring Framework
Spring MVC Spring Data Etc...
GfiBeLux | 04/09/2018 5
Spring Security

What is Spring Security?


› Spring Security is a framework that focuses on providing both authentication
and authorization (or “access-control”) to Java web application and
SOAP/RESTful web services
› Spring Security currently supports integration with all of the
following technologies:
› HTTP basic access authentication
› LDAP system
› OpenID identity providers
› JAAS API
› CAS Server
› ESB Platform
› .....
› Your own authentication systems
› It is built on top of Spring Framework
GfiBeLux | 04/09/2018 6
Spring Security

Spring Security Fundamentals I


› Principal › AuthenticationManager
› User that performs the action › Controller in the authentication process
› Authentication › AuthenticationProvider
› Confirming truth of credentials › Interface that maps to a data store which
› Authorization stores your user data.
› Define access policy for principal › Authentication Object
› GrantedAuthority › Object is created upon authentication,
which holds the login credentials.
› Application permission granted to a
principal › UserDetails
› SecurityContext › Data object which contains the user
credentials, but also the Roles of the user.
› Hold the authentication and other security
information › UserDetailsService
› SecurityContextHolder › Collects the user credentials,
authorities(roles) and build an UserDetails
› Provides access to SecurityContext object.
GfiBeLux | 04/09/2018 7
Spring Security

Spring Security Common Workflow


Authentication object with the login credentials is created
Request Login
Request REST API
Controller in the process that it
just delegates to a collection of
AuthenticationProvider
instances.

Call an object that implements


the UserDetailsService interface,
which it looks up the user data
Front
and returns
End
a UserDetails object.

Will check that the password


matches the password the user
entered.
Back End
GfiBeLux | 04/09/2018 8
Spring Security

Spring Security Architecture

Spring security has a


series/chain of filters
(HTTP Basic, OAuth2, JWT) Authentication object
GfiBeLux | 04/09/2018 9
Spring Security

Spring Security Configuration


› Step 1. Project structure business Java module
› Step 2. Maven or Gradle dependencies (Spring Data REST)
› Step 3. Spring Security configuration
› Web Security Authentication (@EnableWebSecurity) security Java module
› In-Memory Authentication WebSecurityConfigurerAdapter (Spring Security)
› JDBC Authentication
› LDAP Authentication
› UserDetailsService
› AuthenticationProvider
Use BCrypt, as
› REST API
it’s usually the
› OAuth 2.0 SSO Authentication
best solution
› JSON Web Token (JWT)
available.
{crypt}
password
UserID AuthorisationID Authorisation

... Users Permissions Authorisation

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

Spring Security Configuration:


Maven dependencies
› pom.xml
<dependency> › Each release uses a standard triplet of
<groupId>org.springframework.security</groupId> integers: MAJOR.MINOR.PATCH
<artifactId>spring-security-web</artifactId> › All GA releases (i.e. versions ending in
<version>5.0.7.RELEASE</version> .RELEASE) are deployed to Maven
</dependency> Central.
› If you are using a SNAPSHOT version, you
<dependency> will need to have the Spring Snapshot
<groupId>org.springframework.security</groupId> repository:
<artifactId>spring-security-core</artifactId> <repositories>
<version>5.0.7.RELEASE</version> <repository>
<id>spring-snapshot</id>
</dependency> <name>Spring Snapshot Repository</name>
<url>http://repo.spring.io/snapshot</url>
<dependency> </repository>
</repositories>
<groupId>org.springframework.security</groupId>
<artifactId>spring-security-config</artifactId> › If you are using a release candidate
<version>5.0.7.RELEASE</version> or milestone version:
</dependency> <repositories>
<repository>
<id>spring-milestone</id>
You can get hold of Spring Security in several <name>Spring Milestone Repository</name>
<url>http://repo.spring.io/milestone</url>
ways. You can also use Gradle and to set the </repository>
</repositories>
build.gradle file.
GfiBeLux | 04/09/2018 12

Spring Security Configuration: Spring Security

@EnableWebSecurity and HttpSecurity


@RequestMapping("/") @EnableWebSecurity
public String root() { public class SecurityConfig extends WebSecurityConfigurerAdapter {
return "redirect:/index";
}
@Override
@RequestMapping("/index")
public String index() {
protected void configure(HttpSecurity http) throws Exception {
return "index";
} http
@RequestMapping("/user/index") .authorizeRequests()
public String userIndex() { return "user/index"; } .antMatchers("/", "/index").permitAll()
@RequestMapping(value = "/login")
.anyRequest()
public String login() { .hasAnyRole("Consultant“, “Teamlead”, “Hr”)
return "login"; .and()
}
.formLogin()
@RequestMapping(value = "/forbidden") .loginPage("/login").failureUrl("/login-error")
public String forbidden() {
return "forbidden";
.and()
} .exceptionHandling()
.accessDeniedPage("/forbidden");

...

› You have to adapt it for your own application


› Adding more configuration options:
› Form Login
› Authorize request
› Handling logout, exception, custom filters...
GfiBeLux | 04/09/2018 13
Spring Security
Spring Security Configuration: In-Memory Authentication
In-Memory Authentication - AuthenticationManagerBuilder JDBC Authentication
LDAP Authentication
UserDetailsService
AuthenticationProvider

@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception
{
› Configure the authentication
auth method
.inMemoryAuthentication()
.withUser("user").password("{noop}password")
.roles("Consultant", "Teamlead", "Hr");
}
...

› In-memory authentication is usually used in development phase


GfiBeLux | 04/09/2018 14
Spring Security

Spring Security Configuration: In-Memory Authentication


JDBC Authentication
JDBC Authentication - AuthenticationManagerBuilder LDAP Authentication
UserDetailsService
AuthenticationProvider
@Override
public void configure(AuthenticationManagerBuilder auth) throws Exception
It’s defined in Domain module
DataSource dataSource = new JpaConfiguration().dataSource();

auth It’s possible to use the default database scheme


.jdbcAuthentication() provided in spring security documentation or define the
.dataSource(dataSource) SQL query
.usersByUsernameQuery("select username, password, 'true' as enabled"
+ " from user where username=?")
.authoritiesByUsernameQuery("select username, authorisation as authority from"
+ " authorisation a, permissions p, user u"
+ " where a.AuthorisationID=p.AuthorisationID and"
+ " u.UserID=p.UserID and username=?") Create my encryption mechanisms
.passwordEncoder(passwordEncoder());
...

With JDBC-based authentication the user’s authentication and


authorization information are stored in the database.
The standard JDBC implementation of the UserDetailsService requires
tables to load the password, account status (enabled or disabled) and a list
of authorities (roles) for the user. You have to use the schema defined.
GfiBeLux | 04/09/2018 15
Spring Security

Spring Security Configuration:


JDBC Authentication – PasswordEconderImpl
@Service
public class PasswordEncoderImpl implements PasswordEncoder {
Default value is 10
@Override
public String encode(CharSequence rawPassword) {
String hashed = BCrypt.hashpw(rawPassword.toString(), BCrypt.gensalt(12));
return hashed;
}
@Override
public boolean matches(CharSequence rawPassword, String encodedPassword) {
return BCrypt.checkpw(rawPassword.toString(), encodedPassword);
}
}

Spring Security 5 recommends the use of BCrypt,


a salt that helps prevent pre-computed dictionary attacks.
Most of the other encryption mechanisms, such as the MD5PasswordEncoder
and ShaPasswordEncoder use weaker algorithms and are now deprecated.
GfiBeLux | 04/09/2018 16
Spring Security
Spring Security Configuration:
JDBC Authentication - Encrypted properties with Spring
<properties>
<database.host>localhost</database.host>
<database.name>academy</database.name> Database configuration both pom.xml
<database.port>3306</database.port> and application.properties file
<database.driver>com.mysql.jdbc.Driver</database.driver>
<database.username>root</database.username>
<database.password>{cipher}1a5f8bbf59c7290ec5b99fe91e05dd02d692cc07bb1d7bd931f7b4c27679a391
</database.password>
<database.url>jdbc:mysql://${database.host}:${database.port}/${database.name}?useSSL=false</database.url>
</properties>

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.

Spring recommends to use BCrypt BCryptPasswordEncoder, a stronger hashing


algorithm with randomly generated salt.
GfiBeLux | 04/09/2018 17

Spring Security Configuration: Spring Security

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>

public void configure(AuthenticationManagerBuilder auth) throws Exception {


auth
You must store encrypted credentials, so
.ldapAuthentication()
would NOT allow everybody with access to the
.userDnPatterns("uid={0},ou=people")
repository to use these credentials.
.groupSearchBase("ou=groups") encrypted.property={cipher}71144......
.contextSource()
.url("ldap://localhost:389/dc=springframework,dc=org")
.and()
.passwordCompare() To automate this process, you can add the
.passwordEncoder(passwordEncoder()) encryption key to your deployment
.passwordAttribute("userPassword"); infrastructure like Jenkins, Bamboo and so
} on.

With LDAP-based authentication the user’s authentication and authorization


information are stored in a directory LDAP.
GfiBeLux | 04/09/2018 18
Spring Security

Spring Security Configuration: In-Memory Authentication


JDBC Authentication
UserDetailsService I - AuthenticationManagerBuilder LDAP Authentication
UserDetailsService
AuthenticationProvider

@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

Spring Security Configuration:


UserDetailsService II - AuthenticationManagerBuilder
@Service
@Transactional
public class UserDetailsServiceImpl implements UserDetailsService {

@Autowired
private IUserDao userDAO; It’s defined in Domain module

@Override
public UserDetails loadUserByUsername(String username) throws UsernameNotFoundException {

UserVO user = userDAO.findByUsername(username);

if (user == null) {
throw new UsernameNotFoundException(username);
}

return new UserPrincipalImpl(user);


}
}

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

Spring Security Configuration: In-Memory Authentication


JDBC Authentication
UserPrincipal - AuthenticationManagerBuilder LDAP Authentication
UserDetailsService
AuthenticationProvider

public class UserPrincipalImpl implements UserDetails {


String ROLE_PREFIX = "ROLE_"; @RestController
@RequestMapping("/api") API Test
private UserVO user; public class TestService {

public UserPrincipalImpl(UserVO user) { @RequestMapping("/user-information")


this.user = user; @ResponseBody
} public Principal information(Principal principal) {
return principal;
@Override }
public String getPassword() { }
return user.getPassword();
}
http://localhost:8080/api/user-information
@Override
public String getUsername() {
return user.getUsername();
}

@Override
public Collection<GrantedAuthority> getAuthorities() {
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();
List<AuthorisationVO> roles = user.getRoles();

for(AuthorisationVO item : roles) {


grantedAuthorities.add(new SimpleGrantedAuthority(ROLE_PREFIX+item.getAuthorisation()));
}
return grantedAuthorities;
}
...
...
}
GfiBeLux | 04/09/2018 21
Spring Security

Spring Security Configuration:


Authentication Provider I - AuthenticationManagerBuilder

@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

Authentication Provider II - AuthenticationManagerBuilder


public class AuthenticationProviderImpl implements AuthenticationProvider {

@Autowired
private IUserDao userDAO;

@Override
public Authentication authenticate(Authentication authentication) throws AuthenticationException {

String name = authentication.getName();


String password = authentication.getCredentials().toString(); Use the credentials
UserVO user = userDAO.findByUsername(name);
if (user == null) { Authentication against
throw new BadCredentialsException("Authentication failed for " + name); a third-party system
}
List<GrantedAuthority> grantedAuthorities = new ArrayList<>(); like a database in our
if (new PasswordEncoderImpl().matches(password, user.getPassword())) { use case
List<AuthorisationVO> roles = user.getRoles();

for(AuthorisationVO item : roles) {


grantedAuthorities.add(new SimpleGrantedAuthority(ROLE_PREFIX+item.getAuthorisation()));
}
} Must be “ROLE_”
...
GfiBelux | 04/09/2018 23
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

VIII. Spring Security with REST API or RESTful Web Services


IX. Spring Security OAuth2
X. JSON Web Token (JWT) with REST API
XI. Practice: Impl Security
GfiBeLux | 04/09/2018 24
Spring Security

Spring Security Fundamentals II


› JWT (JSON Web Tokens)
› It is just a token format. JWT tokens are JSON encoded data structures
containing information about issuer, subject (claims), expiration time, etc.
JWT is simpler than SAML 1.1/2.0, is supported by all devices and it is
more powerful than SWT (Simple Web Token). See https://jwt.io/

› 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 with REST API


Authorization with annotations on controller I
@RestController
@RequestMapping("/api")
public class TestService {
@Secured("ROLE_Consultant")
API with access control
@RequestMapping("/user-information")
public Principal information(Principal principal) {
return principal;
}
@PreAuthorize("hasRole('ROLE_Consultant') and hasRole('ROLE_Teamlead') and hasRole('ROLE_Hr')")
@RequestMapping("/user-details")
@ResponseBody
public Object details(Authentication auth) {
return auth.getDetails();
} Frontend HTTPS Backend
@Secured("ROLE_Consultant")
@RequestMapping("/thanks") (Node) (Spring Boot)
@ResponseBody Browser/APP Basic API RESTfull
public String getThanks() { Authentication
return "{\"message\":\"Thanks!\"}";
}
}
GfiBeLux | 04/09/2018 26

Spring Security with REST API Spring Security

Authorization with annotations on controller II


Basic Authentication with REST API
(stateless). Very basic mechanism.
Should be used only in HTTPS environmen

Traditional form based authentication


Cookie/Session Based Authentication (stateful)
Even if it is base64 encoded,
it can be easily decoded

Use the Postman tool or the curl


command testing your API Rest

By default, the BasicAuthenticationEntryPoint provisioned by Spring Security returns a full


page for a 401 Unauthorized response back to the client. This HTML representation of the
error renders well in a browser, but it not well suited for other scenarios, such as a REST
API where a json representation may be preferred.
GfiBeLux | 04/09/2018 27
Spring Security with REST API Security

Authorization with annotations on controller III


public class CustomBasicAuthenticationEntryPoint extends BasicAuthenticationEntryPoint {
@Override
public void commence (HttpServletRequest request, HttpServletResponse response, AuthenticationException
authEx throws IOException {
response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
response.setHeader("WWW-Authenticate", "Basic realm=" + getRealmName());
response.setContentType(MediaType.APPLICATION_JSON_UTF8_VALUE);

PrintWriter writer = response.getWriter();


writer.println("HTTP Status 401 : " + authEx.getMessage());
}
@Override
public void afterPropertiesSet() throws Exception {
setRealmName(SecurityConfig.REALM_NAME);
super.afterPropertiesSet();
}
}

http Implementation of a custom


.authorizeRequests().anyRequest().authenticated() BasicAuthenticationEntryPoint
.and()
.httpBasic()
.authenticationEntryPoint(authenticationEntryPoint);
Spring Security OAuth2 GfiBeLux | 04/09/2018
Spring Security
28

Single Sign-On To begin, obtain OAuth 2.0 client


credentials from the Google API Console.

Google's OAuth 2.0 APIs can be used for


both authentication and authorization,
which conforms to the OpenID
Connect specification.

Copying the client-id and client-secret to


application.properties or application.yml

Setting the redirect URI


GfiBeLux | 04/09/2018 29
Spring Security

Spring Security OAuth2


Single Sign-On Application.properties file

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

JSON Web Token (JWT) with REST API

Step 1: Request /api/login Step 2: Request API REST


and get the JWT with JWT (token)
GfiBeLux | 04/09/2018 31
JSON Web Token (JWT) with REST API 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{

private TokenAuthenticationService tokenAuthenticationService;

public JWTLoginFilter(String url, AuthenticationManager authenticationManager)


{
super(new AntPathRequestMatcher(url));
setAuthenticationManager(authenticationManager);
tokenAuthenticationService = new TokenAuthenticationService();
}

@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 {

private long EXPIRATIONTIME = 1000 * 60 * 60 * 24 * 10; // 10 days


private String secret = "secret"; // Must be an environment variable into OS
private String tokenPrefix = ""; // "Bearer "
private String headerString = "Authorization";

public void addAuthentication(HttpServletResponse response, String username)


{
String JWT = Jwts.builder()
.setSubject(username)
.setExpiration(new Date(System.currentTimeMillis() + EXPIRATIONTIME))
.signWith(SignatureAlgorithm.HS512, secret).compact();
response.addHeader(headerString,tokenPrefix + JWT);
}

public Authentication getAuthentication(HttpServletRequest request)


{
String token = request.getHeader(headerString);
if(token != null)
{
String username = Jwts.parser()
.setSigningKey(secret)
.parseClaimsJws(token)
.getBody()
.getSubject();
if(username != null) // we managed to retrieve a user
{
return new AuthenticatedUserImpl(username);
}
}
return null;
}
}
GfiBeLux | 04/09/2018 34
JSON Web Token (JWT) with REST API Spring Security

AuthenticatedUserImpl
public class AuthenticatedUserImpl implements Authentication {

String ROLE_PREFIX = "ROLE_";

private boolean authenticated = true;


private String name;

@Autowired
private IUserDao userDAO;

AuthenticatedUserImpl(String name){
this.name = name;
}

@Override
public Collection<GrantedAuthority> getAuthorities() {
List<GrantedAuthority> grantedAuthorities = new ArrayList<>();

UserVO user = userDAO.findByUsername(name);


List<AuthorisationVO> roles = user.getRoles();

for(AuthorisationVO item : roles) {


grantedAuthorities.add(new SimpleGrantedAuthority(ROLE_PREFIX+item.getAuthorisation()));
}
grantedAuthorities.add(new SimpleGrantedAuthority(ROLE_PREFIX+"Consultant"));

return grantedAuthorities;
}
....
....
GfiBeLux | 04/09/2018 35
JSON Web Token (JWT) with REST API Spring Security

JWTLoginFilter and AccountCredentials


public class JWTAuthenticationFilter extends GenericFilterBean{

@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);
}
}

public class AccountCredentials {

private String username;


private String password;

String getUsername() { return username; }


String getPassword() { return password; }

public void setUsername(String _username) { this.username = _username; }


public void setPassword(String _password) { this.password = _password; }
}
Jesus Perez Franco
Application Architect
Digital Business
Gfi
[email protected]
https://www.linkedin.com/in/jpefranco/

Registered office
Square de Meeûs 28/40 – 1000 Brussels
Tel: +32(0)16381111
Fax: +32(0)16381100
[email protected]

FRANCE | SPAIN | PORTUGAL | BELGIUM | SWITSERLAND | LUXEMBURG | UNITED


gfi.be - gfi.lu - gfi.world
KINGDOM | POLAND | ROMANIA | MOROCCO | IVORY COAST|
ANGOLA | USA | MEXICO | COLOMBIA | BRASIL

You might also like