Code Monkey home page Code Monkey logo

azure-spring-apps-sso-client-credential's Introduction

Comprehensive Security with Azure Spring Apps, Application security principal, Spring Cloud Gateway SSO, and Spring Security

This example shows the procedure of ensuring secure communication between a client application and a microservice that is hosted on Azure Spring Apps and shielded behind a Spring Cloud Gateway. Under these conditions, the client app will be verified as a security principal to initiate contact with the microservice deployed on Azure Spring Apps, via the Azure Spring Apps Spring Cloud Gateway. The methodology employs Spring Cloud Gateway's Single Sign-On feature for the processes of authentication and authorization, realized through the execution of the client credentials flow.

Prerequisites

  • Azure Spring Apps Entreprise tier Instance, In which an application called books-service is created refer to this documentation for provisionning
  • App service with Node runtime, refer to this documentation for provisionning

Architecture Overview

The architecture of this example is demonstrated by a Books Application, consisting of the following components:

  • Books SPA: This Single Page Application (SPA), hosted in Azure App service, interacts with the Books Microservice for adding or searching for books.
  • Books Microservice:
    • A Spring Boot REST microservice hosted in Azure Spring Apps, this service operates behind a Spring Cloud Gateway. It stores book information in an H2 database.
    • The Books Microservice exposes two REST endpoints:
      • 'Add books' for saving books in an H2 database.
      • 'Get Book' for retrieving a book by ID.

The Big Picture
Overview of Books Application

Security Flow

The communication between The Books SPA and the Books Microservice is secured through the client credentials flow, utilizing the Spring Cloud Gateway. This flow is as follows:

Authentication Flow

1- The Books SPA requests a token from Azure AD to call the Spring Cloud Gateway. This token represents the Books SPA App registration as an application security principal.
2 - The Books SPA transmits a request with the acquired token to the Books Microservice through the Spring Cloud Gateway.
3 - The Spring Cloud Gateway validates the received token.
4 - The Spring Cloud Gateway redirects the request (along with the token) to the Books Microservice.
5 - The Books Microservice validates the token and authorizes the request.

Environment Setup

Spring Cloud Gateway Configuration

App Registration

First, we will configure the Spring Cloud Gateway app registration in Azure Portal:

  • Navigate to App registrations -> New registration  Gateway App registration

  • After the Application is registered, retrieve the client ID from the app registration overview. This client ID will be necessary for configuring Spring Cloud Gateway.

  • As we are using the client credentials flow, and the microservices behind Spring Cloud Gateway will be called by client applications security principals (i.e., the Books SPA in our case), we will define App roles for our Spring Cloud Gateway App registration. App roles are used for assigning permissions to users or apps, and are the recommended way for assigning permissions in the client credentials flow. For more details, refer to the app roles documentation.

  • We will add 2 App roles: 'Task.Write' (allows the SPA to add books) and 'Task.Read' (allows the SPA to read a book by ID). To add these roles, navigate to the app registration, click on App roles and then on Add new Roles.
     Add App role

  • Next, add a client secret for the Spring Cloud Gateway App registration. To do so, navigate to Certificate & Secrets and click on New Client Secret. Make sure to copy your client secret as it will be needed in your Spring Cloud Gateway configuration.

Spring Cloud Gateway Configuration:

Endpoint Assignment
  • In Azure portal, go to your Azure Spring Apps instance, select Spring Cloud Gateway, and enable endpoint assignment on the overview page.  SCG Endpoint

  • Copy the endpoint URL, as it will be required for configuring the Redirect URI for the Spring Cloud Gateway app registration.

SSO Configuration
  • Under the configuration tab, in the SSO section, configure the following:
    • Scope: .default, as we are using the client credentials flow (and not using a user sign in), permissions will be managed with App roles, the .default scope is suitable in this case. For more details, refer to .default scope documentation and .default with client credentials.
    • ClientId: The client Id of the Spring Cloud Gateway App registration created in previous steps.
    • ClientSecret: The client secret of Id of the Spring Cloud Gateway App registration created in previous steps.
    • Issuer URI: https://login.microsoftonline.com/< your tenant ID >/v2.0. This URI asserts as its Issuer Identifier. SSO Config
Routing Configuration
  • The routing in the Spring Cloud Gateway will be configured next. In our routes configuration, we will enable SSO (for token validation for the route) and enable tokenRelay (so the token will be passed with the request to the destination microservice). The routes file is configured as follows, and is located under service/routes.
[
    {
      "predicates": [
        "Path=/books/add",
        "Method=POST"
      ],
      "filters": [
        "StripPrefix=0"
      ],
      "tags": [
        "books"
      ],
      "ssoEnabled": true,
      "tokenRelay": true
    },
    {
        "predicates": [
          "Path=/books/{id}",
          "Method=GET"
        ],
        "filters": [
          "StripPrefix=0"
        ],
        "tags": [
          "books"
        ],
        "ssoEnabled": true,
        "tokenRelay": true
      }
]

To apply these routes in spring cloud gateway execute the following command :

az spring gateway route-config update -g <resours-group> --name <route-name> --app-name <app-name>  --routes-file routes/books.json --service <Azure spring apps instance>

Redirect URI Addition

As you have enabled SSO in Spring Cloud Gateway, Azure Ad will need to redirect the authentication response to Spring Cloud Gateway after validating the authentication token. Thus, you will need to add a redirect URI in your App registration. To do so:

  • Go to the Spring Cloud Gateway app registration created earlier, click Authentication.
  • Click on Add platform, choose Web and enter the url < your spring cloud gateway endpoint url >/login/oauth2/code/sso.

Client App Configuration

Client App registration

To enable The books SPA to call the books service with a token serving for authentication and authorization, we should first create an Identity for the books SPA, this identity is represented with the client APP registration. To create the client App registration follow these steps :

  1. In Azure portal go to App registrations and create a new App registration : client-app-reg
    Copy the Client Id of the APP registration, as we will need it in the SPA's code for acquiring the token to call the books microservice.

  2. Create a secret for the SPA App registration, Go to Certificate & Secrets and create a new Secret, copy the generated secret as you will need it in the SPA's code for acquiring the token to call the books microservice.

  3. Assign permissions to the SPA's app registration to call the books service through the Spring cloud gateway, those permissions are represented by the Spring cloud Gateway's App Registration Roles, to do so :

    • In the SPA's app registration go to API permissions -> Add a permission request permission
    • Under My APIs Tab select the Spring cloud Gateway App registration
      request permission
    • Select the Task.Read and Task.Write Roles
      request permission
  4. Applications are authorized to call APIs when they are granted permissions by users/admins as part of the consent process, as we are using using the client credentials flow, we will grant Admin consent for these permissions, to do that click on Grant Admin consent (Admin rights is required for granting Admin consent) grant admin consent

Client Application code

In the SPA, we will need to add the code for acquiring the token to be able to call the books service through the spring cloud gateway. For this purpose, we will need to use msal library. The Msal library is available for multiple languages and for different auth flows.

As our SPA is a node APP, we need first to install msal node library

npm install @azure/msal-node

In The SPA code "server.js" Add msal configuration with your SPA app registration credentials. Note : For demo purpose, we are adding directly client secret in the code, and this is not a recommended way for managing secret, in your environments, it's recommended to use Azure keyvault for storing and retrieving your secrets

const msalConfig = {
    auth: {
        clientId: "< SPA APP registration clientID>",
        authority: "https://login.microsoftonline.com/<Tenant ID>/",
        clientSecret: "< SPA APP registration clientSecred>",
    },
};

const cca = new msal.ConfidentialClientApplication(msalConfig);

Add a function for Aquiring token for the spring cloud gateway app registration scope

const tokenRequest = {
    scopes: ["api://< Spring Cloud Gateway App registration ClientID > /.default"]
};
// Function to get token
async function getToken() {
    const response = await cca.acquireTokenByClientCredential(tokenRequest);
    console.log(response.accessToken);
    return response.accessToken;
}

Call the Books service with the aquired token

    const url = SpringCloudGatewayURL + `/books/${id}`;

    try {
        const token = await getToken();
        const apiResponse = await axios.get(url, {
            headers: {
                Authorization: `Bearer ${token}`,
            },
        });
    }
    ...
Client Application code deploy

To Deploy the books SPA to a the node App Service, refer to this documentation

Books Microservice Configuration

With A Zero trust perspective, security is validated at every level, since Enabled SSO with token relay, In this section we will configure the books microservice for validating the recieved authentication token and validating if the request is authorized for each Rest Endoint, for that we are going to use spring security

Spring Security configuration

Fist we will add dependency for spring securty in pom.xml file

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

We will then configure spring security Issuer URI

spring:
  security:
    oauth2:
      resourceserver:
        jwt:
          issuer-uri: https://login.microsoftonline.com/< your tenant ID> /v2.0

We will then Add the security configuration,

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

    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            .authorizeRequests()
            .anyRequest().authenticated()
            .and()
            .oauth2ResourceServer()
            .jwt()
            .jwtAuthenticationConverter(jwtAuthenticationConverter());
    }

    private JwtAuthenticationConverter jwtAuthenticationConverter() {
        
        JwtGrantedAuthoritiesConverter converter = new JwtGrantedAuthoritiesConverter();
        converter.setAuthoritiesClaimName("roles");
        converter.setAuthorityPrefix("ROLE_"); 
    
        JwtAuthenticationConverter jwtAuthenticationConverter = new JwtAuthenticationConverter();
        jwtAuthenticationConverter.setJwtGrantedAuthoritiesConverter(converter);
        return jwtAuthenticationConverter;
    }
}

On the controller we will put the needed Role for being able to call this endpoint

@RestController
@RequiredArgsConstructor
public class BooksController{
    private final BooksService booksService;


    @PreAuthorize("hasRole('Task.Read')")
    @GetMapping("books/{id}")
    public Book getBook(@PathVariable Long id){
        return booksService.getBook(id);
    }

    @PreAuthorize("hasRole('Task.Write')")
    @PostMapping("/books/add")
    public Book addBook(@RequestBody Book book){
        return booksService.saveBook(book);
    }

}
Books-Service Application code deploy

In order to deploy the Spring APPS books-service application refer to this documentation

azure-spring-apps-sso-client-credential's People

Contributors

asmaefilali avatar microsoft-github-operations[bot] avatar microsoftopensource avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.