# \*\*\*Guide\*\*\* For Setting up Unraid web GUI access after authentication with Authentik

**URL:** <https://forum.hhf.technology/t/guide-for-setting-up-unraid-web-gui-access-after-authentication-with-authentik/156>\
**Category:** Tutorials\
**Tags:** authentik, unraid, security\
**Created:** [February 2, 2024, 1:18pm UTC](https://forum.hhf.technology/t/guide-for-setting-up-unraid-web-gui-access-after-authentication-with-authentik/156 "2024-02-02T13:18:00Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

**Author:** ![hhf.technoloy](https://forum.hhf.technology/user_avatar/forum.hhf.technology/hhf.technoloy/32/68_2.png) [@hhf.technoloy](https://forum.hhf.technology/u/hhf.technoloy)\
**Post date:** [February 2, 2024, 1:18pm UTC](https://forum.hhf.technology/t/guide-for-setting-up-unraid-web-gui-access-after-authentication-with-authentik/156/1 "2024-02-02T13:18:00Z")

</div>

# Secure the Unraid GUI behind Authentik

## Assumptions

1. You are using forward authentication behind a reverse proxy
2. The internal host for Unraid does not use HTTPS
3. The only user allowed for the Unraid web GUI is `root`
4. The password for Unraid is stored as a user attribute
  1. The attribute _can_ come from a group to which the user belongs

## Instructions

1. In Authentik create a new _Scope Mapping_
  1. The _Name_ can be whatever you would like
  2. The _Scope name_ **MUST** be `ak_proxy`
  3. Copy the contents of `unraid_scope_mapping.py` into the _Expression_ field

2. Update the “Important Variables” section of the _Expression_ field
  1. Set `internal_host` to the domain or IP address of your Unraid instance
    1. If the Unraid web GUI isn’t using the default HTTP port, make sure you specify it

  2. Set `external_host` to your Unraid domain name

3. Create a new _Provider_ of type _Proxy Provider_ named “Unraid”
  1. Set it to “Forward auth (single application)”
  2. Fill in the _External host_ field to match the external host specified above
  3. Under _Advanced protocol settings \> Additional scopes_ make sure that you select the scope that you created in the first step

4. Create a new _Application_ and attach the _Provider_ to the _Application_
5. Attach the new _Application_ to the _Outpost_ of your choice
6. Follow the Authentik instructions for setting up your reverse proxy using forward authentication

**unraid\_scope\_mapping.py**

```py
###############################################################################
##### Important Variables #####################################################
###############################################################################
# Set this to your internal Unraid domain or IP
# Include the port if necessary
internal_host = "unraid.internal"

# Set this to your external Unraid domain
external_host = "unraid.external"

# This is the attribute the password is stored in on the user
password_attribute = "unraid_password"
###############################################################################

import hashlib

# Check if the user has the password attribute
# My users inherit it from the group "Unraid Admins"
all_attributes = request.user.group_attributes()

if password_attribute not in all_attributes:
    ak_logger.info(f"user does not have the {password_attribute} attribute")
    return {}

# As far as I know, this is the only valid username for Unraid
unraid_username = "root"

# Get the Unraid password from the attributes
unraid_password = all_attributes[password_attribute]

# Build the URI for the internal Unraid login page
unraid_uri = f"http://{internal_host}/login"

# Login to Unraid
response = requests.post(
    unraid_uri,
    data={
        "username": unraid_username,
        "password": unraid_password,
    },
    allow_redirects=False, # It's important to not follow redirects
)

# Unraid returns a redirect to the main page when successful
if response.status_code != 302:
    ak_logger.error(f"the request failed with: {response.text}")
    return {}

# Look for the Unraid cookie
# The Unraid cookie format is "unraid_{md5(server_name)}" so we can't just copy
# it directly
for key, value in response.cookies.items():
    if key.startswith("unraid_"):
        ak_logger.info(f"found cookie '{key}'; creating new cookie for host '{external_host}'")

        # The session for the browser won't match the internal site, so we have
        # to create a new key for our cookie
        host_hash = hashlib.md5(external_host.encode()).hexdigest()
        cookie = f"unraid_{host_hash}={value}; path=/; HttpOnly; SameSite=Lax"

        # Add a header to set this new cookie in the response to the browser
        return {
            "ak_proxy": {
                "user_attributes": {
                    "additionalHeaders": {
                        "Set-Cookie": cookie,
                    }
                }
            }
        }

# Something went wrong if the login succeeded but the cookie is missing
ak_logger.error("cannot get unraid token")
return {}

```
