Configure basic authentication
This guide introduces how to configure basic authentication for your applications using the AuthenticationFilter CRD.
Authentication is crucial for modern application security and allows you to be confident that only trusted and authorized users are accessing your applications, or API backends.
Through this document, you’ll learn how to protect your application endpoints with NGINX Gateway Fabric using the AuthenticationFilter CRD.
In this guide we will create two sample applications, tea and coffee, where we will enable basic authentication on the /coffee endpoint. The /tea endpoint will not have any authentication. This is to help demonstrate how the application behaves both with and without authentication.
The /coffee endpoint will use the ExtensionRef filter to reference an AuthenticationFilter CRD which is configured for Basic Authentication.
- Install NGINX Gateway Fabric.
To deploy both the coffee and tea applications, copy the following YAML into your terminal:
kubectl apply -f - <<EOF
apiVersion: apps/v1
kind: Deployment
metadata:
name: coffee
spec:
replicas: 2
selector:
matchLabels:
app: coffee
template:
metadata:
labels:
app: coffee
spec:
containers:
- name: coffee
image: nginxdemos/nginx-hello:plain-text
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: coffee
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
selector:
app: coffee
---
apiVersion: apps/v1
kind: Deployment
metadata:
name: tea
spec:
replicas: 2
selector:
matchLabels:
app: tea
template:
metadata:
labels:
app: tea
spec:
containers:
- name: tea
image: nginxdemos/nginx-hello:plain-text
ports:
- containerPort: 8080
---
apiVersion: v1
kind: Service
metadata:
name: tea
spec:
ports:
- port: 80
targetPort: 8080
protocol: TCP
name: http
selector:
app: tea
EOFConfirm that the Pods are running
kubectl get podsNAME READY STATUS RESTARTS AGE
coffee-654ddf664b-fllj7 1/1 Running 0 21s
coffee-654ddf664b-lpgq9 1/1 Running 0 21s
tea-75bc9f4b6d-cx2jl 1/1 Running 0 21s
tea-75bc9f4b6d-s99jz 1/1 Running 0 21sTo create your gateway resource, and provision the NGINX pod, copy the following YAML into your terminal:
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: Gateway
metadata:
name: cafe-gateway
spec:
gatewayClassName: nginx
listeners:
- name: http
port: 80
protocol: HTTP
hostname: "cafe.example.com"
EOFAfter creating the Gateway resource, NGINX Gateway Fabric will provision an NGINX Pod and Service fronting it to route traffic. Verify the gateway is created:
kubectl get gateways.gateway.networking.k8s.io cafe-gatewayNAME CLASS ADDRESS PROGRAMMED AGE
cafe-gateway nginx 10.96.187.113 True 10mSave the public IP address and port of the NGINX Service into shell variables:
GW_IP=XXX.YYY.ZZZ.III
GW_PORT=<port number>Deploy secret with user credentials, and the AuthenticationFilter.
ImportantEnsure the secret deployed is of typenginx.org/htpasswdand the key isauth
kubectl apply -f - <<EOF
apiVersion: v1
kind: Secret
metadata:
name: basic-auth
type: nginx.org/htpasswd
data:
# Base64 of output from: htpasswd -bn user1 password1
auth: dXNlcjE6JGFwcjEkWEFKeU5yekgkY0Rjdy9YMVBCZTFmTjltQVBweXpxMA==
---
apiVersion: gateway.nginx.org/v1alpha1
kind: AuthenticationFilter
metadata:
name: basic-auth
spec:
type: Basic
basic:
secretRef:
name: basic-auth
realm: "Restricted basic-auth"
EOFVerify the AuthenticationFilter is Accepted, and there are no errors:
kubectl describe authenticationfilters.gateway.nginx.org | grep "Status:" -A10Status:
Controllers:
Conditions:
Last Transition Time: 2026-01-08T10:09:18Z
Message: The AuthenticationFilter is accepted
Observed Generation: 1
Reason: Accepted
Status: True
Type: Accepted
Controller Name: gateway.nginx.org/nginx-gateway-controller
Events: <none>Deploy an HTTPRoute which references the AuthenticationFilter. This uses the ExtensionRef filter type. In this example, we set this filter to the /coffee path:
kubectl apply -f - <<EOF
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
name: cafe-routes
spec:
parentRefs:
- name: cafe-gateway
rules:
- matches:
# Coffee configured with Basic Auth
- path:
type: PathPrefix
value: /coffee
backendRefs:
- name: coffee
port: 80
filters:
- type: ExtensionRef
extensionRef:
group: gateway.nginx.org
kind: AuthenticationFilter
name: basic-auth
- matches:
# Tea with no authentication configured
- path:
type: PathPrefix
value: /tea
backendRefs:
- name: tea
port: 80
EOFVerify the HTTPRoute is Accepted, and there are no errors:
kubectl describe httproute cafe-routes | grep "Status:" -A10Status:
Parents:
Conditions:
Last Transition Time: 2026-01-06T15:18:55Z
Message: The Route is accepted
Observed Generation: 1
Reason: Accepted
Status: True
Type: Accepted
Last Transition Time: 2026-01-06T15:18:55Z
Message: All references are resolved
Observed Generation: 1
Reason: ResolvedRefs
Status: True
Type: ResolvedRefs
Controller Name: gateway.nginx.org/nginx-gateway-controller
Parent Ref:
Group: gateway.networking.k8s.io
Kind: Gateway
Name: cafe-gateway
Namespace: default
Section Name: http
Events: <none>Your clients should be able to resolve the domain name "cafe.example.com" to the public IP of the NGINX Service. In this guide we will simulate that using curl’s--resolveoption.
Accessing /coffee with valid credentials:
curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/coffee -u user1:password1Response:
Server address: 10.244.0.7:8080
Server name: coffee-654ddf664b-nhhvr
Date: 06/Jan/2026:15:20:15 +0000
URI: /coffee
Request ID: 13a925b2514b62c45ea4a79800248d5cAccessing /coffee without credentials:
curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/coffeeResponse:
<html>
<head><title>401 Authorization Required</title></head>
<body>
<center><h1>401 Authorization Required</h1></center>
<hr><center>nginx</center>
</body>
</html>Accessing /coffee with incorrect credentials:
curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/coffee -u user1:wrong Response:
<html>
<head><title>401 Authorization Required</title></head>
<body>
<center><h1>401 Authorization Required</h1></center>
<hr><center>nginx</center>
</body>
</html>Accessing /tea
Since tea has no AuthenticationFilter attached, responses are processed normally:
curl --resolve cafe.example.com:$GW_PORT:$GW_IP http://cafe.example.com:$GW_PORT/teaResponse:
Server address: 10.244.0.10:8080
Server name: tea-75bc9f4b6d-ms2n8
Date: 06/Jan/2026:15:36:26 +0000
URI: /tea
Request ID: c7eb0509303de1c160cb7e7d2ac1d99f- Ensure the HTTPRoute is Accepted and references the correct AuthenticationFilter name and group.
- Confirm the secret key is named
authand is of typenginx.org/htpasswd. - Ensure the secret referenced by the AuthenticationFilter is in the same namespace.