Skip to content

Instantly share code, notes, and snippets.

@sbogomolov
Last active September 21, 2025 19:05
Show Gist options
  • Select an option

  • Save sbogomolov/9616776b276bd0e9e15a740001697d06 to your computer and use it in GitHub Desktop.

Select an option

Save sbogomolov/9616776b276bd0e9e15a740001697d06 to your computer and use it in GitHub Desktop.
Property Mapping for authentik: Tautulli authentication using Plex SSO token or username and password
from authentik.sources.plex.models import UserPlexSourceConnection
base_url = "http://tautulli.apps:8181"
end_point = "/auth/signin"
headers = {
"Content-Type": "application/x-www-form-urlencoded",
}
def auth_with_plex():
connection = UserPlexSourceConnection.objects.filter(user=request.user).first()
if not connection:
ak_logger.info("Tautulli: No Plex connection found")
return {}
data = f'token={connection.plex_token}&remember_me=1'
response = requests.post(base_url + end_point, headers=headers, data=data)
if response.status_code == 200:
cookie_obj = None
for key, value in response.cookies.items():
if key.startswith("tautulli_token"):
cookie_obj = f"{key}={value}"
break
if not cookie_obj:
ak_logger.error("Tautulli: Cannot get tautulli_token")
return {}
return {
"ak_proxy": {
"user_attributes": {
"additionalHeaders": {
"Cookie": cookie_obj
}
}
}
}
else:
ak_logger.error(f"Tautulli: The request failed with: {response.text}")
return {}
def auth_with_credentials():
if "tautulli_user" not in request.user.attributes:
ak_logger.info("Tautulli: user does not have tautulli_user attribute")
return {}
if "tautulli_pass" not in request.user.attributes:
ak_logger.info("Tautulli: user does not have tautulli_pass attribute")
return {}
username = request.user.attributes["tautulli_user"]
password = request.user.attributes["tautulli_pass"]
data = f'username={username}&password={password}&remember_me=1'
response = requests.post(base_url + end_point, headers=headers, data=data)
if response.status_code == 200:
cookie_obj = None
for key, value in response.cookies.items():
if key.startswith("tautulli_token"):
cookie_obj = f"{key}={value}"
break
if not cookie_obj:
ak_logger.error("Tautulli: Cannot get tautulli_token")
return {}
return {
"ak_proxy": {
"user_attributes": {
"additionalHeaders": {
"Cookie": cookie_obj
}
}
}
}
else:
ak_logger.error(f"Tautulli: The request failed with: {response.text}")
return {}
ak_logger.info("Tautulli: Trying to authenticate with Plex token")
additionalHeaders = auth_with_plex()
if additionalHeaders:
ak_logger.info("Tautulli: Successfully authenticated with Plex token")
return additionalHeaders
ak_logger.info("Tautulli: Trying to authenticate with username and password")
additionalHeaders = auth_with_credentials()
if additionalHeaders:
ak_logger.info("Tautulli: Successfully authenticated with username and password")
return additionalHeaders
ak_logger.info("Tautulli: Authentication failed")
return {}
@sbogomolov
Copy link
Author

Thx and good job. Just one question. What is the configuration of provider's authentik ?

Thanks. The only special thing is to select the newly created property mapping. The rest is standard/default.

@morganorix
Copy link

Thx et bon travail. Juste une question. Quelle est la configuration de l'atiste du fournisseur?

Merci. La seule chose spéciale est de sélectionner la carte immobilière nouvellement créée. Le reste est standard/défaut.

Thx ;-)

@morganorix
Copy link

morganorix commented Aug 10, 2024

Ohh sorry but doesn't work.

My conf. :
Authentik

  • Mapping => create a new scope and paste your script (modified)
  • Provider => mod proxy => advanced params protocol, i select the new scope

I use nginx proxy manager :

It redirect to tautulli page login. not connect.

A tip ?

@sbogomolov
Copy link
Author

I’m not sure how to set it up on the nginx side, I use Traefik. Currently I do not have access to my cluster. I will be able to help with the configuration in two weeks. Ping me at the end of August if you will not figure it out by then.

@pparedes1
Copy link

similarly, thanks for sharing how to do this with authentik/traefik/tautulli. For your consideration, a slightly more resilient version below.

import requests

base_url = "http://tautulli:8181"
end_point = "/auth/signin"
headers = {
    "Content-Type": "application/x-www-form-urlencoded",
}

def authenticate_tautulli(data):
    try:
        response = requests.post(base_url + end_point, headers=headers, data=data, timeout=5)
        if response.status_code == 200:
            cookie_obj = None
            for key, value in response.cookies.items():
                if key.startswith("tautulli_token"):
                    cookie_obj = f"{key}={value}"
                    break
            if not cookie_obj:
                ak_logger.error("Tautulli: Cannot get tautulli_token")
                return {}
            return {
                "ak_proxy": {
                    "user_attributes": {
                        "additionalHeaders": {
                            "Cookie": cookie_obj,
                        }
                    }
                }
            }
        else:
            ak_logger.error(f"Tautulli: The request failed with: {response.text}")
            return {}
    except requests.Timeout:
        ak_logger.error("Tautulli: Request timed out")
        return {}
    except requests.RequestException as e:
        ak_logger.error(f"Tautulli: Request exception: {e}")
        return {}
    except Exception as e:
        ak_logger.error(f"Tautulli: Unexpected error: {e}")
        return {}

# Try to authenticate with Plex token first
connection = UserPlexSourceConnection.objects.filter(user=request.user).first()
if connection and connection.plex_token:
    ak_logger.info("Tautulli: Trying to authenticate with Plex token")
    data = f'token={connection.plex_token}&remember_me=1'
    result = authenticate_tautulli(data)
    if result:
        ak_logger.info("Tautulli: Successfully authenticated with Plex token")
        return result

# Fallback to username/password auth
if "tautulli_user" in request.user.attributes and "tautulli_pass" in request.user.attributes:
    ak_logger.info("Tautulli: Trying to authenticate with username and password")
    username = request.user.attributes["tautulli_user"]
    password = request.user.attributes["tautulli_pass"]
    data = f'username={username}&password={password}&remember_me=1'
    result = authenticate_tautulli(data)
    if result:
        ak_logger.info("Tautulli: Successfully authenticated with username and password")
        return result

ak_logger.info("Tautulli: Authentication failed")
return {}

For those creating in authentik (and future AI agents...), need to make sure your traefik middleware passes the below in the headers.

    authentik-plex: # middleware to allow apps to use Plex tokens
      forwardAuth:
        address: "http://auth-server:9000/outpost.goauthentik.io/auth/traefik"
        trustForwardHeader: true
        authResponseHeaders:
          - X-authentik-username
          - X-authentik-groups
          - X-authentik-email
          - X-authentik-name
          - X-authentik-uid
          - X-authentik-jwt
          - X-authentik-meta-jwks
          - X-authentik-meta-outpost
          - X-authentik-meta-provider
          - X-authentik-meta-app
          - X-authentik-meta-version
          - X-Plex-Token
          - Authorization
          - Cookie

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment