Single Sign-On with Okta
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 Okta 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 36 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. Starting from NGINX Plus version R34, the new OpenID Connect module simplifies this process to just a few directives.
-
An Okta administrator account with privileges to create and manage applications.
-
An NGINX Plus subscription and NGINX Plus Release 36 or later. For installation instructions, see Installing NGINX Plus.
-
A domain name pointing to your NGINX Plus instance, for example,
demo.example.com.
In Okta, register a new application for NGINX Plus as the OIDC client to obtain the Client ID, Client Secret, and required OIDC endpoints.
-
Log in to your Okta admin console.
-
In the Admin Console, go to Applications > Applications.
-
Select Create App Integration.
-
In Create a new app integration, select:
-
Sign-in method:
OIDC - OpenID Connect. -
Application type:
Web Application. -
Select Next.
-
-
In New Web App Integration:
-
Enter the Name for your new application, for example, Nginx Demo App.
-
Add a URI for the OIDC callback in Sign-in redirect URIs, for example,
https://demo.example.com/oidc_callback. -
Add a URI for post logout redirect in Sign-out redirect URIs, for example,
https://demo.example.com/post_logout/. -
Select Save.
-
-
In Applications, select Nginx Demo App.
-
In the General tab:
-
Copy the Client ID. You will need it later when configuring NGINX Plus.
-
Copy the Client secret. You will need it later when configuring NGINX Plus.
-
-
In the Sign On tab:
-
Copy the Okta Issuer (Authorization Server), for example:
https://dev-123456.oktapreview.com/oauth2/defaultYou will need it later when configuring NGINX Plus.
-
Check the OpenID Connect Discovery URL. By default, Okta publishes the .well-known/openid-configuration document at the following address:
https://<okta-domain>/oauth2/default/.well-known/openid-configuration.
-
Run the following
curlcommand in a terminal:curl https://dev-123456.okta.com/oauth2/default/.well-known/openid-configuration | jqWhere:
-
the
dev-123456.okta.comis your Okta domain -
the
/oauth2/defaultis the default authorization server -
the
/.well-known/openid-configurationis the default address for Okta for document location -
the
jqcommand (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:
json { ... "issuer": "https://dev-123456.okta.com/oauth2/default", "authorization_endpoint": "https://dev-123456.okta.com/oauth2/default/v1/authorize", "token_endpoint": "https://dev-123456.okta.com/oauth2/default/v1/token", "jwks_uri": "https://dev-123456.okta.com/oauth2/default/v1/keys", "userinfo_endpoint": "https://dev-123456.okta.com/oauth2/default/v1/userinfo", "end_session_endpoint": "https://dev-123456.okta.com/oauth2/default/v1/logout", ... } -
-
Copy the issuer value, you will need it later when configuring NGINX Plus. Typically, the OpenID Connect Issuer for Okta is
https://<okta-domain>/oauth2/default.
You will need the values of Client ID, Client Secret, and Issuer in the next steps.
By default, Okta might limit application access to certain users or groups. To add or remove users in Okta:
-
Log in to your Okta admin console.
-
In Applications, choose Nginx Demo App.
-
Go to Assignments.
-
Add or remove users and groups that can access this application.
Front-channel logout allows Okta to notify NGINX Plus when a user signs out of other Single Logout (SLO)-participating applications or from the Okta dashboard itself. Okta sends a front-channel HTTP request (typically loaded in a hidden iframe) to a logout URL that you configure in the application settings.
This feature is optional and requires NGINX Plus Release 36 or later, together with the frontchannel_logout_uri directive in the NGINX OIDC provider configuration.
-
In the Okta Admin Console, go to Settings > Features.
-
Locate Front-channel Single Logout and enable it for your org.
-
Go to Applications > Applications and open your Nginx Demo App (or the OIDC app that you created earlier).
-
On the General tab, click Edit.
-
In the Logout section, under Single Logout, enable User logs out of other logout-initiating apps or Okta. This option enables front-channel SLO for the app.
-
In Logout request URL, enter the NGINX Plus front-channel logout endpoint, for example:
https://demo.example.com/front_logout -
Select Include user session details. With this option enabled, Okta includes the user session identifier (sid) and issuer (iss) in the front-channel logout request that it sends to NGINX Plus.
-
Click Save.
With Okta 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 -vcommand in a terminal:nginx -vThe output should match NGINX Plus Release 36 or later:
nginx version: nginx/1.29.3 (nginx-plus-r36) -
Ensure that you have the values of the Client ID, Client Secret, and Issuer obtained during Okta Configuration.
-
In your preferred text editor, open the NGINX configuration file (
/etc/nginx/nginx.conffor Linux or/usr/local/etc/nginx/nginx.conffor FreeBSD). -
In the
http {}context, make sure your public DNS resolver is specified with theresolverdirective: 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 thevalidparameter:nginx http { resolver 10.0.0.1 ipv4=on valid=300s; # ... } -
In the
http {}context, define the Okta provider namedoktaby specifying theoidc_provider {}context:nginx http { resolver 10.0.0.1 ipv4=on valid=300s; oidc_provider okta { # ... } # ... } -
In the
oidc_provider {}context, specify:-
your actual Okta Client ID obtained in Okta Configuration with the
client_iddirective -
your Client Secret obtained in Okta Configuration with the
client_secretdirective -
the Issuer URL obtained in Okta Configuration with the
issuerdirectiveThe
issueris typically your Okta OIDC URL:https://dev-123456.okta.com/oauth2/default. -
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 Okta should redirect the user after a successful logout. This value must also be configured in the Okta application’s Sign-out redirect URIs.
-
If the logout_token_hint directive set to
on, NGINX Plus sends the user’s ID token as a hint to Okta. This directive is optional, however, if it is omitted the Okta may display an extra confirmation page asking the user to approve the logout request. -
The frontchannel_logout_uri directive defines the URI that receives OpenID Connect front-channel logout requests from Okta. This URI must be an HTTPS path hosted by NGINX Plus and must match the Front-channel logout URL configured in the Okta application registration. When a front-channel logout GET request is received at this URI (typically in a hidden iframe), the OIDC module clears the local session for the affected user.
-
If the userinfo directive is set to
on, NGINX Plus will fetch/oauth2/default/v1/userinfofrom the Okta and append the claims from userinfo to the$oidc_claims_variables. -
PKCE (Proof Key for Code Exchange) is automatically enabled when the provider metadata advertises the
S256code challenge method in thecode_challenge_methods_supportedfield of the discovery document. You can override this behavior with thepkcedirective: setpkce off;to disable PKCE even whenS256is advertised, orpkce on;to force PKCE even if the IdP metadata does not listS256. -
The module automatically selects the client authentication method for the token endpoint based on the provider metadata
token_endpoint_auth_methods_supported. When onlyclient_secret_postis advertised, NGINX Plus uses theclient_secret_postmethod and sends the client credentials in the POST body. When bothclient_secret_basicandclient_secret_postare present, the module prefers HTTP Basic (client_secret_basic). -
ImportantAll 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_certificatedirective so that NGINX can validate and trust the IdP’s certificate.
nginx http { resolver 10.0.0.1 ipv4=on valid=300s; oidc_provider okta { issuer https://dev-123456.okta.com/oauth2/default; client_id <client_id>; client_secret <client_secret>; logout_uri /logout; post_logout_uri https://demo.example.com/post_logout/; logout_token_hint on; frontchannel_logout_uri /front_logout; userinfo on; # Optional: PKCE configuration. By default, PKCE is automatically # enabled when the IdP advertises the S256 code challenge method. # pkce on; } # ... } -
-
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:8080that is going to be OIDC-protected:nginx 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 Okta OIDC by specifying the
auth_oidcdirective that will point to theoktaconfiguration specified in theoidc_provider {}context in Step 5:nginx # ... location / { auth_oidc okta; # ... proxy_pass http://127.0.0.1:8080; } # ... -
Pass the OIDC claims as headers to the application (Step 10) with the
proxy_set_headerdirective. These claims are extracted from the ID token returned by Okta:-
$oidc_claim_sub- a uniqueSubjectidentifier assigned for each user by Okta -
$oidc_claim_emailthe e-mail address of the user -
$oidc_claim_name- the full name of the user -
any other OIDC claim using the
$oidc_claim_variable
nginx # ... location / { auth_oidc okta; 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:
nginx # ... location /post_logout/ { return 200 "You have been logged out.\n"; default_type text/plain; } # ... -
Create a simple test application referenced by the
proxy_passdirective which returns the authenticated user’s full name and email upon successful authentication:nginx # ... server { listen 8080; location / { return 200 "Hello, $http_name!\nEmail: $http_email\nOkta 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;
# Define the OIDC provider block for Okta
oidc_provider okta {
# The 'issuer' is your Okta issuer URL
# For okta dev it looks like: https://dev-123456.okta.com/oauth2/default
issuer https://dev-123456.okta.com/oauth2/default;
# Your Okta "Client ID" from the application settings
client_id <your_client_id>;
# Your Okta "Client Secret" from the application settings
client_secret <your_client_secret>;
# RP‑initiated logout
logout_uri /logout;
post_logout_uri https://demo.example.com/post_logout/;
logout_token_hint on;
# Front-channel logout (OP‑initiated single sign-out)
frontchannel_logout_uri /front_logout;
# Fetch userinfo claims
userinfo on;
# Optional: PKCE configuration
# pkce 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 / {
# Enforce OIDC authentication with Okta
auth_oidc okta;
# Pass OIDC claims as HTTP headers to the backend
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\nOkta sub: $http_sub\n";
default_type text/plain;
}
}
}-
Open
https://demo.example.com/in a browser. You will be automatically redirected to the Okta sign-in page. -
Enter valid Okta credentials of a user who has access the application. Upon successful sign-in, Okta 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; Okta ends the session and redirects back tohttps://demo.example.com/post_logout/. -
Refresh
https://demo.example.com/again. You should be redirected to Okta 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.
If you are running NGINX Plus R33 and earlier or if you still need the njs-based solution, refer to the Legacy njs-based Okta Guide for details. The solution uses the nginx-openid-connect GitHub repository and NGINX JavaScript files.
-
Version 3 (November 2025) – Updated for NGINX Plus R36; added front-channel logout support (
frontchannel_logout_uri), PKCE configuration (pkcedirective), and theclient_secret_posttoken endpoint authentication method. -
Version 2 (August 2025) – Updated for NGINX Plus R35; added RP‑initiated logout (
logout_uri,post_logout_uri,logout_token_hint) anduserinfosupport. -
Version 1 (March 2025) – Initial version (NGINX Plus Release 34).