Protecting your first app with Authentik. A no-fluff quick primer.

Authentik (https://goauthentik.io) is a very capable open source Identity Provider (idP software like Authelia, Okta, Keycloak etc.) which probably has the most features of any open source identify provider available. It’s also still under heavy development with stable releases being made every few weeks.

What we are trying to accomplish.

Identity providers are used for a variety of purposes almost all of which have to do with authentication (can I log in?) and authorization (what am I allowed to do?). They allow you to use Single Sign On (SSO) mechanisms like SAML and Oauth/OIDC as well as add one more layer of protection to your log in procedure by utilizing Two-Factor authentication (2FA) using hardware, software or SMS tokens.

Although there’s a lot of (solid) magic going on behind the scenes to make things easier, it’s relatively difficult initially to get started with an idP even when you pick one that is as user friendly as Authentik.

This short article is written to give the new user the small push necessary to get their first application under protection by authentik and give just enough info on the necessary concepts one needs to know. There won’t be anything else explained in great detail. I won’t pretend to hold your hand by giving out SEO friendly step by step instructions to install the software or anything like that. For more details I recommend the documentation which is simple but very dense. The project’s discord channel is pretty welcoming to newbies and depending on the time of day you can get almost instant help there as well.

The small subset of functionality we will look at is the minimum required to get one simple app without its own 2FA or SSO based security -or even no log in mechanism at all (private intranet page on the Internet etc)- to be protected by Authentik. There won’t be any SSO at this point, nor will we integrate with a web server or reverse proxy. I repeat. Your application will be protected, but you will have to log into it manually when you get to it.

How authentication works with authentik.

In very simple terms here’s what happens when you protect an application (a web site, web application etc) with authentik. A user goes to the url of the protected application on their web browser. Authentik is placed in a position to intercept this user’s connection request and directs the user to authentik’s own Log In screen. A registered user is then able to log in to Authentik with the username/email and password they were provided as well as any 2FA mechanism if any. When the user successfully logs in, Authentik sets a bunch of cookies and http headers which identify both that the user was authenticated and what their identity info such as name, username, group membership is. At this point all necessary data is in place to log into the desired application in a variety of ways, but we have not actually accessed the application yet.

Out of these many many ways to proceed we will concern ourselves with the absolute simplest. (Remember; simple is actually really hard to do - - this is the go code in Authentik talking.)

Using Authentik’s Embedded Proxy Provider.

Authentik comes with an embedded http (web) proxy written in go. It is set up and ready to go when Authentik is installed. In order to be able to protect a web resource with the proxy method at all, the app should not be open to public Internet in the first place. Otherwise we wouldn’t be able to intercept the incoming requests and protect the app. This is obvious but needs to be kept in mind. The usual way it’s done is to run the application on a private IP. One could set up firewall rules to disable direct access as well. The other obvious requirement is for Authentik to be able to access this application without hindrance. Please do your browser/network/routing testing accordingly before starting the configuration.

In this setup Authentik acts as a gatekeeper. As mentioned above, when an unauthenticated user comes in with a request, they are directed to the log in screen. If they are unable to log in, they won’t ever be able to access the protected application because there is no other way to get to the protected application. The neat thing about the embedded proxy provider that comes with Authentik is that it’s aware of both the user’s authentication status and the urls and routes necessary for proxying the connection without much extra configuration or the need for an extra network port. This allows authentik to present the user with its own log in screen when the users comes in unauthenticated but the application itself when authenticated, all by going to the same application URL. (i.e the user does not need to go to a log in portal first.)

So our gatekeeper looks at the user and says “OK. You can come in.” and directs the user to the application utilizing authentik itself as a reverse proxy. The destination application need not be aware that it is even being protected. As far it’s concerned a direct request is coming in albeit via a proxy server which most applications support because proxy use is already widespread on the Internet.

Putting our newfound knowledge into practice.

There are 3 interconnected pieces to every application that is proxy protected with Authentik.

  • An Application is a basic definition of the application including its name, url, icon etc. (This info is used in the very convenient Authentik application portal all users have access to.)

  • A Provider sets the required public and private URLs authentik needs to know about to be able to proxy the connection.

  • A proxy Outpost is the piece that provides the authentication service and takes care of proxying the connection.

An application will only work with authentik when its Application settings are associated with a Provider which in turn gets attached to a proxy Outpost. Most newcomers usually get lost juggling these three.

I recommend configuring the Provider first by going to Applications -> Providers since the Application page will ask you to select an existing Provider. Set a descriptive Name for your application and select the Authorization flow that has ‘explicit’ in its name. Let’s call the provider MyApp-Provider.

In the middle section of the configuration screen, make sure Proxy is selected and enter the External host address of your application. Let’s say our url is https://myapp.domain.com.

When a user enters this URL into their browser the connection needs to actually go to where Authentik is installed, not where your application is (that is a protected resource, not directly accessible remember?). You have to go to your DNS provider’s interface and point this domain to the correct IP address.

For the Internal host enter the url where authentik can reach the application. For this exercise let’s enter http://10.0.10.11:10100/. Note that this is a URL not a bare IP and a network port can be tacked on. In this particular case the site is running on http not https. Check from a network with access to this internal network using a desktop/mobile browser via vpn or a text browser on the actual host that the direct url works as expected without authentication. Authentik is very good but it can’t fix your broken app.

Leave everything else as is and move on to Applications -> Applications. Enter a Name for your application, and a slug. The slug can be anything. Let’s call them MyApp and myapp respectively. Next, find the Provider we’ve created above (MyApp-Provider) and select it. Leave the rest as is.

Finally go to Applications -> Outposts and click the Edit button next to authentik Embedded Outpost. Do not make any changes. Only select MyApp(https://myapp.domain.com) from the Applications list and click Update to save.

Enjoying your app.

If you’re testing right after following the above steps, you will already be logged in as an admin level user. To do a real test of how your users will experience the whole process, either use a different browser or log out of Authentik before your test.

Go to your web browser and enter https://myapp.domain.com to log into your application. You will be greeted by an authentik login screen. Once you’re successfully logged in Authentik will ask if you want to now go to the actual application. This step is there because we selected ‘explicit’ authentication flow in the provider settings. I like it for initial testing, but if you change it to the ‘implicit’ one you will be directed to the application destination automatically.

If all of this worked, congratulations. You’ve set up your first application in Authentik and it took you only 10 minutes instead of 4 hours and you didn’t even bother anybody while doing it. The next one will take even less time. Be advised; the process is quite addictive and you might find yourself installing applications you don’t even need.

The actual content of the article ends here. What follows is fluff.

Bonus round #1 (user access restrictions).

With the above default setup, all of your users will be able to access the protected application. If you would like to allow a subset of your users to access this application. go back to Applications -> Applications, find MyApp and click the name of the application - not the edit icon next to it. At the top. find and click the Policy/User/Group Bindings tab. Click the Create Binding button and select the User tab. Select the user you want to allow access to this app from the User dropdown and click Create. Repeat for more users.

This will do a peculiar thing. As soon as you add one or more users meaning to explicitly allow them, nobody else can access the app anymore. So the logic is this: Unless you specifically create a binding, your application is open to all of your users. As soon as you add a binding, this functionality flips and you have to maintain access restrictions yourself.

Note that there’s a Negate result checkbox within the user bindings screen. You can use this screen to add users you don’t want to access the app, which should be easier if you have a lot of users. There’s also a Group tab in the same screen which works on groups instead of users. I recommend adding your users in appropriate groups and using that if you need to provide custom access to apps to more than a few users. For instance you can create a group called MyApp_Group which contains only users that are allowed to access MyApp and add that group to your application with a binding.

Bonus round #2 (double proxying through a frontend web server or proxy).

If your authentik install is also on a Private IP and you don’t want to deal with port forwarding to allow public Internet users to access it, you can utilize a front end web server (or proxy-only software like Traefik) in reverse proxy mode. Keep in mind that all connections to the application will still also proxy through the embedded proxy outpost we’ve configured above. This setup will give you a bit more flexibility in your setup without a meaningful amount of a perfomance hit. It is especially useful if you are already taking care of your HTTPS certificates elsewhere. By terminating HTTPS on the frontend, you do not need to worry about it on the backend authentik side. We’re talking LetsEncrypt here and zerossl.

The only thing you might have trouble with here is conceptualizing which URL should point to what IP:port in the reverse proxy setup and DNS. It’s very simple. For authentication you have to pass users along to the Authentik server IP:port, and for proxying you pass users along to where the proxy outpost is and its port. Since the embedded proxy is called embedded for a reason, its IP and Port are the same as the former IP and Port.

So assuming your authentik URL is https://authentik.domain.com, you reverse proxy this url to point to the private IP and port of authentik, and you reverse proxy https://myapp.domain.com also to the private IP and port of authentik.

Here’s the Caddy web server configuration for the whole affair above. Authentik is sitting on 10.0.10.11:9010.


{   
    # letsencrypt and other global settings go here - for example:
        email dnsadmin@domain.com
        # this requires cloudflare dns plugin to be built into Caddy
        acme_dns cloudflare Skw_j5Rvb2S9T6VWs7lWRtB5rOpJz_L-2MwvVRKI  
}

# authentik 
authentik.domain.com {
    reverse_proxy 10.0.10.11:9010
}

# myapp
myapp.domain.com {
    reverse_proxy 10.0.10.11:9010
}

Note that both definitions reverse proxy to the same exact place and that we have not used MyApp’s actual internal location of http://10.0.10.11:10100/ at all. Authentik will take care of that bit when the request hits the embedded proxy. Don’t forget to point both domains' DNS to the public IP of the frontend web server.


2155 Words

2022-01-24 00:00 +0000