Authentik: Single Sign-On for Your Self-Hosted Apps (Forward Auth and OAuth2)
Video
Transcript
Hello, this is the channel Easy Self Host.
In this video, we are going to run Authentik, the all-in-one authentication server that can act as the single sign-on for our self-hosted applications.
Authentik supports multiple authentication methods such as Forward Auth, OAuth, LDAP and many more.
In this video, I'll show you the most commonly used methods in self-hosted applications: Forward Auth and OAuth.
Forward Auth is a straightforward concept.
In this method, our proxy servers, such as NGINX or Caddy, work with Authentik to secure requests to the applications.
Before we sign in, the proxy server directs us to the Authentik site.
After signing in, the proxy server forwards the requests directly to the applications, embedding details like usernames in the HTTP headers.
The applications can rely on these headers to identify our account.
This method can also safeguard applications that lack native sign-in capabilities.
OAuth is an open standard for access delegation, commonly used to allow one application to access information in another one.
It is often used for "Login with X" features.
Authentik can serve as an OAuth provider, allowing other self-hosted applications to offer a "Log in with Authentik" option.
In this setup, the applications request your permission to access your profile on the Authentik app by having you sign in and authorize the access.
Following this, Authentik redirects you back to the application with a code to access your profile, enabling the application to sign in your account.
Now letās begin setting up the Authentik app itself.
Here is the Docker Compose file for the Authentik.
First, we declare the proxy-net Docker network, which we will use to connect our proxy server and the Authentik service.
Next, we define a list of Docker volumes to persist data from Authentik, such as database data, media files, and certificates.
We will see how these are mounted in the service section.
In the services section, we have four services: the PostgreSQL database, the Redis cache server, the Authentik web server, and a worker service for background tasks.
For the Postgres database, we use the official Postgres image.
For volumes, we mount the database volume to the data path of Postgres to persist the DB data.
In the environment section, we first configure the Postgres password.
The password is set through the .env file, allowing us to share the value with the Authentik services.
Then we set the username and the DB name to authentik.
In the Redis service, we also use the official image.
We can mount the Redis volume to persist its states between restarts.
Next is the Authentik server.
We use the official image published by the Authentik team with the version specified.
For applications like this, it's good practice to specify the version to avoid unintentional upgrades, as breaking changes could impact many other applications.
Here, we have a command to start the server instead of the worker.
In the environment section, we configure the Redis and Postgres hosts, with host names matching the service names in this Docker Compose file.
The next three environments configure the Postgres user, database name, and password.
Note that the password is referring to the same variable in the .env file as the Postgres service.
We also have an environment to set the secret key, which is specified in the .env file.
In the network section, we assign two networks to this container.
The proxy-net network connects this service to the proxy server, while the default network connects it to the other services in the Docker Compose.
In the expose section, we document the port 9000 for the web server.
For the volumes, we mount two volumes to persist media files and templates.
Finally, we specify that the server depends on Postgres and Redis so that it will start after those services.
The worker service uses the same image as the server, but with a different command.
The rest of the configuration is similar to the server, except that the worker doesnāt need to attach to the proxy network.
And the worker mount an additional certs volume for persisting certificates.
We also need to update our proxy server configuration to assign a domain name for Authentik.
Iām using Caddy, so I'll create a Caddy rule to proxy the domain authentik.home.easyselfhost.com to the authentik-server service at port 9000.
Now letās move to our server command line to deploy this Docker Compose.
Navigate to the directory containing the Docker Compose file and execute docker compose up -d.
Additionally, we need to refresh the proxy configuration.
Iāll restart my Caddy server to apply the changes.
After this, Authentik will be up and running.
To set up the admin user, navigate to the URL starting with your server domain and then add path /if/flow/initial-setup.
Here we can set up the email and password of the admin user.
Then we are on the Authentik web page.
Letās go to the Admin Interface to start our configuration.
In this video, weāll focus on creating logins for our self-hosted apps.
The first thing we need to do is to create users.
Letās navigate to the Directory section and enter the Users setting.
Here, we can create a new non-admin user by assigning an username and entering an email address.
We have the option to configure the mail server to send a sign-up email.
Alternatively, we can directly assign a password for this user by selecting the user, scrolling down, and clicking āSet passwordā.
After we have a user, we can start integrating with apps.
Letās start with a simple utility app that lacks any sign-in mechanismāStirling PDF.
Our goal is to secure this app so that it requires logging in, and we'll use Forward Auth to achieve this.
In the Authentik Admin Interface, go to the Applications section and click 'Create With Wizard'.
Letās name the application āStirling PDFā.
And in the UI setting, specify its launch URL: https://pdf.home.easyselfhost.com.
In the next step, we need to choose the Provider Type.
Here, select āForward Auth (Single Application)ā, and click Next.
For the Authentication flow and Authorization flow, choose the default options.
The External host is the URL of our application.
Then letās click Submit.
Thereās one more step on the Authentik panel.
Letās go to the Outposts tab, click on the Embedded Outpost, select the Stirling PDF app, and click Update.
This action will activate our application settings.
Forward auth requires support from the proxy server, so we need to update our proxy configuration.
Here, I'll show you how to do this in Caddy.
Other proxies like NGINX or Traefik also support forward auth, and you can find configuration guides on the Authentik website.
In the Caddyfile, I added a snippet for using forward auth with Authentik.
This snippet can be reused for each app that we want to secure with Authentik.
It does two things:
First, it proxies a path, /outpost.goauthentik.io, from the app domain to the Authentik server.
Then, it includes a forward_auth directive that targets the Authentik server.
This directive specifies the URI for authentication, sets headers as defined by Authentik, and identifies the trusted proxy to only allow private IPs.
For the Stirling PDF's proxy rule, we simply need to add 'import authenticate' before the reverse_proxy directive.
Now, let's go to our server command line and refresh our proxy configuration.
After updating our proxy configuration, we can open a browser and navigate to the domain for Stirling PDF.
You'll see that it redirects us to the Authentik site, prompting us to log in to Stirling PDF.
Letās log in using the non-admin user we just created.
Once logged in, we'll be back in the Stirling PDF app, just like before.
Now, let's integrate with an app that supports both native logins and Forward Auth.
Paperless-ngx is one such app.
If you're interested, you can check out my video about Paperless-ngx.
According to its documentation, it has an environment configuration to enable Forward Auth.
And it recognizes users through the Remote-User HTTP header.
So, letās add this environment variable in the Docker Compose file for Paperless-ngx.
In the proxy configuration, we can reuse our existing snippet by simply adding 'import authenticate' in the Paperless Caddy rule.
However, thereās an additional step: we need to populate the Remote-User HTTP header.
Authentik defaults to using the X-Authentik-Username header for usernames.
Resources
- https://github.com/easyselfhost/self-host/tree/main/apps/authentik
- https://github.com/easyselfhost/self-host/blob/main/apps/caddy/Caddyfile
- https://goauthentik.io
- https://docs.goauthentik.io/docs/providers/proxy/forward_auth
- https://youtu.be/HWfWRZSZ8YM
- https://youtu.be/h_inF-ypMls
- https://youtu.be/KPp3bJK81n4