Microsoft Entra

Configuration steps

The following steps are required to integrate MS Entra with Nara

Oauth2-proxy Configuration (MS Entra)

We have taken the example oauth2-configuration file from https://oauth2-proxy.github.io/oauth2-proxy/configuration/providers/ as a starting point.

## OAuth2 Proxy Config File
## https://github.com/oauth2-proxy/oauth2-proxy

## <addr>:<port> to listen on for HTTP/HTTPS clients
http_address = "127.0.0.1:4180"
https_address = ":443"

## Are we running behind a reverse proxy? Will not accept headers like X-Real-Ip unless this is set.
reverse_proxy = true

## TLS Settings
# tls_cert_file = ""
# tls_key_file = ""

## the OAuth Redirect URL.
# defaults to the "https://" + requested host header + "/oauth2/callback"
redirect_url = “https://example.com/oauth2/callback"

## the http url(s) of the upstream endpoint. If multiple, routing is based on path
# upstreams = [
#     "http://127.0.0.1:8080/"
# ]

## Logging configuration
#logging_filename = "/tmp/oauth2.log"
#logging_max_size = 100
#logging_max_age = 7
#logging_local_time = true
#logging_compress = false
#standard_logging = true
#standard_logging_format = "[{{.Timestamp}}] [{{.File}}] {{.Message}}"
#request_logging = true
#request_logging_format = "{{.Client}} - {{.Username}} [{{.Timestamp}}] {{.Host}} {{.RequestMethod}} {{.Upstream}} {{.RequestURI}} {{.Protocol}} {{.UserAgent}} {{.StatusCode}} {{.ResponseSize}} {{.RequestDuration}}"
#auth_logging = true
#auth_logging_format = "{{.Client}} - {{.Username}} [{{.Timestamp}}] [{{.Status}}] {{.Message}}"

## pass HTTP Basic Auth, X-Forwarded-User and X-Forwarded-Email information to upstream
pass_basic_auth = true
pass_user_headers = true
set_xauthrequest = true 
## pass the request Host Header to upstream
## when disabled the upstream Host is used as the Host Header
# pass_host_header = true

## Email Domains to allow authentication for (this authorizes any email on this domain)
## for more granular authorization use `authenticated_emails_file`
## To authorize any email addresses use "*"
email_domains = [ 
    "*" 
]

provider="entra-id"
#provider="oidc"
oidc_issuer_url=""
scope="openid email profile"
## The OAuth Client ID, Secret
client_id = ""
client_secret = ""

## Scopes Added to the request
## It has the same behavior as the --scope flag
# scope = "openid email"

## Pass OAuth Access token to upstream via "X-Forwarded-Access-Token"
#pass_access_token = true

## Authenticated Email Addresses File (one email per line)
# authenticated_emails_file = ""

## Htpasswd File (optional)
## Additionally authenticate against a htpasswd file. Entries must be created with "htpasswd -B" for bcrypt encryption
## enabling exposes a username/login signin form
# htpasswd_file = ""

## bypass authentication for requests that match the method & path. Format: method=path_regex OR path_regex alone for all methods
skip_auth_routes = [
  "GET=^/probe",
  "^/metrics"
]

## mark paths as API routes to get HTTP Status code 401 instead of redirect to login page
# api_routes = [
#   "^/api"
# ]

## Templates
## optional directory with custom sign_in.html and error.html
# custom_templates_dir = ""

## skip SSL checking for HTTPS requests
# ssl_insecure_skip_verify = false


## Cookie Settings
## Name     - the cookie name
## Secret   - the seed string for secure cookies; should be 16, 24, or 32 bytes
##            for use with an AES cipher when cookie_refresh or pass_access_token
##            is set
## Domain   - (optional) cookie domain to force cookies to (ie: .yourcompany.com)
## Expire   - (duration) expire timeframe for cookie
## Refresh  - (duration) refresh the cookie when duration has elapsed after cookie was initially set.
##            Should be less than cookie_expire; set to 0 to disable.
##            On refresh, OAuth token is re-validated.
##            (ie: 1h means tokens are refreshed on request 1hr+ after it was set)
## Secure   - secure cookies are only sent by the browser of a HTTPS connection (recommended)
## HttpOnly - httponly cookies are not readable by javascript (recommended)
cookie_name = "_oauth2_proxy"
cookie_secret = ""
# cookie_domains = ""
cookie_expire = "168h"
cookie_refresh = "1h"
cookie_secure = true
cookie_httponly = true

whitelist_domains = "login.microsoftonline.com"

Nginx Configuration (MS Entra)

We have taken the example nginx configuration file at https://oauth2-proxy.github.io/oauth2-proxy/configuration/integration as a starting point.

location /oauth2/ {
                proxy_pass       http://127.0.0.1:4180;
                proxy_set_header Host                    $host;
                proxy_set_header X-Real-IP               $remote_addr;
                proxy_set_header X-Auth-Request-Redirect $request_uri;
                # or, if you are handling multiple domains:
                # proxy_set_header X-Auth-Request-Redirect $scheme://$host$request_uri;
        }
        location = /oauth2/auth {
                proxy_pass       http://127.0.0.1:4180;
                proxy_set_header Host             $host;
                proxy_set_header X-Real-IP        $remote_addr;
                proxy_set_header X-Forwarded-Uri  $request_uri;
                # nginx auth_request includes headers but not body
                proxy_set_header Content-Length   "";
                proxy_pass_request_body           off;
        }

        location / {
                auth_request /oauth2/auth;
                error_page 401 =403 /oauth2/sign_in;

                # pass information via X-User and X-Email headers to backend,
                # requires running with --set-xauthrequest flag
                auth_request_set $user   $upstream_http_x_auth_request_user;
                auth_request_set $email  $upstream_http_x_auth_request_email;
                auth_request_set $groups  $upstream_http_x_auth_request_groups;
                auth_request_set $username $upstream_http_x_auth_request_preferred_username;
                proxy_set_header X-User  $user;
                proxy_set_header X-Email $email;
                proxy_set_header X-Groups $groups;
                proxy_set_header X-Preferred-Username $username;
                proxy_pass_request_headers on;

                # if you enabled --pass-access-token, this will pass the token to the backend
                auth_request_set $token  $upstream_http_x_auth_request_access_token;
                proxy_set_header X-Access-Token $token;

                # if you enabled --cookie-refresh, this is needed for it to work with auth_request
                auth_request_set $auth_cookie $upstream_http_set_cookie;
                add_header Set-Cookie $auth_cookie;

                # When using the --set-authorization-header flag, some provider's cookies can exceed the 4kb
                # limit and so the OAuth2 Proxy splits these into multiple parts.
                # Nginx normally only copies the first `Set-Cookie` header from the auth_request to the response,
                # so if your cookies are larger than 4kb, you will need to extract additional cookies manually.
                auth_request_set $auth_cookie_name_upstream_1 $upstream_cookie_auth_cookie_name_1;

                # Extract the Cookie attributes from the first Set-Cookie header and append them
                # to the second part ($upstream_cookie_* variables only contain the raw cookie content)
                if ($auth_cookie ~* "(; .*)") {
                        set $auth_cookie_name_0 $auth_cookie;
                        set $auth_cookie_name_1 "auth_cookie_name_1=$auth_cookie_name_upstream_1$1";
                }

                # Send both Set-Cookie headers now if there was a second part
                if ($auth_cookie_name_upstream_1) {
                        add_header Set-Cookie $auth_cookie_name_0;
                        add_header Set-Cookie $auth_cookie_name_1;
                }

                proxy_set_header Authorization $http_authorization;

                proxy_pass https://evija:443/;
        }
     	location ~ ^/(prod/gigl/\d+|nara/\d+/?$|nara/\d+/\d+|formats/gigl/\d+) {
                auth_request /oauth2/auth;
                proxy_http_version 1.1;
                proxy_set_header Upgrade $http_upgrade;
                proxy_set_header Connection "Upgrade";
                proxy_set_header Host $host;
                proxy_read_timeout 7d;
		    auth_request_set $username $upstream_http_x_auth_request_preferred_username;
    		    proxy_set_header X-Preferred-Username $username;
    		    proxy_pass_request_headers on;

    		    proxy_pass https://backend-nara/$1$is_args$args;
        }

Final Configuration (MS Entra)

To configure Nara:

  • Set the logout URL in the Nara configuration file at /usr/fl/etc/service.nara.cfg. This should be set to log out of oauth2-proxy, Entra and ideally to finally redirect back to the login page. Note that the logout URL will depend on your tenant id and can be found in the OIDC well known configuration page.

  • Also set the ENABLESSO variable to 1 to enable reading of the http headers by the Nara application.

Testing

In order to successfully integrate with Entra Nara requires that the proxy sets the X-Preferred-Username header after successfully authenticating. If this header is found, an entry will be written to the Nara access log at /usr/fl/log/nara.log which looks like:

6/3/2025, 12:55:01 PM : SSO Auth success for [email protected] Administrator

You can check whether oauth2-proxy is successfully setting this header by visiting eg example.com/oauth2/auth and examining the http headers.

Last updated