Azure Entra ID Implementation Guide
Introduction to Authentication and Authorization
Before we dive into the Azure Entra ID implementation, let’s break down two key concepts: Authentication and Authorization.
Authentication
Authentication is the process of verifying who the user is. It answers the question, “Is this user really who they claim to be?”
In the context of Azure Entra ID, authentication is handled by verifying user credentials, such as username and password, or through more secure methods like multi-factor authentication (MFA) or OAuth2/OpenID Connect (OIDC) tokens. Azure Entra ID acts as the Identity Provider (IdP) in this process.
Authorization
Authorization, on the other hand, determines what an authenticated user is allowed to do. It answers the question, “What actions can this user perform?”
In Azure Entra ID, once a user is authenticated, Access Tokens are issued, and they contain scopes and roles that dictate what actions the user can perform within your application.
Evolution of Authentication Mechanisms
Authentication mechanisms have evolved significantly over time to become more secure and user-friendly. Here are some of the notable developments:
Password-Based Authentication: Traditional method where users provide credentials (username/password). It’s prone to security issues (e.g., password leaks, brute-force attacks).
Token-Based Authentication: Introduction of OAuth 2.0 and OpenID Connect (OIDC). This shifts the focus from passwords to tokens, which are more secure and prevent credentials from being shared directly.
Multi-Factor Authentication (MFA): Introduces an additional layer of security by requiring users to authenticate via another factor (e.g., SMS code, Authenticator App).
Modern OAuth 2.0 Flows: Now include mechanisms such as PKCE (Proof Key for Code Exchange), designed to provide better security for public clients like SPAs (Single Page Applications).
Authorization with PKCE Mechanism Flow
What is PKCE?
PKCE (Proof Key for Code Exchange) is an extension to the OAuth 2.0 Authorization Code flow, used to prevent certain types of attacks (like the authorization code interception attack).
PKCE Flow in Detail
The PKCE flow is especially useful in SPAs (Single Page Applications) or mobile apps, where you cannot securely store secrets. It provides a way for the app to prove that it is the legitimate recipient of the authorization code.
Steps in PKCE Flow:
Client Creates a Code Verifier and Code Challenge:
The client (frontend app) creates a code_verifier, which is a random string.
The app hashes this code_verifier using SHA256 and generates a code_challenge.
User Authentication:
- The app redirects the user to the Azure Entra ID authorization endpoint, sending the code_challenge and other details like the client ID and redirect URI.
User Grants Access:
The user logs in to Azure Entra ID and grants access.
Azure Entra ID then issues an authorization code to the frontend app.
Exchange Authorization Code for Access Token:
The frontend app sends the authorization code along with the original code_verifier (not the code_challenge) to the token endpoint.
Azure Entra ID verifies the code_verifier against the previously sent code_challenge. If they match, an access token is issued.
Access Token Usage:
- The frontend app receives the access token and uses it to call protected APIs by adding it to the Authorization header of the request.
This flow prevents attackers from intercepting the authorization code and using it on their own, as the code_verifier is required to complete the token exchange.
How to Implement PKCE in Frontend
To implement PKCE in your frontend (SPA or mobile app):
Use libraries like MSAL.js (Microsoft Authentication Library) for Azure AD.
The PKCE challenge and token management is automatically handled by these libraries. You just need to configure your app with Azure AD settings (client ID, tenant, redirect URIs).
Spring Boot Project Setup for Azure Entra ID
Configuring Spring Boot to Use Azure Entra ID
In your Spring Boot application, you’ll need to configure it to act as a resource server that validates JWT tokens issued by Azure Entra ID.
Steps for Implementation:
a) Add Dependencies
First, include the required Spring Security OAuth2 dependencies in your pom.xml
:
<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-security</artifactId>
</dependency>
b) Configure application.yml
for Azure Entra ID
Next, configure your Spring Boot application to point to Azure Entra ID for token validation using the issuer URI:
spring:
security:
oauth2:
resourceserver:
jwt:
issuer-uri: https://login.microsoftonline.com/{tenant-id}/v2.0
# you can find the issuer-uri in you token
The
issuer-uri
tells the resource server where to retrieve public keys (JWKS) and other token details from Azure AD’s OpenID Connect discovery document.Replace
{tenant-id}
with your actual Azure AD tenant ID.
c) Understanding How issuer-uri
Works
The issuer-uri points to Azure’s OpenID Connect (OIDC) discovery endpoint. When a JWT is received by your application, Spring Security will:
Retrieve the OIDC discovery document from the issuer URI (
https://login.microsoftonline.com/{tenant-id}/v2.0/.well-known/openid-configuration
).Use the discovery document to find the JWKS (JSON Web Key Set), which contains the public keys Azure AD uses to sign the tokens.
Validate the incoming JWT’s signature and ensure it was issued by the Azure Entra ID tenant (matching the issuer).
d) Secure Endpoints with Roles and Scopes
You can secure specific endpoints in your application based on user roles or scopes defined in the JWT. For example:
@Bean
SecurityFilterChain securityFilterChain(HttpSecurity http) throws Exception {
http
.authorizeRequests(authorizeRequests ->
authorizeRequests
.antMatchers("/admin/**").hasRole("ADMIN")
.antMatchers("/user/**").hasAnyRole("USER", "ADMIN")
.anyRequest().authenticated()
)
.oauth2ResourceServer(OAuth2ResourceServerConfigurer::jwt);
return http.build();
}
- The
hasRole("ADMIN")
orhasAnyRole
methods will check the user’s roles that are included in the JWT token.
Conclusion
By following these steps, you’ll be able to:
Authenticate users using Azure Entra ID.
Securely implement PKCE in the frontend to prevent interception attacks.
Integrate Azure Entra ID with your Spring Boot application to verify and authorize API requests.