DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Leveraging Salesforce Using Spring Boot
  • Develop a Spring Boot REST API in AWS: PART 4 (CodePipeline / CI/CD)
  • Aggregating REST APIs Calls Using Apache Camel
  • Composite Requests in Salesforce Are a Great Idea

Trending

  • Building a DevOps-Ready Internal Developer Platform: A Hands-On Guide to Golden Paths, Self-Service, and Automated Delivery Pipelines
  • Designing API-First EMR Architectures in .NET: Enabling Modular Growth in Compliance-Driven Systems
  • From Indicators to Insights: Automating IOC Enrichment Using Python and Threat Feeds
  • How to Format Articles for DZone
  1. DZone
  2. Software Design and Architecture
  3. Integration
  4. Secure Spring REST API Using OAuth2

Secure Spring REST API Using OAuth2

Want to learn how to secure a Spring REST API using OAuth2? Check out this post to learn how using OAuth2 and PostgreSQL.

By 
Riddhi Parkhiya user avatar
Riddhi Parkhiya
·
Sep. 27, 18 · Tutorial
Likes (12)
Comment
Save
Tweet
Share
68.7K Views

Join the DZone community and get the full member experience.

Join For Free

Let’s secure our Spring REST API with OAuth2 + PostgreSQL. We will store user credentials in the PostgreSQL database and client credentials will be stored in the In-memory database. Every client has its own unique client ID.

To secure our REST API, we will have to do the following things:

  • Configure Spring Security and the database

  • Configure the authorization server and resource server

  • Get an access token and a refresh token

  • Get a protected Resource (REST API) using an access token

Before we start, let's look at some basic concepts related to Spring Security OAuth2.

OAuth2 Roles

Resource Owner

A resource owner is a person (like an end user) in an application that owns the service or a security policy.

Resource Server

This is the resource server hosting the protected resource or service.

Client Application

The client application is the application requesting access to resources stored on the resource server. The client application also obtains authorization from the resource owner.

Authorization Server

The authorization server is the server authorizing the client app to access the resources of the resource owner.

Application

Let's start to secure our REST API endpoints.

First, we need to enable Spring Security to add the security feature in the application. To configure and enable Spring Security, the @EnableWebSecurity annotation is used.

By using @EnableGlobalMethodSecurity, we can easily secure our methods with Java configurations. Global method security will activate  @PreFilter, @PostFilter , @PreAuthorize, and the @PostAuthorize  annotations if we want to use them.

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

  @Autowired
  UserDetailsServiceImpl userDetailsService;


  @Override
  protected void configure(HttpSecurity http) throws Exception {
    http.csrf().disable().sessionManagement().sessionCreationPolicy(SessionCreationPolicy.STATELESS) 
      .and().authorizeRequests().antMatchers("/oauth/token")
      .permitAll().anyRequest().authenticated();
  }

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


Note:

  • Here, WebSecurityConfigurerAdapter  is used to customize security implementation.

  •  Endpoint /OAuth/tpken is used to request a token (access or refresh).

  • We inject a custom implementation of UserDetailsService in order to retrieve user details from the database.

  • We use the defined BCryptPasswordEncoder bean for password encoding.

Now, we need to configure the authorization server. The @EnableAuhtorizationServer  annotation enables an authorization server. AuthorizationServerConfigurerAdapter  implements the  AuthorizationServerConfigurer, which provides all the necessary methods to configure an Authorization server. It also contains information about registered clients and possible access scopes and grant types.

@Configuration
@EnableAuthorizationServer
public class OAuthConfiguration extends AuthorizationServerConfigurerAdapter {

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

  @Autowired
  UserDetailsService userDetailsService;

  @Override
  public void configure(final AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
    oauthServer.tokenKeyAccess("permitAll()").checkTokenAccess("isAuthenticated()");
  }

  @Override
  public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
    clients.inMemory()
      .withClient("fooClientId").secret("secret")
      .authorizedGrantTypes("password", "authorization_code", "refresh_token").scopes("read","write")
      .autoApprove(true);
  }

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


Notes on the above configuration:

  • Registers a client with client-id ‘fooClientId’ and password ‘ secret’ and the roles and scope they are allowed.

  • Specifies authorized grant types (password, authorization_code, refresh_token).

  • Specifies the JwtTokenStore to store tokens.

Next, we need to configure the resource server. The @EnableResourceServer  annotation, applied on OAuth2 Resource Servers, enables a Spring Security filter that authenticates requests using an incoming OAuth2 token. The class ResourceServerConfigurerAdapter implements the ResourceServerConfigure,  providing methods to adjust the access rules and paths that are protected by OAuth2 security.

@Configuration
@EnableResourceServer
public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
    private static final String RESOURCE_ID = "resource-server-rest-api";
    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
        resources.resourceId(RESOURCE_ID);
    }
    @Override
    public void configure(HttpSecurity http) throws Exception {
        http.antMatcher("/**").authorizeRequests().anyRequest().authenticated();
    }
}


Next, we need to update the application.properties to configure the PostgreSQL database. Create the user_management database in PostgreSQL and add the user table to store user credentials with roles.

spring.jpa.database-platform=org.hibernate.dialect.PostgreSQL9Dialect
# Hibernate ddl auto (create, create-drop, validate, update)
spring.jpa.hibernate.ddl-auto=update
spring.datasource.url=jdbc:postgresql://localhost/user_management
spring.datasource.username=postgres
spring.datasource.password=root
spring.jpa.generate-ddl=true


Database script  :

// To create database "user_management"
CREATE DATABASE user_management;

// To create table "users" in "user_management" database
CREATE TABLE users(
   id INT PRIMARY KEY     NOT NULL,
   enabled INT NOT NULL,
   password TEXT    NOT NULL,
   username  TEXT    NOT NULL,
   role TEXT    NOT NULL
);

// To insert values into table
INSERT INTO users VALUES (1,1,'$2a$10$iFolDdAquu/qSclfNDiBK.GFpO0gUBAsCilygHuCy6pUWVd.4ZK8G', 'admin','ADMIN');


Test Application

To access any secured REST API endpoint, first, we will have to get the access token. To get the access token, we will need to add an authorization header with client credentials and add the request body with user credentials in postman.

After receiving the access token and refresh token, we can access any secured REST API endpoints using access token. When the access token expired, the refresh token is used to get a new access token.

You can refer to the whole project on GitHub.

Spring Security API REST Web Protocols authentication Spring Framework

Opinions expressed by DZone contributors are their own.

Related

  • Leveraging Salesforce Using Spring Boot
  • Develop a Spring Boot REST API in AWS: PART 4 (CodePipeline / CI/CD)
  • Aggregating REST APIs Calls Using Apache Camel
  • Composite Requests in Salesforce Are a Great Idea

Partner Resources

×

Comments

The likes didn't load as expected. Please refresh the page and try again.

  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook