Setting Up Traefik Proxy on k3s with Forward Auth using Authorization Header Part 2
In Part 1, we covered the basics of setting up Traefik proxy on k3s and configuring forward authentication. Now, in part 2, we will deploy a sample application to Kubernetes and set up the callback URL on a Node.js Express app to handle the authentication response from GitHub.
Step 4: Configure Traefik
We will now configure Traefik to use our Node.js Express app as the authentication provider for our web application.
- Create a new Kubernetes Secret with the GitHub OAuth credentials:
kubectl create secret generic myapp-oauth \
--from-literal=client_id=<your-github-client-id> \
--from-literal=client_secret=<your-github-client-secret>
Replace <your-github-client-id> and <your-github-client-secret> with the actual values you obtained in step 2.
- Create a new Kubernetes ConfigMap with the Traefik configuration:
kubectl create configmap traefik-config \
--from-file=traefik.toml
In this case, traefik.toml is a file containing the Traefik configuration. Here’s an example configuration:
# traefik.toml
[http.middlewares.myapp-auth.forwardauth]
address = "http://myapp.mynamespace.svc.cluster.local:3000/auth/github"
authResponseHeaders = ["Authorization"]
[http.middlewares.myapp-auth.headers.customRequestHeaders]
Authorization = "Bearer ${http:middleware:myapp-auth.forwardauth}"
[http.routers.myapp]
rule = "Host(`myapp.example.com`)"
entryPoints = ["websecure"]
middlewares = ["myapp-auth"]
service = "myapp-service"
[http.services.myapp-service]
[http.services.myapp-service.loadBalancer]
passHostHeader = true
servers = [
{ url = "http://myapp.mynamespace.svc.cluster.local" }
]
In this configuration, we have defined a middleware called myapp-auth that uses the forwardauth plugin to forward authentication requests to our Node.js Express app. The authResponseHeaders option tells Traefik to include the Authorization header in the authentication response.
We have also defined a custom request header called Authorization that includes the access token returned by our Node.js Express app. This header will be added to all requests to the myapp service.
Finally, we have defined a router called myapp that listens for requests to the myapp.example.com hostname and uses the myapp-auth middleware. The router forwards requests to a Kubernetes service called myapp-service.
Note that you should replace myapp with the actual name of your application.
Once you have created the secret and the configmap, you can deploy Traefik to your Kubernetes cluster:
kubectl apply -f traefik.yaml
Replace traefik.yaml with the actual name of your Traefik deployment file.
Step 5: Deploy the Application
We are now ready to deploy our application to Kubernetes. Here’s how:
- Create a new file called
deployment.yamlwith the following contents:
apiVersion: apps/v1
kind: Deployment
metadata:
name: myapp
labels:
app: myapp
spec:
replicas: 1
selector:
matchLabels:
app: myapp
template:
metadata:
labels:
app: myapp
spec:
containers:
- name: myapp
image: myapp:latest
ports:
- containerPort: 3000
env:
- name: NODE_ENV
value: production
- name: PORT
value: "3000"
- name: CLIENT_ID
valueFrom:
secretKeyRef- Deploy the application to Kubernetes:
kubectl apply -f deployment.yaml
- Create a new Kubernetes Service for the application:
kubectl expose deployment myapp --port=80 --target-port=3000 --type=ClusterIP
- Create a new Kubernetes Ingress for the application:
apiVersion: networking.k8s.io/v1
kind: Ingress
metadata:
name: myapp
annotations:
kubernetes.io/ingress.class: traefik
cert-manager.io/cluster-issuer: letsencrypt-prod
spec:
tls:
- hosts:
- myapp.example.com
secretName: myapp-tls
rules:
- host: myapp.example.com
http:
paths:
- path: /
pathType: Prefix
backend:
service:
name: myapp
port:
name: http
In this Ingress configuration, we are using the traefik ingress class to route traffic to our application. We are also using the letsencrypt-prod cluster issuer to automatically obtain a TLS certificate from Let’s Encrypt.
Replace myapp.example.com with the actual hostname of your application.
Once you have deployed your application, you should be able to access it by visiting https://myapp.example.com in your web browser.
Step 6: Implement the Callback URL on Node.js Express
Finally, we need to implement the callback URL on our Node.js Express app to handle the authentication response from GitHub.
- Install the
passport-github2andjsonwebtokenpackages:
npm install passport-github2 jsonwebtoken
- Create a new file called
auth.jswith the following contents:
const passport = require('passport');
const { Strategy: GitHubStrategy } = require('passport-github2');
const jwt = require('jsonwebtoken');
const clientID = process.env.CLIENT_ID;
const clientSecret = process.env.CLIENT_SECRET;
const jwtSecret = process.env.JWT_SECRET;
passport.use(new GitHubStrategy({
clientID,
clientSecret,
callbackURL: '/auth/github/callback'
}, (accessToken, refreshToken, profile, done) => {
const jwtPayload = {
id: profile.id,
username: profile.username
};
const jwtToken = jwt.sign(jwtPayload, jwtSecret, { expiresIn: '1h' });
return done(null, { jwtToken });
}));
module.exports = passport;
In this file, we are using the passport-github2 package to handle the authentication with GitHub. We are also using the jsonwebtoken package to create a JWT token with the user’s ID and username.
Replace jwtSecret with a secret key for signing the JWT token.
- Create a new file called
index.jswith the following contents:
const express = require('express');
const session = require('express-session');
const auth = require('./auth');
const app = express();
const port = process.env.PORT || 3000;
app.use(session({
secret: 'my-secret',
resave: false,
saveUninitialized: false
}));
app.use(auth.initialize());
app.use(auth.session());
app.get('/', (req, res) => {
res.send('Hello World!');
});
app.get('/auth/github', auth.authenticate('github'));
app.get('/auth/github/callback', auth.authenticate('github', { failureRedirect: '/login' }), (req, res) => {
res.redirect('/');
});
app.listen(port, () => {
console.log(`App listening at http://localhost:${port}`);
});
In this file, we are using the express package to create an HTTP server. We are also using the express-session package to handle sessions.
We are initializing passport using the auth module that we created in auth.js. We are also using the session middleware to enable session support.
We have defined three routes:
/: This is the default route that displays a “Hello World!” message./auth/github: This route redirects the user to GitHub for authentication./auth/github/callback: This route handles the authentication response from GitHub.
When the user visits the /auth/github route, they will be redirected to the GitHub authentication page. After the user has authenticated with GitHub, they will be redirected to the /auth/github/callback route.
In the callback route, we are using the auth.authenticate middleware to handle the authentication response from GitHub. If the authentication is successful, we will redirect the user to the default route.
- Start the Node.js Express app:
npm start
You should now be able to visit http://localhost:3000 in your web browser and see the “Hello World!” message. When you visit http://localhost:3000/auth/github, you should be redirected to GitHub for authentication. After you have authenticated with GitHub, you should be redirected back to http://localhost:3000 and see the “Hello World!” message again.
Congratulations! You have successfully set up Traefik proxy on k3s with forward auth using the Authorization header, deployed a sample application to Kubernetes, and implemented the callback URL on a Node.js Express app to handle the authentication response from GitHub.
Conclusion
Traefik proxy is a powerful tool for managing and routing traffic in a Kubernetes cluster. By setting up forward authentication with the Authorization header, you can add an extra layer of security to your applications and ensure that only authorized users can access them.
In this tutorial, we covered the following:
- Setting up Traefik proxy on k3s
- Configuring forward authentication with the
Authorizationheader - Deploying a sample application to Kubernetes
- Implementing the callback URL on a Node.js Express app to handle the authentication response from GitHub
I hope this tutorial has been helpful in getting you started with Traefik proxy and forward authentication. Happy coding!