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.yaml
with 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-github2
andjsonwebtoken
packages:
npm install passport-github2 jsonwebtoken
- Create a new file called
auth.js
with 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.js
with 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
Authorization
header - 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!