Enterprise Java

Spring Boot Oauth2 Security

This post is an enhancement for my previous post which talks about how to secure your REST API using Spring security oauth2.

In case if you missed it, here is the place to grab: http://blog.rajithdelantha.com/2015/09/secure-your-rest-api-with-spring.html

Spring boot is one of the new inventions from Spring framework that makes developers’ lives easier when building large scale applications. Here is a good place to grab the concepts.

If you check my previous post related to oauth2 security then you know there is a bit of configuration that needs to be done in Spring side. But on the other hand Spring boot will do all the hard work and we just need to tell them what to do by a simple annotation.

So this post is about how to configure Spring boot project with Spring security and Oauth2. Actually we can’t really say configure because all most all configurations are done by Spring boot itself.

Step 1

For this project I’m using H2 in memory database. Because of that you don’t need to create any database and tables as the creation happens at run time. But if you want this project to use MySQL as the data source then first create the database and then create the tables.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
CREATE TABLE user
  username VARCHAR(50) NOT NULL PRIMARY KEY
  email VARCHAR(50), 
  password VARCHAR(500), 
  activated BOOLEAN DEFAULT FALSE
  activationkey VARCHAR(50) DEFAULT NULL
  resetpasswordkey VARCHAR(50) DEFAULT NULL 
 ); 
 CREATE TABLE authority ( 
  name VARCHAR(50) NOT NULL PRIMARY KEY 
 ); 
 CREATE TABLE user_authority ( 
   username VARCHAR(50) NOT NULL
   authority VARCHAR(50) NOT NULL
   FOREIGN KEY (username) REFERENCES user (username), 
   FOREIGN KEY (authority) REFERENCES authority (name), 
   UNIQUE INDEX user_authority_idx_1 (username, authority) 
 ); 
 CREATE TABLE oauth_access_token ( 
  token_id VARCHAR(256) DEFAULT NULL
  token BLOB, 
  authentication_id VARCHAR(256) DEFAULT NULL
  user_name VARCHAR(256) DEFAULT NULL
  client_id VARCHAR(256) DEFAULT NULL
  authentication BLOB, 
  refresh_token VARCHAR(256) DEFAULT NULL 
 ); 
 CREATE TABLE oauth_refresh_token ( 
  token_id VARCHAR(256) DEFAULT NULL
  token BLOB, 
  authentication BLOB 
 );
  • user table – system users
  • authority –  roles
  • user_authority – many to many table for user and role
  • oauth_access_token – to hold access_token
  • oauth_refresh_token – to hold refresh_token

Add some seed data.

1
2
3
4
5
6
7
8
9
INSERT INTO user (username,email, password, activated) VALUES ('admin', 'admin@mail.me', 'b8f57d6d6ec0a60dfe2e20182d4615b12e321cad9e2979e0b9f81e0d6eda78ad9b6dcfe53e4e22d1', true); 
 INSERT INTO user (username,email, password, activated) VALUES ('user', 'user@mail.me', 'd6dfa9ff45e03b161e7f680f35d90d5ef51d243c2a8285aa7e11247bc2c92acde0c2bb626b1fac74', true); 
 INSERT INTO user (username,email, password, activated) VALUES ('rajith', 'rajith@abc.com', 'd6dfa9ff45e03b161e7f680f35d90d5ef51d243c2a8285aa7e11247bc2c92acde0c2bb626b1fac74', true); 
 INSERT INTO authority (name) VALUES ('ROLE_USER'); 
 INSERT INTO authority (name) VALUES ('ROLE_ADMIN'); 
 INSERT INTO user_authority (username,authority) VALUES ('rajith', 'ROLE_USER'); 
 INSERT INTO user_authority (username,authority) VALUES ('user', 'ROLE_USER'); 
 INSERT INTO user_authority (username,authority) VALUES ('admin', 'ROLE_USER'); 
 INSERT INTO user_authority (username,authority) VALUES ('admin', 'ROLE_ADMIN');

Step 2

Configure WebSecurityAdapter

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
@Configuration 
 @EnableWebSecurity 
 public class SecurityConfiguration extends WebSecurityConfigurerAdapter { 
   @Autowired 
   private UserDetailsService userDetailsService; 
   @Bean 
   public PasswordEncoder passwordEncoder() { 
     return new StandardPasswordEncoder(); 
   
   @Autowired 
   public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception { 
     auth 
         .userDetailsService(userDetailsService) 
         .passwordEncoder(passwordEncoder()); 
   
   @Override 
   public void configure(WebSecurity web) throws Exception { 
     web 
         .ignoring() 
         .antMatchers("/h2console/**"
         .antMatchers("/api/register"
         .antMatchers("/api/activate"
         .antMatchers("/api/lostpassword"
         .antMatchers("/api/resetpassword"); 
   
   @Override 
   @Bean 
   public AuthenticationManager authenticationManagerBean() throws Exception { 
     return super.authenticationManagerBean(); 
   
   @EnableGlobalMethodSecurity(prePostEnabled = true, jsr250Enabled = true
   private static class GlobalSecurityConfiguration extends GlobalMethodSecurityConfiguration { 
     @Override 
     protected MethodSecurityExpressionHandler createExpressionHandler() { 
       return new OAuth2MethodSecurityExpressionHandler(); 
     
   
 }

Step 3

Configuration for Oauth2

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
@Configuration 
 public class OAuth2Configuration { 
   @Configuration 
   @EnableResourceServer 
   protected static class ResourceServerConfiguration extends ResourceServerConfigurerAdapter { 
     @Autowired 
     private CustomAuthenticationEntryPoint customAuthenticationEntryPoint; 
     @Autowired 
     private CustomLogoutSuccessHandler customLogoutSuccessHandler; 
     @Override 
     public void configure(HttpSecurity http) throws Exception { 
       http 
           .exceptionHandling() 
           .authenticationEntryPoint(customAuthenticationEntryPoint) 
           .and() 
           .logout() 
           .logoutUrl("/oauth/logout"
           .logoutSuccessHandler(customLogoutSuccessHandler) 
           .and() 
           .csrf() 
           .requireCsrfProtectionMatcher(new AntPathRequestMatcher("/oauth/authorize")) 
           .disable() 
           .headers() 
           .frameOptions().disable() 
           .sessionManagement() 
           .sessionCreationPolicy(SessionCreationPolicy.STATELESS) 
           .and() 
           .authorizeRequests() 
           .antMatchers("/hello/**").permitAll() 
           .antMatchers("/secure/**").authenticated(); 
     
   
   @Configuration 
   @EnableAuthorizationServer 
   protected static class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter implements EnvironmentAware { 
     private static final String ENV_OAUTH = "authentication.oauth."
     private static final String PROP_CLIENTID = "clientid"
     private static final String PROP_SECRET = "secret"
     private static final String PROP_TOKEN_VALIDITY_SECONDS = "tokenValidityInSeconds"
     private RelaxedPropertyResolver propertyResolver; 
     @Autowired 
     private DataSource dataSource; 
     @Bean 
     public TokenStore tokenStore() { 
       return new JdbcTokenStore(dataSource); 
     
     @Autowired 
     @Qualifier("authenticationManagerBean"
     private AuthenticationManager authenticationManager; 
     @Override 
     public void configure(AuthorizationServerEndpointsConfigurer endpoints) 
         throws Exception { 
       endpoints 
           .tokenStore(tokenStore()) 
           .authenticationManager(authenticationManager); 
     
     @Override 
     public void configure(ClientDetailsServiceConfigurer clients) throws Exception { 
       clients 
           .inMemory() 
           .withClient(propertyResolver.getProperty(PROP_CLIENTID)) 
           .scopes("read", "write"
           .authorities(Authorities.ROLE_ADMIN.name(), Authorities.ROLE_USER.name()) 
           .authorizedGrantTypes("password", "refresh_token"
           .secret(propertyResolver.getProperty(PROP_SECRET)) 
           .accessTokenValiditySeconds(propertyResolver.getProperty(PROP_TOKEN_VALIDITY_SECONDS, Integer.class, 1800)); 
     
     @Override 
     public void setEnvironment(Environment environment) { 
       this.propertyResolver = new RelaxedPropertyResolver(environment, ENV_OAUTH); 
     
   
 }

This is it. Try running Spring boot application by mvn spring-boot:run

Then check your oauth2 security by executing following curls:

Reference: Spring Boot Oauth2 Security from our JCG partner Rajith Delantha at the Looping around with Rajith… blog.
Do you want to know how to develop your skillset to become a Java Rockstar?
Subscribe to our newsletter to start Rocking right now!
To get you started we give you our best selling eBooks for FREE!
1. JPA Mini Book
2. JVM Troubleshooting Guide
3. JUnit Tutorial for Unit Testing
4. Java Annotations Tutorial
5. Java Interview Questions
6. Spring Interview Questions
7. Android UI Design
and many more ....
I agree to the Terms and Privacy Policy

Rajith Delantha

Rajith is an software engineer, open source contributor and love to develop application based on open source projects.
Subscribe
Notify of
guest


This site uses Akismet to reduce spam. Learn how your comment data is processed.

13 Comments
Oldest
Newest Most Voted
Inline Feedbacks
View all comments
Roger
Roger
9 years ago

I tried the curl message: curl -vu rajith:secret http://localhost:9191/ api/oauth/token?username=admin&password=admin&grant_type=password I got {“error”:”invalid_request”,”error_description”:”Missing grant type”} Looks like the entire parameter list is not “getting” to the application. Curl output: * Adding handle: conn: 0xa84000 * Adding handle: send: 0 * Adding handle: recv: 0 * Curl_addHandleToPipeline: length: 1 * – Conn 0 (0xa84000) send_pipe: 1, recv_pipe: 0 * About to connect() to localhost port 9191 (#0) * Trying 127.0.0.1… * Connected to localhost (127.0.0.1) port 9191 (#0) * Server auth using Basic with user ‘rajith’ > GET /api/oauth/token?username=admin HTTP/1.1 > Authorization: Basic cmFqaXRoOnNlY3JldA== > User-Agent: curl/7.33.0 > Host: localhost:9191 >… Read more »

Houssem
Houssem
8 years ago

You’ve used a database so why you didn’t store the clients in the database … (because you used clients .inMemory() )
this let the server remembrer its clients even after a restart, Right?
I always check this website and I rarely find comments, so here I have posted my comment and my question and I wish that you gave me an answer.
Thanks in advance

Rajith
Rajith
8 years ago
Reply to  Houssem

This is just a demo project that try to use spring boot + oauth2 out of the box configuration. Answering your question yes you are right, but again this is just a demo project and you are free to extend this.

Nirant
Nirant
8 years ago
Reply to  Rajith

Hi Rajith
How can i store client in db and use that for authentication.

kris
kris
8 years ago

Hi, Thanks for posting good example. Do you have any clue why it is not working with post request. Appreciate if you able to provide curl sample.

-Kris

venkat
venkat
8 years ago

Hi brother, Thanks for the example on Github. I just trying with the demo. But when i execute to fetch ‘refresh token’ i get the following error:

{
“error”: “unauthorized”,
“error_description”: “Full authentication is required to access this resource”
}

Can u please comment what i’m making wrong. So that i can continue with this. If i get clear picture on this, it would be a great help.

venkat
venkat
8 years ago

Hai Brother,

I got working with the sample as mentioned in the steps in Github page. But, i have a questions to ask. Please reply for clarification then it would be a great help for me:

1. How to generate NEW_REFRESH_TOKEN for every ACCESS_TOKEN?

can u give a walk-through or any clue for that?

Nivas Mane
Nivas Mane
8 years ago

Hello sir,

I have error for fetching refresh token using RestClient…Plz give me sugestion..what exactly do there..

Thank you

adinarayana
adinarayana
8 years ago

Thanks a lot Rajith. It’s very helpful…

Narottam Singh
Narottam Singh
8 years ago

Hello,

This is great post , its working fine with SQL database.

I need implement spring rest oauth2 security with NO -SQL(MONGO) database. can you provide me any example or idea how to implement with mongo.

William Fragoso
William Fragoso
8 years ago

Thank you for sharing your knowledge! It greatly facilitated my learning of how Sping Boot + OAuth2 works.

Raja
Raja
7 years ago

Hi Rajith
I have implemented rajithd/spring-boot-oauth2.
Can you tell me how can I change password admin to something else in db.

secret
6 years ago

Please explain which Oauth2 grant type is being implemented here

Back to top button