You are browsing documentation for an older version. See the latest documentation here.
Allowing Multiple Authentication Methods
Learn to configure multiple authentication options for consumers using the Kong Ingress Controller. The default behavior for Kong authentication plugins is to require credentials for all requests even if a request has been authenticated through another plugin. Configure an anonymous consumer on your authentication plugins to set clients authentication options.
Prerequisites: Install Kong Ingress Controller in your Kubernetes cluster and connect to Kong.
Prerequisites
Install Kong
You can install Kong in your Kubernetes cluster using Helm.
-
Add the Kong Helm charts:
helm repo add kong https://charts.konghq.com helm repo update
-
Install Kong Ingress Controller and Kong Gateway with Helm:
helm install kong kong/ingress -n kong --create-namespace
Test connectivity to Kong
Kubernetes exposes the proxy through a Kubernetes service. Run the following commands to store the load balancer IP address in a variable named PROXY_IP
:
-
Populate
$PROXY_IP
for future commands:export PROXY_IP=$(kubectl get svc --namespace kong kong-gateway-proxy -o jsonpath='{.status.loadBalancer.ingress[0].ip}') echo $PROXY_IP
-
Ensure that you can call the proxy IP:
curl -i $PROXY_IP
The results should look like this:
HTTP/1.1 404 Not Found Content-Type: application/json; charset=utf-8 Connection: keep-alive Content-Length: 48 X-Kong-Response-Latency: 0 Server: kong/3.0.0 {"message":"no Route matched with those values"}
Create a Kubernetes service
Create a Kubernetes service setup an httpbin service in the cluster and proxy it.
$ kubectl apply -f https://raw.githubusercontent.com/Kong/kubernetes-ingress-controller/v3.4.0/deploy/manifests/httpbin.yaml
The results should look like this:
service/httpbin created
deployment.apps/httpbin created
Expose the Kubernetes service using Ingress
-
Expose the service outside the Kubernetes cluster by defining Ingress rules.
echo ' apiVersion: networking.k8s.io/v1 kind: Ingress metadata: name: demo annotations: konghq.com/strip-path: "true" spec: ingressClassName: kong rules: - http: paths: - path: /test pathType: Prefix backend: service: name: httpbin port: number: 80 ' | kubectl apply -f -
The results should look like this:
ingress.networking.k8s.io/demo created
We can now call
$PROXY_IP/test/status/200
to reach our deployed service.
Create Consumers and secrets
Create two consumers that use different authentication methods:
-
consumer-1
usesbasic-auth
-
consumer-2
useskey-auth
-
Create a secret to add
basic-auth
credential forconsumer-1
.kubectl create secret generic consumer-1-basic-auth \ --from-literal=kongCredType=basic-auth \ --from-literal=username=consumer-1 \ --from-literal=password=consumer-1-password
The results should look like this:
secret/consumer-1-basic-auth created
-
Create a consumer named
consumer-1
.echo "apiVersion: configuration.konghq.com/v1 kind: KongConsumer metadata: name: consumer-1 annotations: kubernetes.io/ingress.class: kong username: consumer-1 credentials: - consumer-1-basic-auth " | kubectl apply -f -
The results should look like this:
kongconsumer.configuration.konghq.com/consumer-1 created
-
Create a secret to add
key-auth
credential forconsumer-2
.kubectl create secret generic consumer-2-key-auth \ --from-literal=kongCredType=key-auth \ --from-literal=key=consumer-2-password
The results should look like this:
secret/consumer-2-key-auth created
-
Create a consumer named
consumer-2
.echo "apiVersion: configuration.konghq.com/v1 kind: KongConsumer metadata: name: consumer-2 annotations: kubernetes.io/ingress.class: kong username: consumer-2 credentials: - consumer-2-key-auth " | kubectl apply -f -
The results should look like this:
kongconsumer.configuration.konghq.com/consumer-2 created
Secure the Ingress
-
Create two plugins.
- Create a plugin named
httpbin-basic-auth
.
echo ' apiVersion: configuration.konghq.com/v1 kind: KongPlugin metadata: name: httpbin-basic-auth config: anonymous: anonymous hide_credentials: true plugin: basic-auth ' | kubectl apply -f -
The results should look like this:
kongplugin.configuration.konghq.com/httpbin-basic-auth created
- Create a plugin named
httpbin-key-auth
.
echo ' apiVersion: configuration.konghq.com/v1 kind: KongPlugin metadata: name: httpbin-key-auth config: key_names: - apikey anonymous: anonymous hide_credentials: true plugin: key-auth ' | kubectl apply -f -
The results should look like this:
kongplugin.configuration.konghq.com/httpbin-key-auth created
- Create a plugin named
-
Associate the plugins with the Ingress rule that you created.
kubectl patch ingress demo -p '{"metadata":{"annotations":{"konghq.com/plugins":"httpbin-basic-auth, httpbin-key-auth"}}}'
The results should look like this:
ingress.networking.k8s.io/demo patched
Anonymous Consumers
Your endpoints are now secure, but neither consumer can access the endpoint when providing valid credentials. This is because each plugin will verify the consumer using it’s own authentication method.
To allow multiple authentication methods, create an anonymous consumer which is the default user if no valid credentials are provided:
-
Create a consumer named
anonymous
.echo "apiVersion: configuration.konghq.com/v1 kind: KongConsumer metadata: name: anonymous annotations: kubernetes.io/ingress.class: kong username: anonymous " | kubectl apply -f -
The results should look like this:
kongconsumer.configuration.konghq.com/anonymous created
All requests to the API will now succeed as the anonymous consumer is being used as a default.
To secure the API once again, add a request termination plugin to the anonymous consumer that returns
HTTP 401
: -
Create a
Request Termination
plugin.echo ' apiVersion: configuration.konghq.com/v1 kind: KongPlugin metadata: name: anonymous-request-termination config: message: "Authentication required" status_code: 401 plugin: request-termination ' | kubectl apply -f -
The results should look like this:
kongplugin.configuration.konghq.com/anonymous-request-termination created
-
Associate the
Request Termination
plugin to theanonymous
consumer.echo ' apiVersion: configuration.konghq.com/v1 kind: KongConsumer metadata: annotations: konghq.com/plugins: anonymous-request-termination kubernetes.io/ingress.class: kong name: anonymous username: anonymous ' | kubectl apply -f -
The results should look like this:
kongconsumer.configuration.konghq.com/anonymous configured
Test the configuration
Any requests with missing or invalid credentials are rejected, whereas authorized requests using either of the authentication methods are allowed.
- Send a request with invalid credentials.
curl -i $PROXY_IP/test/status/200 -H apikey:invalid
The results should look like this:
HTTP/1.1 401 Unauthorized Content-Type: application/json; charset=utf-8 Connection: keep-alive WWW-Authenticate: Key realm="kong" Content-Length: 37 X-Kong-Response-Latency: 3 Server: kong/3.3.1 {"message":"Authentication required"}%
- Send a request without any credentials.
curl -i $PROXY_IP/test/status/200
The results should look like this:
HTTP/1.1 401 Unauthorized Content-Type: application/json; charset=utf-8 Connection: keep-alive WWW-Authenticate: Key realm="kong" Content-Length: 37 X-Kong-Response-Latency: 1 Server: kong/3.3.1 {"message":"Authentication required"}%
- Send a request using the
basic-auth
authentication methodcurl -i $PROXY_IP/test/status/200 -u consumer-1:consumer-1-password
The results should look like this:
HTTP/1.1 200 OK Content-Type: text/html; charset=utf-8 Content-Length: 0 Connection: keep-alive WWW-Authenticate: Key realm="kong" Server: gunicorn/19.9.0 Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true X-Kong-Upstream-Latency: 1309 X-Kong-Proxy-Latency: 3 Via: kong/3.3.1
- Send a request using the
key-auth
authentication methodcurl -i $PROXY_IP/test/status/200 -H apikey:consumer-2-password
The results should look like this:
HTTP/1.1 200 OK Content-Type: text/html; charset=utf-8 Content-Length: 0 Connection: keep-alive Server: gunicorn/19.9.0 Access-Control-Allow-Origin: * Access-Control-Allow-Credentials: true X-Kong-Upstream-Latency: 1227 X-Kong-Proxy-Latency: 4 Via: kong/3.3.1