# Create OAuth2 API Server using Spring Boot

In the [previous article](https://hpareek.hashnode.dev/authentication-using-oauth2-openid-connect-in-angular-single-page-application) of the series, we created a Single Page Application (SPA) using Angular Framework. And we used OAuth2 and OpenId Connect to authenticate users. In this part, we will create an API server using [Spring Boot framework](https://spring.io/projects/spring-boot) which will provide some APIs to be consumed by SPA. API server is called Resource Server as well.

### Create a Spring Boot project
There are multiple ways to create Spring Boot project. The method I like most is using [Spring Initializr](https://start.spring.io/) website.
1. Head over to https://start.spring.io/.
2. Select **Maven Project** as *Project* and **Java** as *Language*.
3. Keep the default selected version of **Spring Boot**. At the time of writing of this blog, it is `2.6.1`.
4. Select **Jar** as *Packaging*.
5. Let's use Java version `11`.
6. Fill rest of the fields as needed.
7. Click on **Add Dependencies** button.
8. Search for **Web** in the search box and Select **Spring Web** dependency. *Spring Web* dependency is used to create RESTFul APIs.
![Screenshot from 2021-12-04 12-49-27.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1638602391108/hRQCVzKGG.png)
9. Click on **Generate** button. This will download a zip.
10. Extract the zip file. You can delete the zip file after that.

### Run the project
Its time to run the project. Open the project in your favourite IDE. I will tell the steps for [IntelliJ IDEA](https://www.jetbrains.com/idea/).
1. Open **IntelliJ IDEA**. You will see a welcome screen.
![Screenshot from 2021-12-04 12-58-33.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1638602934507/Y1xg2axIj.png)
2. Click on **Open** button.
3. Select the extracted directory.
4. Click on **OK** or **Open**.
5. If you see a popup to trust the project, click on **Trust Project**. 

The project opens in IDE. It takes some time to resolve the dependencies. The progress is visible in the bottom of the IDE. Let's wait for it to complete. Create 2 package with name `controllers` and `security` as shown in the image below.

![Screenshot from 2021-12-04 16-18-19.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1638614931752/Adp0exZ_V.png)
Create a file `AuthorController.java` inside `controllers` package. This will be a rest controller for our application. Replace the code of `AuthorController.java` with the following code:
```
package dev.hashnode.hpareek.OAuth2DemoResourceServer.controllers;

import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;

@RestController
@RequestMapping("/authors") // This class handles requests for /authors
public class AuthorController {

    @GetMapping("/all") // This method handles requests for /authors/all
    public List<String> getAuthors() {
        List<String> authorList = new ArrayList<>();
        authorList.add("Author 1");
        authorList.add("Author 2");
        authorList.add("Author 3");
        return authorList;
    }
}
```
In the code above, `AuthorController` class handles requests for `/authors` endpoint. `getAuthors` method handles requests for `/authors/all` endpoint and returns a list of some dummy author names. Run the server by clicking on green play button. The server runs on port `8080` as shown in the image

![Screenshot from 2021-12-04 16-33-29.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1638615849657/9ryYHACyA.png)
Go to url `http://localhost:8080/authors/all` in browser and we can see the response from the server. We have not added security yet, so we are able to access `/authors/all` endpoint. Now, we will add security to the project.

### Adding Security Dependencies
We need 2 dependencies to make this server secure using OAuth2.
1. `spring-boot-starter-security` is required to prevent unauthorized access to the protected resources of the server. Add these lines in `pom.xml` for this dependency:
```
<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-security</artifactId>
</dependency>
```
2. `spring-boot-starter-oauth2-resource-server` is required to make this server capable of using OAuth2 protocol to verify the access of the user. Add these lines in `pom.xml` file for this dependency:
```
<dependency>
    <groupId>org.springframework.boot</groupId>
	<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
</dependency>
```
After adding the above dependencies, the `dependencies` node of the `pom.xml` file looks similar to below code:
```

	<dependencies>
		<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>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-oauth2-resource-server</artifactId>
		</dependency>

		<dependency>
			<groupId>org.springframework.boot</groupId>
			<artifactId>spring-boot-starter-test</artifactId>
			<scope>test</scope>
		</dependency>
	</dependencies>
```
After adding dependencies, *Refresh maven changes* using `Ctrl/Cmd + Shift + o` in IntelliJ IDEA or any other method (depends on IDE). Some IDEs do this automatically.

### Configure Resource Server
Edit `src/main/resources/application.properties` file and replace the code with following code:
```
spring.security.oauth2.resourceserver.jwt.issuer-uri=<Issuer URI>

```
**Issuer URI** is same which was used while creating Angular application in the previous article. If you are using **Okta** as an identity provider, then Issuer URI is `https://${OktaDomain}/oauth2/default`.

Create a file `SecurityConfig.java` inside `security` package and replace the code with the following code:
```
package dev.hashnode.hpareek.OAuth2DemoResourceServer.security;

import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

@Configuration
public class SecurityConfig extends WebSecurityConfigurerAdapter {
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .oauth2ResourceServer().jwt();
    }
}
```
In this code, we are configuring `HttpSecurity` to make sure that each request is authenticated and to use OAuth2 protocol for authenticating and authorizing requests. Now, restart the server and try to access `http://localhost:8080/authors/all` url again in a browser. You won't be able to access it, since we have secured our server to allow only authenticated requests.

### Get Access Token
To access the protected resources at resource server, the request should contain some information about the authenticated user. This is done using `authorization header`. For OAuth2 protocol, we use `Authorization: Bearer ACCESS_TOKEN` header. We get `ACCESS_TOKEN`, when we authenticate to application using OAuth2. So, how do we get it?

Simple, run the angular application using `ng serve` command which we developed in previous article and open the url `http://localhost:4200` in a private browser window. Open **Developer tools** in browser and switch to **Network** tab. Now, click on **Login** button and login using username and password. After successful login, in network tab, wee see a request to `token` endpoint. Click on this request to see the response. We see the response similar to the image below:

![Screenshot from 2021-12-04 19-45-07.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1638627348870/cFvY5W6YY.png)
From the response copy the value of `access_token` field. This is the required `ACCESS_TOKEN`. Now, open any terminal and paste the following command to send a request to the resource server along with `ACCESS_TOKEN`:
```
curl -X GET --location "http://localhost:8080/authors/all" \
-H "Authorization: Bearer ACCESS_TOKEN"
```
You will get response like this:
```
["Author 1","Author 2","Author 3"]
```
### Configure Angular App to send access token
Now, let's configure the Angular App to send access token with each request to resource server. Open `app.module.ts` file and replace the code with the below code:
```
import { HttpClientModule } from '@angular/common/http';
import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { OAuthModule } from 'angular-oauth2-oidc';

import { AppComponent } from './app.component';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    OAuthModule.forRoot({
      resourceServer: {
        allowedUrls: ["http://localhost:8080"],
        sendAccessToken: true
      }
    })
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

```
Here, we are defining `resourceServer` to send `access_token` with all requests which has prefix `http://localhost:8080`. Now, let's send a request to resource server from app. Open `app.component.ts` file and replace the code with the following code:
```
import { HttpClient } from '@angular/common/http';
import { Component } from '@angular/core';
import { OAuthService } from 'angular-oauth2-oidc';
import { authCodeFlowConfig } from './config/authCodeFlowConfig';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'AngularOAuth2Demo';

  constructor(private oauthService: OAuthService,
    private _http: HttpClient
  ) {
    this.oauthService.configure(authCodeFlowConfig);
    this.oauthService.loadDiscoveryDocumentAndTryLogin();
  }

  login() {
    this.oauthService.initCodeFlow();
  }

  logout() {
    this.oauthService.logOut();
  }

  get name () {
    const claims = this.oauthService.getIdentityClaims();
    if (!claims) return null;
    const nameClaim = claims as {name: string};
    return nameClaim.name;
  }

  getAuthors() {
    this._http.get("http://localhost:8080/authors/all")
      .toPromise()
      .then(console.log)
      .catch(console.error);
  }

}

```
In `getAuthors()` method we are simply sending a request to `http://localhost:8080/authors/all` endpoint and printing the response to the console. Header `Authorization: Bearer ACCESS_TOKEN` will be added to it since we configured it in previous step. Now, create a `button` in `app.component.html` file to invoke `getAuthors` method using the following code:
```
<div>
  // Previous code should remain same
  <br />
  <button (click)="getAuthors()">Get Authors</button>
</div>
```
Now, restart the angular app and open the same url `http://localhost:4200` in a private browser window. Login to the app by clicking on **Login** button. Open the developer tools and select **Network** tab. Click on **Get Authors** button. We can see a request sent to `http://localhost:8080/authors/all` endpoint with `Authorization` header.
![Screenshot from 2021-12-04 20-55-56.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1638631583680/TaJzStcZS.png)

### Solve CORS Error
But, if we open the **Console** tab, we see an error that the request to the resource server is blocked by the **CORS** policy.
![Screenshot from 2021-12-04 20-57-51.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1638631693604/hvNKqX9RT.png)
This is because, by default we can not send request to another origin (server) from any server. To allow requests from Angular app to Resource Server, we need to do some configuration in Spring Boot Application.

Open `SecurityConfig.java` file inside `security` package and add `http.cors()` after other configurations:
```
http.authorizeRequests()
                .anyRequest().authenticated()
                .and()
                .oauth2ResourceServer().jwt();
        http.cors();
```
We need to configure individual controllers with `CrossOrigin` annotation. Open `AuthorController.java` file inside `controllers` package and add `CrossOrigin` annotation:
```
@CrossOrigin(origins = "http://localhost:4200") // allow requests from origin 'http://localhost:4200'
@RestController
@RequestMapping("/authors") // This class handles requests for /authors
public class AuthorController {
    // Rest of the code
}
```
Restart the Resource Server. Again click on **Get Authors** button in Angular app (make sure you are signed into the app).
In the console, we can see the correct output:

![Screenshot from 2021-12-04 21-09-35.png](https://cdn.hashnode.com/res/hashnode/image/upload/v1638632399809/EkrnyF8bb.png)
It's working. Wow.

### Summary
You can find the source code of everything covered in the article [here](https://github.com/himanshu-pareek/OAuth2SPA/tree/02-Resource-server-init). In this article, we saw how to make resource server and how to send api requests to the server. We also got to know about CORS and how to solve it. In the next article, I will explain how to handle Authentication and Authorization failure errors in resource server and how to return appropriate response.

Your suggestions are welcome. Until then, bye and keep learning...
