TLDR; If you end up on this page, you probably realize that configuring domain-level Forward Auth from Traefik in K3S with Authentik 2024.2.2 is not easy. I show here how to do it.
Authentik is a popular identity provider which can be used in various authentication and authorisation flows. You can get more information about it on https://goauthentik.io/. There is a big list of possible integrations with known services, such as Portainer and Jenkins.
The other feature of Authentik is more interesting. It provides a capability to protect web-services from unauthorized access, even if these services do not support it originally. This is achieved by intercepting incoming requests and testing if they contain a proper http-header. In case no such header is found, the request is redirected to a login page of Authentik.
It sounds great and doable. There are plenty of resources describing the configuration process. Unfortunately, I did not find a solution for K3S with Traefik. Getting it work cost me a lot of time and patience. The official documentation does not describe this case. So I would like to share this knowledge.
To be on the same page, here are the prerequisites:
1. Your instance of Authentik is deployed at https://authentik.domain1
2. The service you would like to protect is deployed in a K3S and available at https://service.domain2
3. A future Authentik Outpost will be accessible at https://outpost.domain3
.
Please note, that domain1
, domain2
and domain3
do not need to be different. They all can use 1 domain and be deployed in the same K3S cluster.
First of all, we install an Authentik Outpost using a helm chart from https://artifacthub.io/packages/helm/goauthentik/authentik-remote-cluster. The installation process ends with a kube-config. This config is reqiured to create an outpost integration in Authentik.
![](https://artur.rocks/content/images/2024/04/Screenshot-2024-04-14-at-19.03.50.png)
Later, you can use the integration to create an outpost for an app of your choice. The created outpost will automatically trigger a new ghcr.io/goauthentik/proxy
deployment in the cluster which will connect to Authentik.
Here is a catch! The outpost needs to be exposed at https://outpost.domain3
. There is a ping endpoint which must be testable via:curl -i https://outpost.domain3/outpost.goauthentik.io/ping
. A correct response contains HTTP/2 204
. One way to expose the outpost is using Ingress:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: outpost-ingress
spec:
ingressClassName: traefik
rules:
- host: outpost.domain3
http:
paths:
- backend:
service:
name: ak-outpost
port:
number: 9000
path: /
pathType: Prefix
Finally, the target web-service needs to be re-configured to use the following Traefik Middleware with the exposed outpost:
apiVersion: traefik.containo.us/v1alpha1
kind: Middleware
metadata:
name: authentik
spec:
forwardAuth:
address: https://outpost.domain3/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
The target web-service can be exposed via:
---
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: whoami-ingress
annotations:
traefik.ingress.kubernetes.io/router.middlewares: default-authentik@kubernetescrd
spec:
ingressClassName: traefik
rules:
- host: https://service.domain2
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: whoami
port:
number: 80
This configuration works for domain-level forward auth, where an auth cookie is set for the whole domain2
and all services within the domain, e.g. service2.domain2
.
Single app forward auth is also possible, but needs changes to Ingress. Let me know if you are interested.