nginx-proxy-manager icon indicating copy to clipboard operation
nginx-proxy-manager copied to clipboard

How to pass the JWT Token for web authentication after v2.13.1?

Open moutasem1989 opened this issue 1 month ago • 8 comments

Since there is no OIDC/SSO Authentication yet, I use Authentik Proxy Authentication to sign into NPM Web UI.

In Authentik group Attributes I added

nginx_username: [email protected]
nginx_password: changeme

Attributes can be also added to individual users. The Property Mapping Expression must be adjusted accordingly.

Then created a Property Mappings for NginX to obtain the JWT Token from NPM API: Name: NginX Token Scope Name: ak_proxy Expression:

import json
from urllib.parse import urlencode
from urllib.request import Request, urlopen

if request.user.username == "":
  return {"ak_proxy": {"user_attributes": {"additionalHeaders": {"X-Nginx-Token": "null"}}}}
else:
  nginxuser = request.user.group_attributes().get("nginx_username", "")
  nginxpass = request.user.group_attributes().get("nginx_password", "")

base_url = "http://nginx:81"
end_point = "/api/tokens"
json_data = {'identity': nginxuser,'secret': nginxpass}
postdata = json.dumps(json_data).encode()
headers = {"Content-Type": "application/json; charset=UTF-8"}
try:
  httprequest = Request(base_url + end_point, data=postdata, method="POST", headers=headers)
  with urlopen(httprequest) as response:
    responddata = json.loads(response.read().decode())
  return {"ak_proxy": {"user_attributes": {"additionalHeaders": {"X-Nginx-Token": responddata['token']}}}}
except: return {"ak_proxy": {"user_attributes": {"additionalHeaders": {"X-Nginx-Token": "null"}}}}

Create Authentik Application and Proxy Provider for NPM. Make sure to add the application to Authentik Outpost. Add NginX Token to Selected Scopes.

In NPM Proxy Host, I had this configuration:

proxy_buffers 8 16k;
proxy_buffer_size 32k;
port_in_redirect off;

location = /login {
  return 301 /;
}

location / {
    proxy_pass          $forward_scheme://$server:$port;
    auth_request     /outpost.goauthentik.io/auth/nginx;
    error_page       401 = @goauthentik_proxy_signin;
    auth_request_set $auth_cookie $upstream_http_set_cookie;
    add_header       Set-Cookie $auth_cookie;

    auth_request_set $authentik_auth $upstream_http_x_nginx_token;
    proxy_set_header Authorization "Bearer ${authentik_auth}";
    proxy_pass_header Authorization;
}

location /outpost.goauthentik.io {
    proxy_pass              https://authentik-server:9443/outpost.goauthentik.io;
    proxy_set_header        Host $host;
    proxy_set_header        X-Original-URL $scheme://$http_host$request_uri;
    add_header              Set-Cookie $auth_cookie;
    auth_request_set        $auth_cookie $upstream_http_set_cookie;
    proxy_pass_request_body off;
    proxy_set_header        Content-Length "";
}

location @goauthentik_proxy_signin {
    internal;
    add_header Set-Cookie $auth_cookie;
    return 302 /outpost.goauthentik.io/start?rd=$request_uri;
}

This part fetches the JWT Token from Authentik Scope and passes it as a header:

    auth_request_set $authentik_auth $upstream_http_x_nginx_token;
    proxy_set_header Authorization "Bearer ${authentik_auth}";
    proxy_pass_header Authorization;

Up to v2.13.1 this worked smoothly. I would like to know if it is still possible to use JWT Token to authenticate into the WebUI. I am not using NPM in production settings or publicly exposed, but I am constantly experimenting with it for learning purposes.

moutasem1989 avatar Nov 07 '25 09:11 moutasem1989

Does this work under v2.13.1? Would you describe the steps in detail? Or is there a URL where this is described? Thanks in advance for your help!

GyimPet avatar Nov 07 '25 18:11 GyimPet

Yes this worked under v2.13.1. Steps for Both Authentik and NPX are described in the issue above.

moutasem1989 avatar Nov 08 '25 15:11 moutasem1989

Can you provide more detailed instructions if necessary?

Does this mean that npm.domain.de redirects directly to authentik and after logging in, you are logged into NPM?

lastsamurai26 avatar Nov 10 '25 06:11 lastsamurai26

NPX credentials are stored in Authentik Attributes. When going to npm.domain.de i am redirected to Authentik login page. After logging in, i am then redirected to NPM main dashboard. Because a fresh JWT token is fetched by Authentik and only after authentication is passed as header to npm.domain.de, NPM thinks a login session is still valid. This means login once into Authentik allows me to login to all apps that use it.

moutasem1989 avatar Nov 10 '25 06:11 moutasem1989

The title of this says "after v2.13.1" - are you having problems using the /api/tokens endpoint in 2.13.2?

I ask because I've made no changes to the API - especially this endpoint - in 2.13

jc21 avatar Nov 11 '25 04:11 jc21

Apologies for any misunderstanding. In the new web UI i am still able to fetch a token using Authentik and pass it into Authorization header after loging into Authentik. API endpoints did not change. In the new web UI is even when a valid token is passed in Authorization header, i am no longer redirect to NPM dashboard. Logging in using JWT token in Authorization header is not working after v2.13.1.

My question was: With the new frontend, is it still possible somehow to login into NPM dashboard using a JWT Token?

moutasem1989 avatar Nov 11 '25 06:11 moutasem1989

I’ve encountered the same problem.

In my setup, I previously worked around the missing OIDC support (PR #2630) by using an external authentication proxy in front of Nginx Proxy Manager. This setup worked fine up until version v2.13.1, but it stopped working after upgrading beyond that.

xsustek avatar Nov 11 '25 06:11 xsustek

I believe the root cause of this issue might be related to how the authentication state is determined in the frontend.

In Router.tsx, the authenticated variable depends on the token value stored in localStorage. This token is set and read through AuthStore.ts and the AuthContext.

However, in setups where authentication is handled via an auth proxy, the token is not persisted in the browser’s localStorage — it’s attached dynamically to each proxied request instead. As a result, the frontend incorrectly assumes the user is unauthenticated even though the backend authenticates every request.

xsustek avatar Nov 11 '25 20:11 xsustek