# Secure your API with Spring Data MongoDB and Microsoft EntraID

## Introduction

Welcome to our hands-on tutorial, where you'll learn how to build a RESTful API with Spring Data MongoDB, fortified by the security of Microsoft Entra ID and OAuth2. On this journey, we'll lead you through the creation of a streamlined to-do list API, showcasing not just how to set it up, but also how to secure it effectively. 

This guide is designed to provide you with the tools and knowledge needed to implement a secure, functional API from the ground up. Let's dive in and start building something great together!

## Prerequisites
- A MongoDB account and cluster set up
- An Azure subscription (Get started for free)
- Java Development Kit (JDK) version 17 or higher
- Apache Maven
- A Spring Boot application — you can create a **Maven project** with the Spring Initializr; there are a couple of dependencies you will need:
- Spring Web
- OAuth2 Resource Server
- Azure Active Directory  
- Select Java version 17 or higher and generate a **JAR**

You can follow along with this tutorial and build your project as you read or you can clone the repository directly:

```bash
git clone git@github.com:mongodb-developer/java-spring-boot-secure-todo-app.git
```

## Create our API with Spring Data MongoDB
Once these prerequisites are in place, we're ready to start setting up our Spring Boot secure RESTful API. Our first step will be to lay the foundation with `application.properties`.

```properties
spring.application.name=todo
spring.cloud.azure.active-directory.enabled=true
spring.cloud.azure.active-directory.profile.tenant-id=
spring.cloud.azure.active-directory.credential.client-id=
spring.security.oauth2.client.registration.azure.client-authentication-method=none
spring.security.oauth2.resourceserver.jwt.issuer-uri=https://login.microsoftonline.com//swagger-ui/oauth2-redirect.html
spring.data.mongodb.uri=
spring.data.mongodb.database=
```
- `spring.application.name=todo`: Defines the name of your Spring Boot application
- `spring.cloud.azure.active-directory...`: Integrates your application with Azure AD for authentication and authorization
- `spring.security.oauth2.client.registration.azure.client-authentication-method=none`: Specifies the authentication method for the OAuth2 client; setting it to `none` is used for public clients, where a client secret is not applicable
- `spring.security.oauth2.resourceserver.jwt.issuer-uri=https://login.microsoftonline.com/ {
}

```

Next, create a `service` package and a class TodoService. This will contain our business logic for our application.
```java
package com.example.todo.service;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.todo.model.Todo;
import com.example.todo.model.repository.TodoRepository;

import java.util.List;
import java.util.Optional;

@Service
public class TodoService {

private final TodoRepository todoRepository;

    public TodoService(TodoRepository todoRepository) {
        this.todoRepository = todoRepository;
    }

    public List findAll() {
        return todoRepository.findAll();
    }

    public Optional findById(String id) {
        return todoRepository.findById(id);
    }

    public Todo save(Todo todo) {
        return todoRepository.save(todo);
    }

    public void deleteById(String id) {
        todoRepository.deleteById(id);
    }
}
```
To establish your API endpoints, create a `controller` package and a TodoController class. There are a couple things going on here. For each of the API endpoints we want to restrict access to, we use `@PreAuthorize("hasAuthority('SCOPE_Todo.')")` where `` corresponds to the scopes we will define in Microsoft Entra ID.

We have also disabled CORS here. In a production application, you will want to specify who can access this and probably not just allow all, but this is fine for this tutorial.
```java
package com.example.todo.controller;

import com.example.todo.model.Todo;
import com.example.todo.sevice.TodoService;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.security.core.Authentication;
import org.springframework.web.bind.annotation.*;
import java.util.List;

@CrossOrigin(origins = "*")
@RestController
@RequestMapping("/api/todos")
public class TodoController {

    public TodoController(TodoService todoService) {
        this.todoService = todoService;
    }

    @GetMapping
    public List getAllTodos() {
        return todoService.findAll();
    }

    @GetMapping("/{id}")
    public Todo getTodoById(@PathVariable String id) {
        return todoService.findById(id).orElse(null);
    }

    @PostMapping
    @PreAuthorize("hasAuthority('SCOPE_Todo.User')")
    public Todo createTodo(@RequestBody Todo todo, Authentication authentication) {
        return todoService.save(todo);
    }

    @PutMapping("/{id}")
    @PreAuthorize("hasAuthority('SCOPE_Todo.User')")
    public Todo updateTodo(@PathVariable String id, @RequestBody Todo todo) {
        return todoService.save(todo);
    }

    @DeleteMapping("/{id}")
    @PreAuthorize("hasAuthority('SCOPE_Todo.Admin')")
    public void deleteTodo(@PathVariable String id) {
        todoService.deleteById(id);
    }
}
```

Now, we need to configure our Swagger UI for our app. Create a `config` package and an OpenApiConfiguration class. A lot of this is boilerplate, based on the demo applications provided by springdoc.org. We're setting up an authorization flow and specifying the scopes available in our application. We'll create these in a later part of this application, but pay attention to the API name when setting scopes (`.addString("api://todo/Todo.User", "Access todo as a user")`. You have an option to configure this later but it needs to be the same in the application and on Microsoft Entra ID.

```java
package com.example.todo.config;

import io.swagger.v3.oas.models.Components;
import io.swagger.v3.oas.models.OpenAPI;
import io.swagger.v3.oas.models.info.Info;
import io.swagger.v3.oas.models.security.OAuthFlow;
import io.swagger.v3.oas.models.security.OAuthFlows;
import io.swagger.v3.oas.models.security.Scopes;
import io.swagger.v3.oas.models.security.SecurityScheme;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

@Configuration
class OpenApiConfiguration {

@Value("${spring.cloud.azure.active-directory.profile.tenant-id}")
    private String tenantId;

    @Bean
    OpenAPI customOpenAPI() {
        OAuthFlow authorizationCodeFlow = new OAuthFlow();
        authorizationCodeFlow.setAuthorizationUrl(String.format("https://login.microsoftonline.com/%s/oauth2/v2.0/authorize", tenantId));
        authorizationCodeFlow.setRefreshUrl(String.format("https://login.microsoftonline.com/%s/oauth2/v2.0/token", tenantId));
        authorizationCodeFlow.setTokenUrl(String.format("https://login.microsoftonline.com/%s/oauth2/v2.0/token", tenantId));
        authorizationCodeFlow.setScopes(new Scopes()
        
.addString("api://todo/Todo.User", "Access todo as a user")
        
.addString("api://todo/Todo.Admin", "Access todo as an admin"));
        OAuthFlows oauthFlows = new OAuthFlows();
        oauthFlows.authorizationCode(authorizationCodeFlow);
        SecurityScheme securityScheme = new SecurityScheme();
        securityScheme.setType(SecurityScheme.Type.OAUTH2);
        securityScheme.setFlows(oauthFlows);
        return new OpenAPI()
            .info(new Info().title("RESTful APIs for Todo"))
            .components(new Components().addSecuritySchemes("Microsoft Entra ID", securityScheme));
    }
}
```
The last thing we need to do is create a WebConfig class in our `config` package. Here, we just need to disable Cross-Site Request Forgery (CSRF).

```java
package com.example.todo.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.web.SecurityFilterChain;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;

@Configuration
public class WebConfig {
    
@Bean
public SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
    http.csrf(AbstractHttpConfigurer::disable);
    return http.build();
}
}

```
When using OAuth for authentication in a web application, the necessity of CSRF tokens depends on the specific context of your application and how OAuth is being implemented.

In our application, we are using a single-page application (SPAs) for interacting with our API. OAuth is often used with tokens (such as JWTs) obtained via the OAuth Authorization Code Flow with PKCE so the CSRF is not necessary. If your application still uses cookies (traditional web access) for maintaining session state post-OAuth flow, implement CSRF tokens to protect against CSRF attacks. For API serving an SPA, we will rely on bearer tokens.

## Expose your RESTful APIs in Microsoft Entra ID
It is time to register a new application with Microsoft Entra ID (formerly known as Azure Active Directory) and get everything ready to secure our RESTful API with OAuth2 authentication and authorization. Microsoft Entra ID is a comprehensive identity and access management (IAM) solution provided by Microsoft. It encompasses various services designed to help manage and secure access to applications, services, and resources across the cloud and on-premises environments.
1. Sign in to the Azure portal. If you have access to multiple tenants, select the tenant in which you want to register an application.
2. Search for and select the **Microsoft Entra ID** service.
- If you don't already have one, create one here.
1. From the left side menu, under **Manage**, select **App registrations** and **New registration**.
2. Enter a name for your application in the **Name** field. For this tutorial, we are going to stick with the classic CRUD example, a to-do list API, so we'll call it `TodoAPI`. 
3. For **Supported account types**, select **Accounts in any organizational directory (Any Microsoft Entra directory - Multitenant) and personal Microsoft accounts**. This will allow the widest set of Microsoft entities. 
4. Select **Register** to create the application.
5. On the app **Overview** page, look for the **Application (client) ID** value, and then record it for later use. You need it to configure the `application.properties` file for this app.
6. Navigate to **Manage** and click on **Expose an API**. Locate the **Application ID URI** at the top of the page and click **Add**.
7. On the **Edit application ID URI** screen, it's necessary to generate a distinctive Application ID URI. Opt for the provided default `api://{client ID}` or choose a descriptive name like `api://todo` before hitting **Save**.
8. Go to **Manage**, click on **Expose an API**, then **Add a scope**, and provide the specified details:
    - For **Scope name**, enter _ToDo.User_.
    - For **Who can consent**, select **Admins and Users**.
    - For **Admin consent display name**, enter _Create and edit ToDo data_.
    - For **Admin consent description**, enter _Allows authenticated users to create and edit the ToDo data._
    - For **State**, keep it enabled.
    - Select **Add scope**.
9. Repeat the previous steps to add the other scopes: _ToDo.Admin_, which will grant the authenticated user permission to delete.
Now that we have our application created and our EntraID configured, we will look at how to request our access token. At this point, you can upload your API to Azure Spring Apps, following our tutorial, Getting Started With Azure Spring Apps and MongoDB Atlas, but we'll keep everything running local for this tutorial. 

## Grant access to our client with Swagger
The RESTful APIs serve as a resource server, safeguarded by Microsoft Entra ID. To obtain an access token, you are required to register a different application within Microsoft Entra ID and assign permissions to the client application.

### Register the client application
We are going to register a second app in Microsoft Entra ID.
1. Repeat steps 1 through 6 above, but this time, name your application `TodoClient`.
2. On the app **Overview** page, look for the **Application (client) ID** value. Record it for later use. You need it to acquire an access token.
3. Select **API permissions** and **Add a permission**. 
4. Under **My APIs**, select the `TodoAPI` application that you registered earlier.
Choose the permissions your client application needs to operate correctly. In this case, select both **ToDo.Admin** and **ToDo.User** permissions.
Confirm your selection by clicking on **Add permissions** to apply these to your `TodoClient` application.

5. Select **Grant admin consent for ``** to grant admin consent for the permissions you added.

### Add a user
Now that we have the API created and the client app registered, it is time to create our user to grant permission to. We are going to make a member in our Microsoft Entra tenant to interact with our `TodoAPI`.
1. Navigate to your Microsoft Entra ID and under **Manage**, choose **Users**.
2. Click on **New user** and then on **Create new user**.
3. In the **Create new user** section, fill in **User principal name**, **Display name**, and **Password**. The user will need to change this after their first sign-in.
4. Click **Review + create** to examine your entries. Press **Create** to finalize the creation of the user.

### Update the OAuth2 configuration for Swagger UI authorization
To connect our application for this tutorial, we will use Swagger. We need to refresh the OAuth2 settings for authorizing users in Swagger UI, allowing them to get access tokens via the `TodoClient` application.
1. Access your Microsoft Entra ID tenant, and navigate to the `TodoClient` app you've registered.
2. Click on **Manage**, then **Authentication**, choose **Add a platform**, and select **Single-page application**. For implicit grant and hybrid flows, choose both access tokens and ID tokens.
3. In the **Redirect URIs** section, input your application's URL or endpoint followed by `/swagger-ui/oauth2-redirect.html` as the OAuth2 redirect URL, and then click on **Configure**.

## Log into your application
Navigate to the app's published URL, then click on **Authorize** to initiate the OAuth2 authentication process. In the **Available authorizations** dialog, input the `TodoClient` app's client ID in the **client_id** box, check all the options under the **Scopes** field, leave the **client_secret** box empty, and then click **Authorize** to proceed to the Microsoft Entra sign-in page. After signing in with the previously mentioned user, you will be taken back to the **Available authorizations** dialog. Voila! You should be greeted with your successful login screen. 

, or read more about securing your data with How to Implement Client-Side Field Level Encryption (CSFLE) in Java with Spring Data MongoDB. 

Are you ready to start building with Atlas on Azure? Get started for free today with MongoDB Atlas on Azure Marketplace

  [1]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/bltacdf6418ee4a5504/66016e4fdf6972781d39cc8d/image2.png
  [2]: https://images.contentstack.io/v3/assets/blt39790b633ee0d5a7/blt594d8d4172aae733/66016e4f1741ea64ba650c9e/image3.png