Allow clients to choose their authentication methods and prevent unauthorized access

Uses: Kong Gateway decK
Related Resources
Minimum Version
Kong Gateway - 3.4
TL;DR

Configure multiple authentication plugins, like Key Auth and Basic Auth, and apply them to specific Consumers. Set config.anonymous in those plugins to the ID of the anonymous Consumer to catch access attempts from anyone else. Then, apply the Request Termination plugin to the anonymous Consumer to terminate the requests and send back a specific message.

Prerequisites

This is a Konnect tutorial. If you don’t have a Konnect account, you can get started quickly with our onboarding wizard.

  1. The following Konnect items are required to complete this tutorial:

    • Personal access token (PAT): Create a new personal access token by opening the Konnect PAT page and selecting Generate Token.
    • Control Plane Name: You can use an existing Control Plane or create a new one to use for this tutorial.
    • Konnect Proxy URL: By default, a self-hosted Data Plane uses http://localhost:8000. You can set up Data Plane nodes for your Control Plane from the Gateway Manager in Konnect.
  2. Set the personal access token, the Control Plane name, the Control Plane URL, and the Konnect proxy URL as environment variables:

     export DECK_KONNECT_TOKEN='YOUR KONNECT TOKEN'
     export DECK_KONNECT_CONTROL_PLANE_NAME='YOUR CONTROL PLANE NAME'
     export KONNECT_CONTROL_PLANE_URL=https://us.api.konghq.com
     export KONNECT_PROXY_URL='KONNECT PROXY URL'
    

This tutorial requires Kong Gateway Enterprise. If you don’t have Kong Gateway set up yet, you can use the quickstart script with an enterprise license to get an instance of Kong Gateway running almost instantly.

  1. Export your license to an environment variable:

     export KONG_LICENSE_DATA='LICENSE-CONTENTS-GO-HERE'
    
  2. Run the quickstart script:

     curl -Ls https://get.konghq.com/quickstart | bash -s -- -e KONG_LICENSE_DATA 
    

    Once Kong Gateway is ready, you will see the following message:

     Kong Gateway Ready
    

decK is a CLI tool for managing Kong Gateway declaratively with state files. To complete this tutorial you will first need to install decK.

For this tutorial, you’ll need Kong Gateway entities, like Gateway Services and Routes, pre-configured. These entities are essential for Kong Gateway to function but installing them isn’t the focus of this guide. Follow these steps to pre-configure them:

  1. Run the following command:

    echo '
    _format_version: "3.0"
    services:
      - name: example-service
        url: http://httpbin.konghq.com/anything
    routes:
      - name: example-route
        paths:
        - "/anything"
        service:
          name: example-service
    ' | deck gateway apply -
    

To learn more about entities, you can read our entities documentation.

Create Consumers

You can use multiple authentication plugins with an anonymous Consumer to give clients multiple options for authentication. The anonymous Consumer doesn’t correspond to any real user, and acts as a fallback to catch all other unauthorized requests.

Create three Consumers, including the anonymous Consumer:

echo '
_format_version: "3.0"
consumers:
  - username: anonymous
  - username: Dana
  - username: Mahan
' | deck gateway apply -

We’re going to assign a different authentication type to each Consumer later.

Set up authentication

Add the Key Auth and Basic Auth plugins to the example-service Gateway Service, and set the anonymous fallback to the Consumer we created earlier:

echo '
_format_version: "3.0"
plugins:
  - name: key-auth
    service: example-service
    config:
      hide_credentials: true
      anonymous: anonymous
  - name: basic-auth
    service: example-service
    config:
      hide_credentials: true
      anonymous: anonymous
' | deck gateway apply -

Test with anonymous Consumer

You now have authentication enabled on the Gateway Service, but the anonymous Consumer also allows requests from unauthenticated clients.

The following validation works because the unauthenticated request falls back to the anonymous Consumer, which allows it through:

curl -i "$KONNECT_PROXY_URL/anything"
curl -i "http://localhost:8000/anything"

The following validation with fake credentials also works because an incorrect API key is treated as anonymous:

curl -i "$KONNECT_PROXY_URL/anything" \
     -H "apikey:nonsense"
curl -i "http://localhost:8000/anything" \
     -H "apikey:nonsense"

In both cases, you should get a 200 response, as the anonymous Consumer is allowed.

Configure credentials

Now, let’s configure Consumers with different auth credentials and prevent unauthenticated access. Configure different credentials for the two named users: basic auth for Dana, and key auth for Mahan:

echo '
_format_version: "3.0"
consumers:
  - username: Dana
    basicauth_credentials:
    - username: Dana
      password: dana
  - username: Mahan
    keyauth_credentials:
    - key: mahan
' | deck gateway apply -

Add Request Termination to the anonymous Consumer

The anonymous Consumer gets no credentials, as we don’t want unauthenticated users accessing our Gateway Service. Instead, you can configure the Request Termination plugin to handle anonymous Consumers and redirect their requests with a 401:

echo '
_format_version: "3.0"
consumers:
  - username: anonymous
    plugins:
    - name: request-termination
      config:
        status_code: 401
        message: '"Error - Authentication required"'
' | deck gateway apply -

Validate authentication

Let’s check that authentication works.

Try to access the Gateway Service via the /anything Route using a nonsense API key:

curl -i "$KONNECT_PROXY_URL/anything" \
     -H "apikey:nonsense"
curl -i "http://localhost:8000/anything" \
     -H "apikey:nonsense"

The request should now fail with a 401 response and your configured error message, as this Consumer is considered anonymous.

You should get the same result if you try to access the Route without any API key:

curl -i "$KONNECT_PROXY_URL/anything"
curl -i "http://localhost:8000/anything"

Finally, try accessing the Route with the configured basic auth credentials:

curl -i "$KONNECT_PROXY_URL/anything" \
     -u Dana:dana
curl -i "http://localhost:8000/anything" \
     -u Dana:dana

This time, authentication should succeed with a 200.

Cleanup

If you created a new control plane and want to conserve your free trial credits or avoid unnecessary charges, delete the new control plane used in this tutorial.

curl -Ls https://get.konghq.com/quickstart | bash -s -- -d

FAQs

If config.anonymous isn’t set, then all configured authentication plugins will attempt to authenticate every request. For example, if you have Key Auth and Basic Auth configured on a Gateway Service, then every request has to contain both types of authentication. In this case, the last plugin executed is the one setting the credentials passed to the upstream service.

When multiple authentication plugins are enabled on a Gateway Service and config.anonymous is set without any request termination, unauthorized requests will be allowed through. If you want anonymous access to be forbidden, you must configure the Request Termination plugin on the anonymous Consumer.

If you are using the OpenID Connect plugin for handling Consumer authentication, you must set both config.anonymous and config.consumer_claim in the plugin’s configuration, as setting config.anonymous alone doesn’t map that Consumer.

Something wrong?

Help us make these docs great!

Kong Developer docs are open source. If you find these useful and want to make them better, contribute today!