Spring Boot Oauth2 implementation and generate JWT token using H2 database

Spring Boot Oauth2 Implementation using H2 Dadabase

Purpose: In this post, we will learn how we can implement Oauth2. The steps are given below.

1. Setup and Create Project: Visit hereSpring Boot Rest API Hello World Examples.

Next Step. Spring Boot Parent Dependencies.


<parent>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter-parent</artifactId>
        <version>2.2.6.RELEASE</version>
        <relativePath /> <!-- lookup parent from repository -->
    </parent>
Next Step. H2 Database Dependencies.

    <dependency>
      <groupId>com.h2database</groupId>
      <artifactId>h2</artifactId>
      <scope>runtime</scope>
    </dependency>

Next Step. Oauth2 and JWT Token dependency Dependencies.

      <dependency>
          <groupId>org.springframework.security</groupId>
          <artifactId>spring-security-jwt</artifactId>
          <version>1.0.9.RELEASE</version>
      </dependency>

      <dependency>
        <groupId>org.springframework.security.oauth</groupId>
          <artifactId>spring-security-oauth2</artifactId>
          <version>2.3.6.RELEASE</version>
      </dependency>
       

Next Step. Spring Boot main class.

Class: Application.java

Note: @SpringBootApplication=@Configuration+ @EnableAutoConfiguration+ @ComponentScan.



package com.bce;

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Application {
    public static void main(String[] args) {
        SpringApplication.run(Application.class, args);
    }

}



Next Step. Create Rest Controller.

package com.bce.contoller;

import java.util.List;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestHeader;
import org.springframework.web.bind.annotation.RestController;

import com.bce.model.UserInfo;
import com.bce.service.UserInfoService;

@RestController
public class UserController {
    @Autowired
    private UserInfoService userService;

    @GetMapping("/user/get")
    public List<UserInfo> getAllUser(@RequestHeader HttpHeaders requestHeader) {
        List<UserInfo> userInfos = userService.getAllActiveUserInfo();
       
        return userInfos;
    }

    @PostMapping("/user")
    public UserInfo addUser(@RequestBody UserInfo userRecord) {
        return userService.addUser(userRecord);
    }

}

In above controller we have two API in which BASE_URL/user is accessible without authentication and BASE_URL/user/get is accessible with authentication.

Next Step. Add below line in application.properties for H2 and Oauth2 .

#server PORT
server.port=8081

#H2 database configuration
spring.datasource.driverClassName=org.h2.Driver
spring.datasource.username=sa
spring.datasource.password=
spring.jpa.database-platform=org.hibernate.dialect.H2Dialect
#enabling the H2 console
spring.h2.console.enabled=true
spring.jpa.show-sql=true
spring.jpa.generate-ddl=true
spring.jpa.hibernate.ddl-auto=update
# Before run change directory
spring.datasource.url=jdbc:h2:C:/data/oauth2
# Custom H2 Console URL
spring.h2.console.path=/h2

#################### SECURITY CONFIG ########

#Application specific : Note: Change client id and Secret key
authentication.oauth.clientid=springbootrest
authentication.oauth.secret=restservice
authentication.oauth.tokenValidityInSeconds=6000
authentication.oauth.refreshTokenValidityInSeconds=10000
authentication.oauth.grant.type=password
authentication.oauth.grant.refresh.type=refresh_token


Next Step. OAuth Configuration add below java file (OAuthConfiguration.java)


package com.bce.configuration;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.crypto.factory.PasswordEncoderFactories;
import org.springframework.security.crypto.password.PasswordEncoder;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.security.oauth2.provider.token.store.JwtAccessTokenConverter;
import org.springframework.security.oauth2.provider.token.store.JwtTokenStore;

@Configuration
@EnableAuthorizationServer
public class OAuthConfiguration extends AuthorizationServerConfigurerAdapter {

    @Value("${authentication.oauth.clientid:clientid}")
    private String PROP_CLIENTID;
   
    @Value("${authentication.oauth.secret:secret}")
    private String PROP_SECRET;
   
    @Value("${authentication.oauth.tokenValidityInSeconds:60}")
    private Integer PROP_TOKEN_VALIDITY_SECONDS;
   
    @Value("${authentication.oauth.refreshTokenValidityInSeconds:120}")
    private Integer PROP_REFRESH_TOKEN_VALIDITY_SECONDS;

   
    @Autowired
    @Qualifier("authenticationManagerBean")
    private AuthenticationManager authenticationManager;
   
    @Autowired
    UserDetailsService userDetailsService;

    @Override
    public void configure(final AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
        oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
    }
   
    @Bean
    public PasswordEncoder passwordEncoder() {
        return PasswordEncoderFactories.createDelegatingPasswordEncoder();
    }

    @Override
    public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
        clients.inMemory()
        .withClient(PROP_CLIENTID).secret(passwordEncoder().encode(PROP_SECRET))
        .authorizedGrantTypes("password", "authorization_code", "refresh_token").scopes("read","write")
        .authorities("USER","ADMIN")
        .autoApprove(true)
        .accessTokenValiditySeconds(PROP_TOKEN_VALIDITY_SECONDS)
        .refreshTokenValiditySeconds(PROP_REFRESH_TOKEN_VALIDITY_SECONDS);
    }

    @Override
    public void configure(final AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
        endpoints.tokenStore(tokenStore()).authenticationManager(authenticationManager).accessTokenConverter(defaultAccessTokenConverter())
        .userDetailsService(userDetailsService);
    }

    @Bean
    public TokenStore tokenStore(){
        return new JwtTokenStore(defaultAccessTokenConverter());    
    }

    @Bean
    public JwtAccessTokenConverter defaultAccessTokenConverter() {
        JwtAccessTokenConverter converter = new JwtAccessTokenConverter();
        converter.setSigningKey("123");
        return converter;
    }
}


Next Step. OAuth Configuration add below java file (SecurityConfig.java)




package com.bce.configuration;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.dao.DaoAuthenticationProvider;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.method.configuration.EnableGlobalMethodSecurity;
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.crypto.bcrypt.BCryptPasswordEncoder;

import com.bce.service.UserDetailsServiceImpl;

@EnableWebSecurity
@EnableGlobalMethodSecurity(securedEnabled = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    @Autowired
    UserDetailsServiceImpl userDetailsService;

    @Override
    public void configure(WebSecurity web) throws Exception {
        web.ignoring().antMatchers("/pages/");

    }
   
    @Bean
    public DaoAuthenticationProvider authenticationProvider() {
        DaoAuthenticationProvider provider = new DaoAuthenticationProvider();
        provider.setPasswordEncoder(bCryptPasswordEncoder());
        provider.setUserDetailsService(userDetailsService);
        return provider;
    }

    @Bean
    public BCryptPasswordEncoder bCryptPasswordEncoder() {
        return new BCryptPasswordEncoder();
    }

    @Override
    @Bean
    public AuthenticationManager authenticationManagerBean() throws Exception {
        return super.authenticationManagerBean();
    }

    @Autowired
    public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
        auth.authenticationProvider(authenticationProvider());
    }
}
Next Step: add  ResourceServerConfiguration.java file.


package com.bce.configuration;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.ResourceServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configurers.ResourceServerSecurityConfigurer;

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
    private static final String RESOURCE_ID = "oauth2-api";

    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources.resourceId(RESOURCE_ID);
    }

    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests().antMatchers("/", "/h2/**", "/user", "/oauth/token").permitAll();
        http.csrf().disable();
        http.headers().frameOptions().disable();
        http.antMatcher("/**").authorizeRequests().anyRequest().authenticated();

    }
}



Next Step. Get all users without authentication token.

Next Step. Create new user for Authentication.




Next Step. Generate access token using below url. Username=client id and password=secret which is define in application properties.




Next Step. Get all users with authentication token.



Next Step. Check user in H2 database.




Download Code from GitHub.  Download

No comments:

Post a Comment