I am running an Emby Server behind NginX Proxy Manager. Although Emby does not support SSO, I was still able to log in to the Web UI with the URL: schenme://emby.domain.com/web/index.html?userId=abc&accessToken=xxx&e=1
. This URI to authenticate into Emby can be generated in Authentik and the value can be passed after authentication. I need help doing that in NginX.
I will write the steps and method I used in case it was relevant.
In Authentik > Admin Interface > Directory > Users: Edit the desired users to add emby authentication. Simply add the following values in the Attributes section:
emby_password: ****
emby_username: abc
In Authentik > Admin Interface > Customization > Property Mappings and create a new Scope Maping. The Name will be “Emby Token” and the Scope Name ”ak_proxy”. The expression needs an API Token that you can get from Emby UI. Don’t forget to edit the URL so Authentik has access to Emby:
import json
from urllib.parse import urlencode
from urllib.request import Request, urlopen
if request.user.username == "":
return "null"
else:
embyuser = request.user.attributes.get("emby_username", "")
embypass = request.user.attributes.get("emby_password", "")
base_url = "http://embyserver:80"
end_point = "/Users/AuthenticateByName?api_key=xyz"
json_data = {'Username': embyuser,'Pw': embypass}
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())
AccessToken = responddata['AccessToken']
UserId = responddata['User']['Id']
except:
AccessToken = "null"
UserId = "null"
return {"ak_proxy": {"user_attributes": {"additionalHeaders": {"X-Emby-Uri": "/web/index.html?userId=" + UserId + "&accessToken=" + AccessToken + "&e=1"}}}}
If Authentik has access to Emby Server and the atribiuts to login are correctly provided, this scope should return /web/index.html?userId=abc&accessToken=xxx&e=1
that can be used to login.
After that I created an Aplication, Provider and added them to the Outpost. Authentication workes as intended.Trying to pass this value in NginX Proxy Manager as following is sadly not working:
client_max_body_size 100M;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Forwarded-Proto $scheme;
proxy_set_header Sec-WebSocket-Extensions $http_sec_websocket_extensions;
proxy_set_header Sec-WebSocket-Key $http_sec_websocket_key;
proxy_set_header Sec-WebSocket-Version $http_sec_websocket_version;
#proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_redirect off;
proxy_buffering off;
location / {
proxy_pass $forward_scheme://$server:$port;
}
location /ssoauth {
proxy_set_header Upgrade $http_upgrade;
auth_request /outpost.goauthentik.io/auth/nginx;
error_page 401 = gnin;
auth_request_set $auth_cookie $upstream_http_set_cookie;
add_header Set-Cookie $auth_cookie;
auth_request_set $authentik_embyuri $upstream_http_x_emby_uri;
rewrite ^ $authentik_embyuri;
proxy_pass $forward_scheme://$server:$port/;
}
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 gnin {
internal;
add_header Set-Cookie $auth_cookie;
return 302 /outpost.goauthentik.io/start?rd=$request_uri;
}
By going to schenme://emby.domain.com/ssoauth
I am promoted to login with Authentik. After authentication, the uri to login is loaded using auth_request_set $authentik_embyuri $upstream_http_x_emby_uri;
. Inspecting the value and testing it I am able to login. However, rewriting the uri from /SSO auto
into $authentik_embyuri
using rewrite ^ $authentik_embyuri;
is not working. Using return
bypass the Authentik login process and the login uri is not loaded.
I hope the endgoal and method are clear.
The question remains: how can I manager to redirect from /SSO auto
into the returned value of $authentik_embyuri
in NginX? Can I do this by overwriting the Location
header (trying this did not work)?
Each HTTP request passes through a sequence of request processing phases. Your rewrite
directive doesn't work properly because it is executed during the NGX_HTTP_REWRITE_PHASE
(as well as the return
directive), when the $authentik_embyuri
variable value hasn't been evaluated yet, since the auth_request
directive is executed during the later NGX_HTTP_ACCESS_PHASE
.
To achieve your goal, you need to return a redirect to the new URL after the NGX_HTTP_ACCESS_PHASE
is completed and the $authentik_embyuri
variable value has been evaluated. Nginx has a dedicated directive, internal_redirect
, to do this; unfortunately, it is available only as part of a commercial subscription. A typical way to achieve the same result using open-source nginx is to use the try_files
directive, which is executed during the even later NGX_HTTP_PRECONTENT_PHASE
(more details here).
Here is the configuration that might work for you (I moved one of the auth_request_set
directives since they should be declared along with the auth_request
directive and made several other adjustments):
location /ssoauth {
error_page 401 = gnin;
auth_request /outpost.goauthentik.io/auth/nginx;
auth_request_set $auth_cookie $upstream_http_set_cookie;
auth_request_set $authentik_embyuri $upstream_http_x_emby_uri;
try_files "" @redirect;
}
location /outpost.goauthentik.io {
internal;
proxy_pass https://authentik-server:9443;
proxy_set_header Host $host;
proxy_set_header X-Original-URL $scheme://$http_host$request_uri;
proxy_pass_request_body off;
proxy_set_header Content-Length "";
}
location @redirect {
add_header Set-Cookie $auth_cookie;
return 302 $authentik_embyuri;
}
location gnin {
internal;
add_header Set-Cookie $auth_cookie;
return 302 /outpost.goauthentik.io/start?rd=$request_uri;
}