Single Sign-On with Microsoft Entra ID
This guide explains how to enable single sign-on (SSO) for applications being proxied by F5 NGINX Plus. The solution uses OpenID Connect as the authentication mechanism, with Microsoft Entra ID as the Identity Provider (IdP), and NGINX Plus as the Relying Party, or OIDC client application that verifies user identity.
This guide applies to NGINX Plus Release 35 and later. In earlier versions, NGINX Plus relied on an njs-based solution, which required NGINX JavaScript files, key-value stores, and advanced OpenID Connect logic. In the latest NGINX Plus version, the new OpenID Connect module simplifies this process to just a few directives.
-
A Microsoft Entra tenant with admin access.
-
Azure CLI. For installation instructions, see How to install the Azure CLI.
-
An NGINX Plus subscription and NGINX Plus Release 35 or later. For installation instructions, see Installing NGINX Plus.
-
A domain name pointing to your NGINX Plus instance, for example,
demo.example.com
.
Register a new application in Microsoft Entra ID that will represent NGINX Plus as an OIDC client. This is necessary to obtain unique identifiers and secrets for OIDC, as well as to specify where Azure should return tokens. Ensure you have access to the Azure Portal with Entra ID app administrator privileges.
-
Log in to Azure CLI:
az login
This command will open your default browser for authentication.
-
Register a New Application.
-
Create a new application, for example, “Nginx Demo App”, with NGINX callback URI
/oidc_callback
:az ad app create --display-name "Nginx Demo App" --web-redirect-uris "https://demo.example.com/oidc_callback"
-
From the command output, copy the
appId
value which represents your Client ID. You will need it later when configuring NGINX Plus.
-
-
Generate a new Client Secret.
-
Create a client secret for your application by running:
az ad app credential reset --id <appId>
-
Replace the
<appId>
with the value obtained in the previous step. -
From the command output, copy the the
password
value which represents your Client Secret. You will need it later when configuring NGINX Plus. Make sure to securely save the generated client secret, as it will not be displayed again. -
From the same command output, copy the the
tenant
value which represents your Tenant ID. You will need it later when configuring NGINX Plus.
-
-
Configure logout URLs to support RP-initiated logout:
-
Add a logout URL for your application by running:
az ad app update --id <appId> --web-logout-urls "https://demo.example.com/post_logout/"
-
Replace the
<appId>
with the value obtained in step 2.
-
Check the OpenID Connect Discovery URL. By default, Microsoft Entra ID publishes the .well-known/openid-configuration
document at the following address:
https://login.microsoftonline.com/<tenant_id>/v2.0/.well-known/openid-configuration
.
-
Run the following
curl
command in a terminal:curl https://login.microsoftonline.com/<tenant_id>/v2.0/.well-known/openid-configuration | jq
where:
-
the
<tenant_id>
is your Microsoft Entra Tenant ID -
the
login.microsoftonline.com
is your Microsoft Entra server address -
the
/v2.0/.well-known/openid-configuration
is the default address for Microsoft Entra ID for document location -
the
jq
command (optional) is used to format the JSON output for easier reading and requires the jq JSON processor to be installed.
The configuration metadata is returned in the JSON format:
{ ... "issuer": "https://login.microsoftonline.com/{tenant_id}/v2.0", "authorization_endpoint": "https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/authorize", "token_endpoint": "https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/token", "jwks_uri": "https://login.microsoftonline.com/{tenant_id}/discovery/v2.0/keys", "userinfo_endpoint": "https://graph.microsoft.com/oidc/userinfo", "end_session_endpoint": "https://login.microsoftonline.com/{tenant_id}/oauth2/v2.0/logout", ... }
-
-
Copy the issuer value, you will need it later when configuring NGINX Plus. Typically, the OpenID Connect Issuer for Microsoft Entra ID is
https://login.microsoftonline.com/<tenant_id>/v2.0
.
You will need the values of Client ID, Client Secret, and Tenant ID in the next steps.
With Microsoft Entra ID configured, you can enable OIDC on NGINX Plus. NGINX Plus serves as the Rely Party (RP) application — a client service that verifies user identity.
-
Ensure that you are using the latest version of NGINX Plus by running the
nginx -v
command in a terminal:nginx -v
The output should match NGINX Plus Release 35 or later:
nginx version: nginx/1.29.0 (nginx-plus-r35)
-
Ensure that you have the values of the Client ID, Client Secret, and Tenant ID obtained during Microsoft Entra ID Configuration.
-
In your preferred text editor, open the NGINX configuration file (
/etc/nginx/nginx.conf
for Linux or/usr/local/etc/nginx/nginx.conf
for FreeBSD). -
In the
http {}
context, make sure your public DNS resolver is specified with theresolver
directive: By default, NGINX Plus re‑resolves DNS records at the frequency specified by time‑to‑live (TTL) in the record, but you can override the TTL value with thevalid
parameter:http { resolver 10.0.0.1 ipv4=on valid=300s; # ... }
-
In the
http {}
context, define the Entra ID provider namedentra
by specifying theoidc_provider {}
context:http { resolver 10.0.0.1 ipv4=on valid=300s; oidc_provider entra { # ... } # ... }
-
In the
oidc_provider {}
context, specify:-
your Client ID obtained in Entra ID Configuration with the
client_id
directive -
your Client Secret obtained in Entra ID Configuration with the
client_secret
directive -
the Issuer URL obtained in Entra ID Configuration with the
issuer
directiveThe
issuer
is typically:https://login.microsoftonline.com/<tenant_id>/v2.0
.By default, NGINX Plus creates the metadata URL by appending the
/.well-known/openid-configuration
part to the Issuer URL. If your metadata URL is different, you can explicitly specify it with theconfig_url
directive. -
The logout_uri is URI that a user visits to start an RP‑initiated logout flow.
-
The post_logout_uri is absolute HTTPS URL where Microsoft Entra ID should redirect the user after a successful logout. This value must also be configured in the Entra ID application logout URLs.
-
If the logout_token_hint directive set to
on
, NGINX Plus sends the user’s ID token as a hint to Microsoft Entra ID. This directive is optional, however, if it is omitted the Microsoft Entra ID may display an extra confirmation page asking the user to approve the logout request. If the “Require ID token in logout requests” option is enabled in your tenant (commonly the case in Azure AD B2C), then the token hint becomes mandatory. -
If the userinfo directive is set to
on
, NGINX Plus will fetch userinfo from Microsoft Graph API and append the claims from userinfo to the$oidc_claims_
variables. -
Important: All interaction with the IdP is secured exclusively over SSL/TLS, so NGINX must trust the certificate presented by the IdP. By default, this trust is validated against your system’s CA bundle (the default CA store for your Linux or FreeBSD distribution). If the IdP’s certificate is not included in the system CA bundle, you can explicitly specify a trusted certificate or chain with the
ssl_trusted_certificate
directive so that NGINX can validate and trust the IdP’s certificate.
http { resolver 10.0.0.1 ipv4=on valid=300s; oidc_provider entra { issuer https://login.microsoftonline.com/<tenant_id>/v2.0; client_id <client_id>; client_secret <client_secret>; logout_uri /logout; post_logout_uri https://demo.example.com/post_logout/; logout_token_hint on; userinfo on; ssl_trusted_certificate /etc/ssl/certs/ca-certificates.crt; } # ... }
-
-
Make sure you have configured a server that corresponds to
demo.example.com
, and there is a location that points to your application (see Step 10) athttp://127.0.0.1:8080
that is going to be OIDC-protected:http { # ... server { listen 443 ssl; server_name demo.example.com; ssl_certificate /etc/ssl/certs/fullchain.pem; ssl_certificate_key /etc/ssl/private/key.pem; location / { # ... proxy_pass http://127.0.0.1:8080; } } # ... }
-
Protect this location with Entra ID OIDC by specifying the
auth_oidc
directive that will point to theentra
configuration specified in theoidc_provider {}
context in Step 5:# ... location / { auth_oidc entra; # ... proxy_pass http://127.0.0.1:8080; } # ...
-
Pass the OIDC claims as headers to the application (Step 10) with the
proxy_set_header
directive. These claims are extracted from the ID token returned by Entra ID:-
$oidc_claim_sub
- a uniqueSubject
identifier assigned for each user by Entra ID -
$oidc_claim_email
- the e-mail address of the user -
$oidc_claim_name
- the full name of the user -
any other OIDC claim using the
$oidc_claim_
variable
# ... location / { auth_oidc entra; proxy_set_header sub $oidc_claim_sub; proxy_set_header email $oidc_claim_email; proxy_set_header name $oidc_claim_name; proxy_pass http://127.0.0.1:8080; } # ...
-
-
Provide endpoint for completing logout:
# ... location /post_logout/ { return 200 "You have been logged out.\n"; default_type text/plain; } # ...
-
Create a simple test application referenced by the
proxy_pass
directive which returns the authenticated user’s full name and email upon successful authentication:# ... server { listen 8080; location / { return 200 "Hello, $http_name!\nEmail: $http_email\nEntra ID sub: $http_sub\n"; default_type text/plain; } }
-
Save the NGINX configuration file and reload the configuration:
nginx -s reload
This configuration example summarizes the steps outlined above. It includes only essential settings such as specifying the DNS resolver, defining the OIDC provider, configuring SSL, and proxying requests to an internal server.
http {
# Use a public DNS resolver for Issuer discovery, etc.
resolver 10.0.0.1 ipv4=on valid=300s;
oidc_provider entra {
# The issuer is typically something like:
# https://login.microsoftonline.com/<tenant_id>/v2.0
issuer https://login.microsoftonline.com/<tenant_id>/v2.0;
# Replace with your actual Entra client_id and client_secret
client_id <client_id>;
client_secret <client_secret>;
# RP‑initiated logout
logout_uri /logout;
post_logout_uri https://demo.example.com/post_logout/;
logout_token_hint on;
# Fetch userinfo claims
userinfo on;
}
server {
listen 443 ssl;
server_name demo.example.com;
ssl_certificate /etc/ssl/certs/fullchain.pem;
ssl_certificate_key /etc/ssl/private/key.pem;
location / {
# Protect this location with Entra OIDC
auth_oidc entra;
# Forward OIDC claims as headers if desired
proxy_set_header sub $oidc_claim_sub;
proxy_set_header email $oidc_claim_email;
proxy_set_header name $oidc_claim_name;
proxy_pass http://127.0.0.1:8080;
}
location /post_logout/ {
return 200 "You have been logged out.\n";
default_type text/plain;
}
}
server {
# Simple test upstream server
listen 8080;
location / {
return 200 "Hello, $http_name!\nEmail: $http_email\nEntra ID sub: $http_sub\n";
default_type text/plain;
}
}
}
-
Open
https://demo.example.com/
in a browser. You will be automatically redirected to the Entra ID sign-in page. -
Enter valid Entra ID credentials of a user who has access the application. Upon successful sign-in, Entra ID redirects you back to NGINX Plus, and you will see the proxied application content (for example, “Hello, Jane Doe!”).
-
Navigate to
https://demo.example.com/logout
. NGINX Plus initiates an RP‑initiated logout; Microsoft Entra ID ends the session and redirects back tohttps://demo.example.com/post_logout/
. -
Refresh
https://demo.example.com/
again. You should be redirected to Microsoft Entra ID for a fresh sign‑in, proving the session has been terminated.
If you restricted access to a group of users, be sure to select a user who has access to the application.
-
Version 2 (August 2025) – Added RP‑initiated logout (logout_uri, post_logout_uri, logout_token_hint) and userinfo support.
-
Version 1 (March 2025) – Initial version (NGINX Plus Release 34)