Basic Authentication may seem like a trivial mechanism because it only uses a username and a password. However, using it correctly means separating three ideas: the HTTP standard, the validation performed by Kong Gateway, and the identity that Kong associates with valid credentials.

In this article we will look at those three layers and build a reproducible lab with Kong Ingress Controller. The goal is not simply to copy files and blindly apply them. First we will understand what each resource represents, then we will apply it, and finally we will check what happens inside Kong.

This lab continues exactly from the scenario created in the KIC installation post. It reuses the Gateway kong, the echo Service, and the 192.168.121.200 address assigned by MetalLB to kong-gateway-proxy.

The tests in this article were carried out with Kong Gateway 3.10.0.16 and Kong Ingress Controller 3.5.

1. What is Basic Authentication?

Basic Authentication is an authentication scheme defined by RFC 7617. It allows an HTTP client to send a username and password inside the Authorization header.

The client starts by building a string with this format:

username:password

The : character separates both values. The client then encodes the string with Base64 and adds the result to the HTTP header:

username:password
        |
        v
      Base64
        |
        v
Authorization: Basic <credentials>

In our lab we will use:

alice:alice-basic-password

We can calculate its Base64 representation from the terminal. We use -n so that echo does not append a newline to the end of the string:

echo -n 'alice:alice-basic-password' | base64

The result is:

YWxpY2U6YWxpY2UtYmFzaWMtcGFzc3dvcmQ=

Therefore, the complete header is:

Authorization: Basic YWxpY2U6YWxpY2UtYmFzaWMtcGFzc3dvcmQ=

Base64 is an encoding, not encryption. Anyone who captures the header can decode it and recover the username and password. For this reason, Basic Authentication must be used over HTTPS. TLS provides confidentiality and integrity during transport.

The standard also defines the challenge that a server can return when credentials are missing. In this article we will focus on the 401 Unauthorized status code and the validation performed by Kong.

2. How does Basic Authentication work in Kong Gateway?

Kong implements this mechanism through the official basic-auth plugin. The plugin is available for traditional, hybrid, and DB-less topologies, and can be applied globally, to a Gateway Service, or to a Route.

In this lab we will apply it only to the Route generated from /basic-auth. This means that the other routes published on echo.javiercd.es are not protected by this plugin.

When a request matches the Route, Kong runs the plugin during access processing, before sending the request to the upstream. According to the official documentation, it looks for credentials in this order:

  1. Proxy-Authorization
  2. Authorization

If it finds a Basic header, it decodes the value, locates the credential, and compares the received password with the password stored for that identity.

The following diagram summarizes the two possible branches of the plugin. Invalid credentials end at Kong with a 401 Unauthorized response. Valid credentials identify the Consumer and allow the request to continue to the upstream.

Basic Authentication flow in Kong Gateway

The behavior is as follows:

  • If there are no credentials and anonymous access has not been configured, Kong returns 401 Unauthorized.
  • If the user does not exist, Kong returns 401 Unauthorized.
  • If the password does not match, Kong returns 401 Unauthorized.
  • If the credentials are valid, Kong identifies the Consumer and allows the request to continue.
  • When Kong rejects authentication, the request does not reach the upstream.

The Basic Auth plugin does not decide which backend receives a request. Backend selection remains the responsibility of the Route and the Service. The plugin only adds a prerequisite: the client must authenticate successfully.

3. Consumers and Basic Auth credentials

A Consumer is the representation Kong uses to identify an API client. It can represent a person, an application, a service, a device, or any other entity that needs to consume an API.

Do not confuse these three names in the lab:

  • basic-auth-client is the name of the KongConsumer resource in Kubernetes.
  • alice is the Consumer’s username in Kong.
  • alice is also the username in the Basic Auth credential.

Although they match in this example, the Consumer’s username and the credential’s username are different fields.

The relationship is:

Consumer
    |
    +-- Basic Auth credential
            |
            +-- username
            +-- password

The Consumer provides the identity. The credential provides the proof used to demonstrate that identity. Once validation finishes successfully, Kong knows both the authenticated Consumer and the identifier of the credential that was used.

A single Consumer can have several credentials. However, it is usually better to assign one credential per Consumer so that we can control who consumes our APIs.

4. Configuring Basic Auth in Kong with KIC

We will publish the echo Service through an HTTPRoute and protect that route with Basic Auth.

The KIC installation post already created these shared resources:

  • The Gateway kong in the kong namespace.
  • The echo Service in the javier namespace.
  • Kong’s proxy exposed through MetalLB.

We will not create them again. This lab only adds a KongPlugin, a Secret, a KongConsumer, and an HTTPRoute.

4.1. Relationship between Kubernetes and Kong resources

Kubernetes resourceKong internal resource
KongPluginplugins
Secretbasicauth_credentials
KongConsumerconsumers
HTTPRouteroutes, services, upstreams, and targets

In DB-less mode, these translations are part of Kong’s in-memory configuration. In traditional mode, they would be reflected in entities such as plugins, basicauth_credentials, consumers, routes, services, upstreams, and targets.

4.2. Create the basic-auth plugin

This file declares the plugin that will perform the validation.

hide_credentials: true tells Kong to remove the header used for authentication before sending the request to the upstream. realm defines the authentication scope that Kong advertises through WWW-Authenticate when it rejects the request.

The KongPlugin does not protect any route by itself. It becomes associated with a route when we add its name to the HTTPRoute annotation.

apiVersion: configuration.konghq.com/v1
kind: KongPlugin
metadata:
  name: basic-auth
  namespace: javier
plugin: basic-auth
config:
  hide_credentials: true
  realm: javier-basic-auth

In a database-backed installation, this configuration would become a plugins entity. When associated with the Route, the entity would contain a reference to that Route.

4.3. Create the credential

KIC uses a Kubernetes Secret to declare authentication plugin credentials.

The konghq.com/credential: basic-auth label is required. It tells KIC to interpret username and password as a Basic Auth credential instead of treating the object as a generic Secret.

apiVersion: v1
kind: Secret
metadata:
  name: basic-auth-credential
  namespace: javier
  labels:
    konghq.com/credential: basic-auth
stringData:
  username: alice
  password: alice-basic-password

Using stringData makes the lab easier because Kubernetes performs the Base64 encoding when it stores the Secret. That Kubernetes encoding does not encrypt the password either.

KIC reads this Secret and translates it into a Basic Auth credential. In a database-backed Kong deployment, it would correspond to a basicauth_credentials entity, not to a generic Secrets table.

4.4. Create the KongConsumer

The KongConsumer creates the alice identity and references the previous Secret through credentials.

apiVersion: configuration.konghq.com/v1
kind: KongConsumer
metadata:
  name: basic-auth-client
  namespace: javier
  annotations:
    kubernetes.io/ingress.class: kong
username: alice
credentials:
  - basic-auth-credential

KIC resolves the basic-auth-credential reference, creates the Consumer, and associates the credential. In traditional mode, the Consumer would be represented in consumers and the credential would retain the relationship through its identifier.

4.5. Create the HTTPRoute

The HTTPRoute publishes the /basic-auth route on echo.javiercd.es.

parentRefs connects the route to the kong Gateway. backendRefs reuses the echo Service. The konghq.com/plugins: basic-auth annotation applies the previously created KongPlugin.

apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  name: basic-auth
  namespace: javier
  annotations:
    konghq.com/plugins: basic-auth
spec:
  parentRefs:
    - name: kong
      namespace: kong
  hostnames:
    - echo.javiercd.es
  rules:
    - matches:
        - path:
            type: PathPrefix
            value: /basic-auth
      backendRefs:
        - name: echo
          port: 80

KIC translates this definition into a Kong Route. It also creates or reuses the internal entities needed to reach the echo Service endpoints. The annotation creates the association between the Route and the plugin.

4.6. Apply the manifests

Apply the resources in the order in which we have explained them:

sudo kubectl apply -f 10-basic-auth-plugin.yaml
sudo kubectl apply -f 10-basic-auth-secret.yaml
sudo kubectl apply -f 10-basic-auth-consumer.yaml
sudo kubectl apply -f 10-basic-auth-httproute.yaml

Check their status:

sudo kubectl get kongplugin basic-auth -n javier
sudo kubectl get kongconsumer basic-auth-client -n javier
sudo kubectl get httproute basic-auth -n javier
sudo kubectl describe httproute basic-auth -n javier

The HTTPRoute should be accepted by the Gateway.

5. Testing Basic Authentication

Now we will test the configuration we have deployed.

5.1. Request without credentials

Make the request without sending credentials:

curl -i http://echo.javiercd.es/basic-auth

The response observed in the lab is:

HTTP/1.1 401 Unauthorized
Date: Sun, 26 Jul 2026 09:01:38 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
WWW-Authenticate: Basic realm="javier-basic-auth"
Content-Length: 26
X-Kong-Response-Latency: 0
Server: kong/3.10.0.16-enterprise-edition
X-Kong-Request-Id: da02e8552baa4a0f020f5761b6401524

{"message":"Unauthorized"}

X-Kong-Upstream-Latency is absent because Kong generated the response before contacting echo.

5.2. Incorrect credentials

Now we will send the request using incorrect credentials with curl -u, which builds the Authorization: Basic header for us:

curl -i -u alice:incorrecta \
  http://echo.javiercd.es/basic-auth

The response is again:

HTTP/1.1 401 Unauthorized
Date: Sun, 26 Jul 2026 09:01:38 GMT
Content-Type: application/json; charset=utf-8
Connection: keep-alive
WWW-Authenticate: Basic realm="javier-basic-auth"
Content-Length: 26
X-Kong-Response-Latency: 0
Server: kong/3.10.0.16-enterprise-edition
X-Kong-Request-Id: baf09c5e879385768ab2480cf3c5bc3f

{"message":"Unauthorized"}

Kong does not reveal whether the error is caused by a missing user or by an incorrect password.

5.3. Correct credentials

curl -i -u alice:alice-basic-password \
  http://echo.javiercd.es/basic-auth

The observed response is:

HTTP/1.1 200 OK
Content-Type: text/plain; charset=utf-8
Content-Length: 28
Connection: keep-alive
X-App-Name: http-echo
X-App-Version: 1.0.0
Date: Sun, 26 Jul 2026 09:01:38 GMT
Server: kong/3.10.0.16-enterprise-edition
X-Kong-Upstream-Latency: 0
X-Kong-Proxy-Latency: 1
Via: 1.1 kong/3.10.0.16-enterprise-edition
X-Kong-Request-Id: 229ad4616bfa4a0c334d112502217437

Hola desde Kong Gateway KIC

This time Kong identified the Consumer and sent the request to the upstream.

We can also send the header manually:

curl -i \
  -H 'Authorization: Basic YWxpY2U6YWxpY2UtYmFzaWMtcGFzc3dvcmQ=' \
  http://echo.javiercd.es/basic-auth

Official sources