Spring Boot OAuth2 Part 1 - Getting The Authorization Code | JavaInUse



Spring Boot OAuth2 Part 1 - Getting The Authorization Code

In previous tutorial we had an overview of OAuth and how we will be implementing it.
In this tutorial we will be implementing the Client Application and the Resource Server. The flow we will be implementing is as follows -
  • The Resource Owner will ask the Client Application to get some data from the Resource Server.
  • The Resource Server asks the Resource Owner to authenticate itself and as for authorization to share data.
  • After successful authentication the Resource Server shares an authorization code with the client application
In the next tutorial we will see how using the authorization code

Spring Boot Security - Implementing OAuth2

Spring Boot Security - Introduction to OAuth Spring Boot OAuth2 Part 1 - Getting The Authorization Code Spring Boot OAuth2 Part 2 - Getting The Access Token And Using it to fetch data. Spring Boot + OAuth 2 Client Credentials Grant - Hello World Example. Spring Boot + OAuth 2 Password Grant - Hello World Example.

Video

This tutorial is explained in the below Youtube Video.

Lets Begin?

  • Resource Server Application
    In a previous tutorial we had implemented an Application with Simple Login Page using Spring Boot Security. We will quickly create a similar project which will authenticate and return json data. Also we will be configuring the authorization server. The Maven project will be as follows -
    The pom.xml will have added the spring-security-oauth2 dependency
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>
        <groupId>com.oauth</groupId>
        <artifactId>boot-sec</artifactId>
        <version>0.0.1-SNAPSHOT</version>
        <packaging>jar</packaging>
    
        <name>boot-resource-server</name>
        <description>Demo project for Spring Boot OAuth</description>
    
        <parent>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-parent</artifactId>
            <version>1.5.2.RELEASE</version>
            <relativePath /> <!-- lookup parent from repository -->
        </parent>
    
        <properties>
            <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
            <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
            <java.version>1.8</java.version>
        </properties>
    
        <dependencies>
    
            <dependency>
                <groupId>org.springframework.security.oauth</groupId>
                <artifactId>spring-security-oauth2</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-web</artifactId>
            </dependency>
    
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-security</artifactId>
            </dependency>
    
        </dependencies>
    
        <build>
            <plugins>
                <plugin>
                    <groupId>org.springframework.boot</groupId>
                    <artifactId>spring-boot-maven-plugin</artifactId>
                </plugin>
            </plugins>
        </build>
    
    </project>
    
    Define the Spring Boot bootstrap class having the SpringBootApplication annotation.
    package com.javainuse;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class SpringBootResourceServerApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringBootResourceServerApplication.class, args);
        }
    }
    
    Define the model class Employee. We will be return this model class as JSON response.
    package com.javainuse.model;
    
    public class Employee {
    
        private String empId;
        private String empName;
    
        public String getEmpId() {
            return empId;
        }
    
        public void setEmpId(String empId) {
            this.empId = empId;
        }
    
        public String getEmpName() {
            return empName;
        }
    
        public void setEmpName(String empName) {
            this.empName = empName;
        }
    
        @Override
        public String toString() {
            return "Employee [empId=" + empId + ", empName=" + empName + "]";
        }
    
    }
    
    Define the controller that exposes a GET REST endpoint to return JSON as response.
    package com.javainuse.controllers;
    
    import java.util.ArrayList;
    import java.util.List;
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.ResponseBody;
    import com.javainuse.model.Employee;
    
    @Controller
    public class EmployeeController {
    
        @RequestMapping(value = "/user/getEmployeesList", produces = "application/json")
        @ResponseBody
        public List<Employee> getEmployeesList() {
            List<Employee> employees = new ArrayList<>();
            Employee emp = new Employee();
            emp.setEmpId("emp1");
            emp.setEmpName("emp1");
            employees.add(emp);
            return employees;
    
        }
    
    }
    
    Finally we will be configuring security. In this configuration we specify which urls are to be intercepted, and are to be accessed by which users and having which roles.
    package com.javainuse.config;
    
    import org.springframework.context.annotation.Configuration;
    import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
    import org.springframework.security.config.annotation.web.builders.HttpSecurity;
    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;
    
    @Configuration
    @EnableWebSecurity
    public class EmployeeSecurityConfiguration extends WebSecurityConfigurerAdapter {
    
        @Override
        public void configure(WebSecurity web) throws Exception {
            web.ignoring().antMatchers("/resources/**");
        }
    
        @Override
        protected void configure(HttpSecurity http) throws Exception {
            http.authorizeRequests().antMatchers("/").permitAll().antMatchers("/user/getEmployeesList")
                .hasAnyRole("ADMIN").anyRequest().authenticated().and().formLogin()
                .permitAll().and().logout().permitAll();
    
            http.csrf().disable();
        }
    
        @Override
        public void configure(AuthenticationManagerBuilder authenticationMgr) throws Exception {
            authenticationMgr.inMemoryAuthentication().withUser("admin").password("admin")
                .authorities("ROLE_ADMIN");
        }
    }
    
    Next we configure an authorization server using EnableAuthorizationServer annotation.
    The server is customized by extending the class AuthorizationServerConfigurerAdapter which provides empty method implementations for the interface AuthorizationServerConfigurer.
    The authorization server does not secure the authorization end point i.e. /oauth/authorize. The configure method here injects the Spring Security authentication manager.
    Using in memory client service we setup the clients that can access the server.
    package com.javainuse.config;
    
    import org.springframework.context.annotation.Configuration;
    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;
    
    @Configuration
    @EnableAuthorizationServer
    public class AuthorizationServerConfig extends AuthorizationServerConfigurerAdapter {
    
        @Override
        public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
            clients.inMemory().withClient("javainuse").secret("secret").authorizedGrantTypes("authorization_code")
                .scopes("read").authorities("CLIENT");
        }
    }
    
  • Client Application
    We will create the client application. This application will ask the resource server we created above for JSON data.
    As explained previously we have assumed that this Client Application is already registered to the Resource Server, and has got the client id as 'javainuse' and secret key as 'secret'
    According to OAuth spec, it should ask for authorization at the default uri /authorize.
    We can change this default uri according to the requirement but we will be using the default one only in this example.
    Along with the default uri we should also send the following parameters.
    • response_type - REQUIRED. Value MUST be set to "code".
    • client_id - REQUIRED. The client identifier obtained during registration. In our case it is 'javainuse'
    • redirect_uri - OPTIONAL. After successful authorization, the resource owner should redirect to this uri.
    • scope - OPTIONAL. The scope of the access request. Can be either Read or Write. We will be using Read value.
    The above parameters should be "application/x-www-form-urlencoded" format. So lets begin the implementation.
    The Maven Project is as follows -
    The pom.xml will is as follows -
    <?xml version="1.0" encoding="UTF-8"?>
    <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    	xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    	<modelVersion>4.0.0</modelVersion>
    
    	<groupId>com.oauth</groupId>
    	<artifactId>boot-client-application</artifactId>
    	<version>0.0.1-SNAPSHOT</version>
    	<packaging>jar</packaging>
    
    	<name>boot-client-application</name>
    	<description>Demo project for Spring Boot</description>
    
    	<parent>
    		<groupId>org.springframework.boot</groupId>
    		<artifactId>spring-boot-starter-parent</artifactId>
    		<version>1.5.2.RELEASE</version>
    		<relativePath /> <!-- lookup parent from repository -->
    	</parent>
    
    	<properties>
    		<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    		<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    		<java.version>1.8</java.version>
    	</properties>
    
    	<dependencies>
    
    		<dependency>
    			<groupId>org.springframework.boot</groupId>
    			<artifactId>spring-boot-starter-web</artifactId>
    		</dependency>
    
    		<dependency>
    			<groupId>org.apache.tomcat.embed</groupId>
    			<artifactId>tomcat-embed-jasper</artifactId>
    		</dependency>
    
    		<dependency>
    			<groupId>javax.servlet</groupId>
    			<artifactId>jstl</artifactId>
    		</dependency>
    
    	</dependencies>
    
    	<build>
    		<plugins>
    			<plugin>
    				<groupId>org.springframework.boot</groupId>
    				<artifactId>spring-boot-maven-plugin</artifactId>
    			</plugin>
    		</plugins>
    	</build>
    
    
    </project>
    
    Create the Controller class with the getEmployeeInfo method which returns a jsp page.
    package com.javainuse.controllers;
    
    import org.springframework.stereotype.Controller;
    import org.springframework.web.bind.annotation.RequestMapping;
    import org.springframework.web.bind.annotation.RequestMethod;
    import org.springframework.web.servlet.ModelAndView;
    
    @Controller
    public class EmployeeController {
    
        @RequestMapping(value = "/getEmployees", method = RequestMethod.GET)
        public ModelAndView getEmployeeInfo() {
            return new ModelAndView("getEmployees");
        }
    }
    
    Define the following properties -
    spring.mvc.view.prefix:/WEB-INF/jsp/
    spring.mvc.view.suffix:.jsp
    
    server.port:8090
    
    Finally create the Spring Boot Bootstrap class with SpringBootApplication annotation.
    package com.javainuse;
    
    import org.springframework.boot.SpringApplication;
    import org.springframework.boot.autoconfigure.SpringBootApplication;
    
    @SpringBootApplication
    public class SpringBootFormHandingApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringBootFormHandingApplication.class, args);
        }
    }
    
    Net create the getEmployees.jsp using which we will POST a request to /authorize in form encoded url format.
    <%@taglib uri="http://www.springframework.org/tags/form" prefix="form"%>
    <html>
    <head>
    <meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1">
    <title>Get Employees</title>
    </head>
    <body>
        <h3 style="color: red;">Get Employee Info</h3>
    
        <div id="getEmployees">
            <form:form action="http://localhost:8080/oauth/authorize"
                method="post" modelAttribute="emp">
                <p>
                    <label>Enter Employee Id</label>
                     <input type="text" name="response_type" value="code" /> 
                     <input type="text" name="client_id" value="javainuse" />
                     <input type="text" name="redirect_uri" value="http://localhost:8090/showEmployees" />
                     <input type="text" name="scope" value="read" /> 
                     <input type="SUBMIT" value="Get Employee info" />
            </form:form>
        </div>
    </body>
    </html>
    
Next start the boot-resource-server and the boot-client-application. Go to localhost:8090/getEmployees
Click on Get Employee Info Button.
Enter the credentials as 'admin' and 'admin'
Authorize the Resource Owner to share the data
We can see that Resource Owner shares the authorization code with the Client Application.

Download Source Code

Download it -
Spring Boot OAuth - Client Application
Spring Boot OAuth - Resource Server