Back to Apisix

basic-auth

docs/en/latest/plugins/basic-auth.md

3.17.031.0 KB
Original Source
<!-- # # Licensed to the Apache Software Foundation (ASF) under one or more # contributor license agreements. See the NOTICE file distributed with # this work for additional information regarding copyright ownership. # The ASF licenses this file to You under the Apache License, Version 2.0 # (the "License"); you may not use this file except in compliance with # the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # --> <head> <link rel="canonical" href="https://docs.api7.ai/hub/basic-auth" /> </head>

import Tabs from '@theme/Tabs'; import TabItem from '@theme/TabItem';

Description

The basic-auth Plugin adds basic access authentication for Consumers to authenticate themselves before being able to access Upstream resources.

When a Consumer is successfully authenticated, APISIX adds additional headers, such as X-Consumer-Username, X-Credential-Identifier, and other Consumer custom headers if configured, to the request, before proxying it to the Upstream service. The Upstream service will be able to differentiate between consumers and implement additional logics as needed. If any of these values is not available, the corresponding header will not be added.

Attributes

For Consumer/Credentials:

NameTypeRequiredDefaultValid valuesDescription
usernamestringTrueUnique basic auth username for a Consumer.
passwordstringTrueBasic auth password for the Consumer. The password is encrypted with AES before being stored in etcd. You can also store it in an environment variable and reference it using the env:// prefix, or in a secret manager such as HashiCorp Vault's KV secrets engine, and reference it using the secret:// prefix.

For Route:

NameTypeRequiredDefaultValid valuesDescription
hide_credentialsbooleanFalsefalseIf true, do not pass the authorization request header to Upstream services.
anonymous_consumerstringFalseAnonymous Consumer name. If configured, allow anonymous users to bypass the authentication.
realmstringFalsebasicRealm in the WWW-Authenticate response header returned with a 401 Unauthorized response due to authentication failure. Available in Apache APISIX version 3.15.0 and later.

Examples

The examples below demonstrate how you can work with the basic-auth Plugin for different scenarios.

:::note

bash
admin_key=$(yq '.deployment.admin.admin_key[0].key' conf/config.yaml | sed 's/"//g')

:::

Implement Basic Authentication on Route

The following example demonstrates how to implement basic authentication on a Route.

<Tabs groupId="api" defaultValue="admin-api" values={[ {label: 'Admin API', value: 'admin-api'}, {label: 'ADC', value: 'adc'}, {label: 'Ingress Controller', value: 'aic'} ]}>

<TabItem value="admin-api">

Create a Consumer johndoe:

shell
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
  -H "X-API-KEY: ${admin_key}" \
  -d '{
    "username": "johndoe"
  }'

Create basic-auth Credential for the Consumer:

shell
curl "http://127.0.0.1:9180/apisix/admin/consumers/johndoe/credentials" -X PUT \
  -H "X-API-KEY: ${admin_key}" \
  -d '{
    "id": "cred-john-basic-auth",
    "plugins": {
      "basic-auth": {
        "username": "johndoe",
        "password": "john-key"
      }
    }
  }'

Create a Route with basic-auth:

shell
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
  -H "X-API-KEY: ${admin_key}" \
  -d '{
    "id": "basic-auth-route",
    "uri": "/anything",
    "plugins": {
      "basic-auth": {}
    },
    "upstream": {
      "type": "roundrobin",
      "nodes": {
        "httpbin.org:80": 1
      }
    }
  }'
</TabItem> <TabItem value="adc">

Create a Consumer with basic-auth Credential and a Route with basic-auth Plugin configured:

yaml
consumers:
  - username: johndoe
    credentials:
      - name: basic-auth
        type: basic-auth
        config:
          username: johndoe
          password: john-key
services:
  - name: basic-auth-service
    routes:
      - name: basic-auth-route
        uris:
          - /anything
        plugins:
          basic-auth: {}
    upstream:
      type: roundrobin
      nodes:
        - host: httpbin.org
          port: 80
          weight: 1

Synchronize the configuration to the gateway:

shell
adc sync -f adc.yaml
</TabItem> <TabItem value="aic">

Create a Consumer with basic-auth Credential and a Route with basic-auth Plugin configured:

<Tabs groupId="k8s-api" defaultValue="gateway-api" values={[ {label: 'Gateway API', value: 'gateway-api'}, {label: 'APISIX Ingress Controller', value: 'apisix-ingress-controller'} ]}>

<TabItem value="gateway-api">
yaml
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
  namespace: aic
  name: johndoe
spec:
  gatewayRef:
    name: apisix
  credentials:
    - type: basic-auth
      name: primary-cred
      config:
        username: johndoe
        password: john-key
---
apiVersion: v1
kind: Service
metadata:
  namespace: aic
  name: httpbin-external-domain
spec:
  type: ExternalName
  externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
  namespace: aic
  name: basic-auth-plugin-config
spec:
  plugins:
    - name: basic-auth
      config:
        _meta:
          disable: false
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  namespace: aic
  name: basic-auth-route
spec:
  parentRefs:
    - name: apisix
  rules:
    - matches:
        - path:
            type: Exact
            value: /anything
      filters:
        - type: ExtensionRef
          extensionRef:
            group: apisix.apache.org
            kind: PluginConfig
            name: basic-auth-plugin-config
      backendRefs:
        - name: httpbin-external-domain
          port: 80

Apply the configuration to your cluster:

shell
kubectl apply -f basic-auth-ic.yaml
</TabItem> <TabItem value="apisix-ingress-controller">
yaml
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
  namespace: aic
  name: johndoe
spec:
  ingressClassName: apisix
  authParameter:
    basicAuth:
      value:
        username: johndoe
        password: john-key
---
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
  namespace: aic
  name: httpbin-external-domain
spec:
  ingressClassName: apisix
  externalNodes:
  - type: Domain
    name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  namespace: aic
  name: basic-auth-route
spec:
  ingressClassName: apisix
  http:
    - name: basic-auth-route
      match:
        paths:
          - /anything
      upstreams:
      - name: httpbin-external-domain
      plugins:
      - name: basic-auth
        enable: true

Apply the configuration to your cluster:

shell
kubectl apply -f basic-auth-ic.yaml
</TabItem> </Tabs> </TabItem> </Tabs>

Verify with Valid Credentials

Send a request to the Route with valid Credentials:

shell
curl -i "http://127.0.0.1:9080/anything" -u johndoe:john-key

You should see an HTTP/1.1 200 OK response similar to the following:

json
{
  "args": {},
  "headers": {
    "Accept": "*/*",
    "Authorization": "Basic am9obmRvZTpqb2huLWtleQ==",
    "Host": "127.0.0.1",
    "User-Agent": "curl/8.6.0",
    "X-Amzn-Trace-Id": "Root=1-66e5107c-5bb3e24f2de5baf733aec1cc",
    "X-Consumer-Username": "johndoe",
    "X-Credential-Identifier": "cred-john-basic-auth",
    "X-Forwarded-Host": "127.0.0.1"
  },
  "origin": "192.168.65.1, 205.198.122.37",
  "url": "http://127.0.0.1/anything"
}

Verify with Invalid Credentials

Send a request with invalid Credentials:

shell
curl -i "http://127.0.0.1:9080/anything" -u johndoe:invalid-password

You should see an HTTP/1.1 401 Unauthorized response with the following:

text
{"message":"Invalid user authorization"}

Verify without Credentials

Send a request without Credentials:

shell
curl -i "http://127.0.0.1:9080/anything"

You should see an HTTP/1.1 401 Unauthorized response with the following:

text
{"message":"Missing authorization in request"}

Hide Authentication Information From Upstream

The following example demonstrates how to prevent the client's Credentials (the Authorization header) from being sent to the Upstream services by configuring hide_credentials. If you are using APISIX, the Authorization header containing the client's Credentials is forwarded to the Upstream services by default, which might lead to security risks in some circumstances and you should consider updating hide_credentials as shown in this example.

<Tabs groupId="api" defaultValue="admin-api" values={[ {label: 'Admin API', value: 'admin-api'}, {label: 'ADC', value: 'adc'}, {label: 'Ingress Controller', value: 'aic'} ]}>

<TabItem value="admin-api">

Create a Consumer johndoe:

shell
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
  -H "X-API-KEY: ${admin_key}" \
  -d '{
    "username": "johndoe"
  }'

Create basic-auth Credential for the Consumer:

shell
curl "http://127.0.0.1:9180/apisix/admin/consumers/johndoe/credentials" -X PUT \
  -H "X-API-KEY: ${admin_key}" \
  -d '{
    "id": "cred-john-basic-auth",
    "plugins": {
      "basic-auth": {
        "username": "johndoe",
        "password": "john-key"
      }
    }
  }'

Without Hiding Credentials

Create a Route with basic-auth and configure hide_credentials to false, which is the default configuration:

shell
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
-H "X-API-KEY: ${admin_key}" \
-d '{
  "id": "basic-auth-route",
  "uri": "/anything",
  "plugins": {
    "basic-auth": {
      "hide_credentials": false
    }
  },
  "upstream": {
    "type": "roundrobin",
    "nodes": {
      "httpbin.org:80": 1
    }
  }
}'
</TabItem> <TabItem value="adc">

Create a Consumer with basic-auth Credential and a Route with basic-auth Plugin configured:

yaml
consumers:
  - username: johndoe
    credentials:
      - name: basic-auth
        type: basic-auth
        config:
          username: johndoe
          password: john-key
services:
  - name: basic-auth-service
    routes:
      - name: basic-auth-route
        uris:
          - /anything
        plugins:
          basic-auth:
            hide_credentials: false
    upstream:
      type: roundrobin
      nodes:
        - host: httpbin.org
          port: 80
          weight: 1

Synchronize the configuration to the gateway:

shell
adc sync -f adc.yaml
</TabItem> <TabItem value="aic">

Create a Consumer with basic-auth Credential and a Route with basic-auth Plugin configured:

<Tabs groupId="k8s-api" defaultValue="gateway-api" values={[ {label: 'Gateway API', value: 'gateway-api'}, {label: 'APISIX Ingress Controller', value: 'apisix-ingress-controller'} ]}>

<TabItem value="gateway-api">
yaml
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
  namespace: aic
  name: johndoe
spec:
  gatewayRef:
    name: apisix
  credentials:
    - type: basic-auth
      name: primary-cred
      config:
        username: johndoe
        password: john-key
---
apiVersion: v1
kind: Service
metadata:
  namespace: aic
  name: httpbin-external-domain
spec:
  type: ExternalName
  externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
  namespace: aic
  name: basic-auth-plugin-config
spec:
  plugins:
    - name: basic-auth
      config:
        _meta:
          disable: false
        hide_credentials: false
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  namespace: aic
  name: basic-auth-route
spec:
  parentRefs:
    - name: apisix
  rules:
    - matches:
        - path:
            type: Exact
            value: /anything
      filters:
        - type: ExtensionRef
          extensionRef:
            group: apisix.apache.org
            kind: PluginConfig
            name: basic-auth-plugin-config
      backendRefs:
        - name: httpbin-external-domain
          port: 80

Apply the configuration to your cluster:

shell
kubectl apply -f basic-auth-ic.yaml
</TabItem> <TabItem value="apisix-ingress-controller">
yaml
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
  namespace: aic
  name: johndoe
spec:
  ingressClassName: apisix
  authParameter:
    basicAuth:
      value:
        username: johndoe
        password: john-key
---
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
  namespace: aic
  name: httpbin-external-domain
spec:
  ingressClassName: apisix
  externalNodes:
  - type: Domain
    name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  namespace: aic
  name: basic-auth-route
spec:
  ingressClassName: apisix
  http:
    - name: basic-auth-route
      match:
        paths:
          - /anything
      upstreams:
      - name: httpbin-external-domain
      plugins:
      - name: basic-auth
        enable: true
        config:
          hide_credentials: false

Apply the configuration to your cluster:

shell
kubectl apply -f basic-auth-ic.yaml
</TabItem> </Tabs> </TabItem> </Tabs>

Send a request with the valid Credentials:

shell
curl -i "http://127.0.0.1:9080/anything" -u johndoe:john-key

You should see an HTTP/1.1 200 OK response with the following:

json
{
  "args": {},
  "data": "",
  "files": {},
  "form": {},
  "headers": {
    "Accept": "*/*",
    "Authorization": "Basic am9obmRvZTpqb2huLWtleQ==",
    "Host": "127.0.0.1",
    "User-Agent": "curl/8.6.0",
    "X-Amzn-Trace-Id": "Root=1-66cc2195-22bd5f401b13480e63c498c6",
    "X-Consumer-Username": "johndoe",
    "X-Credential-Identifier": "cred-john-basic-auth",
    "X-Forwarded-Host": "127.0.0.1"
  },
  "json": null,
  "method": "GET",
  "origin": "192.168.65.1, 43.228.226.23",
  "url": "http://127.0.0.1/anything"
}

Note that the Credentials are visible to the Upstream service in base64-encoded format. You can also pass the base64-encoded Credentials in the request using the Authorization header:

shell
curl -i "http://127.0.0.1:9080/anything" -H "Authorization: Basic am9obmRvZTpqb2huLWtleQ=="

Hide Credentials

<Tabs groupId="api" defaultValue="admin-api" values={[ {label: 'Admin API', value: 'admin-api'}, {label: 'ADC', value: 'adc'}, {label: 'Ingress Controller', value: 'aic'} ]}>

<TabItem value="admin-api">

Update the Plugin's hide_credentials to true:

shell
curl "http://127.0.0.1:9180/apisix/admin/routes/basic-auth-route" -X PATCH \
-H "X-API-KEY: ${admin_key}" \
-d '{
  "plugins": {
    "basic-auth": {
      "hide_credentials": true
    }
  }
}'
</TabItem> <TabItem value="adc">

Update the Route configuration:

yaml
# other configs
# ...
services:
  - name: basic-auth-service
    routes:
      - name: basic-auth-route
        uris:
          - /anything
        plugins:
          basic-auth:
            hide_credentials: true
    upstream:
      type: roundrobin
      nodes:
        - host: httpbin.org
          port: 80
          weight: 1

Synchronize the configuration to the gateway:

shell
adc sync -f adc.yaml
</TabItem> <TabItem value="aic">

<Tabs groupId="k8s-api" defaultValue="gateway-api" values={[ {label: 'Gateway API', value: 'gateway-api'}, {label: 'APISIX Ingress Controller', value: 'apisix-ingress-controller'} ]}>

<TabItem value="gateway-api">

Update the PluginConfig to set hide_credentials to true:

yaml
# other configs
# ---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
  namespace: aic
  name: basic-auth-plugin-config
spec:
  plugins:
    - name: basic-auth
      config:
        _meta:
          disable: false
        hide_credentials: true

Apply the configuration to your cluster:

shell
kubectl apply -f basic-auth-ic.yaml
</TabItem> <TabItem value="apisix-ingress-controller">

Update the ApisixRoute to set hide_credentials to true:

yaml
# other configs
# ---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  namespace: aic
  name: basic-auth-route
spec:
  ingressClassName: apisix
  http:
    - name: basic-auth-route
      match:
        paths:
          - /anything
      upstreams:
      - name: httpbin-external-domain
      plugins:
      - name: basic-auth
        enable: true
        config:
          hide_credentials: true

Apply the configuration to your cluster:

shell
kubectl apply -f basic-auth-ic.yaml
</TabItem> </Tabs> </TabItem> </Tabs>

Send a request with the valid Credentials:

shell
curl -i "http://127.0.0.1:9080/anything" -u johndoe:john-key

You should see an HTTP/1.1 200 OK response with the following:

json
{
  "args": {},
  "data": "",
  "files": {},
  "form": {},
  "headers": {
    "Accept": "*/*",
    "Host": "127.0.0.1",
    "User-Agent": "curl/8.6.0",
    "X-Amzn-Trace-Id": "Root=1-66cc21a7-4f6ac87946e25f325167d53a",
    "X-Consumer-Username": "johndoe",
    "X-Credential-Identifier": "cred-john-basic-auth",
    "X-Forwarded-Host": "127.0.0.1"
  },
  "json": null,
  "method": "GET",
  "origin": "192.168.65.1, 43.228.226.23",
  "url": "http://127.0.0.1/anything"
}

Note that the Credentials are no longer visible to the Upstream service.

Add Consumer Custom ID to Header

The following example demonstrates how you can attach a Consumer custom ID to authenticated request in the Consumer-Custom-Id header, which can be used to implement additional logics as needed.

<Tabs groupId="api" defaultValue="admin-api" values={[ {label: 'Admin API', value: 'admin-api'}, {label: 'ADC', value: 'adc'}, {label: 'Ingress Controller', value: 'aic'} ]}>

<TabItem value="admin-api">

Create a Consumer johndoe with a custom ID label:

shell
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
  -H "X-API-KEY: ${admin_key}" \
  -d '{
    "username": "johndoe",
    "labels": {
      "custom_id": "495aec6a"
    }
  }'

Create basic-auth Credential for the Consumer:

shell
curl "http://127.0.0.1:9180/apisix/admin/consumers/johndoe/credentials" -X PUT \
  -H "X-API-KEY: ${admin_key}" \
  -d '{
    "id": "cred-john-basic-auth",
    "plugins": {
      "basic-auth": {
        "username": "johndoe",
        "password": "john-key"
      }
    }
  }'

Create a Route with basic-auth:

shell
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
  -H "X-API-KEY: ${admin_key}" \
  -d '{
    "id": "basic-auth-route",
    "uri": "/anything",
    "plugins": {
      "basic-auth": {}
    },
    "upstream": {
      "type": "roundrobin",
      "nodes": {
        "httpbin.org:80": 1
      }
    }
  }'
</TabItem> <TabItem value="adc">

Create a Consumer with basic-auth Credential and a Route with basic-auth Plugin enabled:

yaml
consumers:
  - username: johndoe
    labels:
      custom_id: "495aec6a"
    credentials:
      - name: basic-auth
        type: basic-auth
        config:
          username: johndoe
          password: john-key
services:
  - name: basic-auth-service
    routes:
      - name: basic-auth-route
        uris:
          - /anything
        plugins:
          basic-auth: {}
    upstream:
      type: roundrobin
      nodes:
        - host: httpbin.org
          port: 80
          weight: 1

Synchronize the configuration to the gateway:

shell
adc sync -f adc.yaml
</TabItem> <TabItem value="aic">

Create a Consumer with basic-auth Credential and a Route with basic-auth Plugin enabled:

<Tabs groupId="k8s-api" defaultValue="gateway-api" values={[ {label: 'Gateway API', value: 'gateway-api'}, {label: 'APISIX CRD', value: 'apisix-crd'} ]}>

<TabItem value="gateway-api">
yaml
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
  namespace: aic
  name: johndoe
  labels:
    custom_id: "495aec6a"
spec:
  gatewayRef:
    name: apisix
  credentials:
    - type: basic-auth
      name: primary-key
      config:
        username: johndoe
        password: john-key
---
apiVersion: v1
kind: Service
metadata:
  namespace: aic
  name: httpbin-external-domain
spec:
  type: ExternalName
  externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
  namespace: aic
  name: basic-auth-plugin-config
spec:
  plugins:
    - name: basic-auth
      config:
        _meta:
          disable: false
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  namespace: aic
  name: basic-auth-route
spec:
  parentRefs:
    - name: apisix
  rules:
    - matches:
        - path:
            type: Exact
            value: /anything
      filters:
        - type: ExtensionRef
          extensionRef:
            group: apisix.apache.org
            kind: PluginConfig
            name: basic-auth-plugin-config
      backendRefs:
        - name: httpbin-external-domain
          port: 80

Apply the configuration to your cluster:

shell
kubectl apply -f basic-auth-ic.yaml
</TabItem> <TabItem value="apisix-crd">
yaml
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
  namespace: aic
  name: johndoe
  labels:
    custom_id: "495aec6a"
spec:
  ingressClassName: apisix
  authParameter:
    basicAuth:
      value:
        username: johndoe
        password: john-key
---
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
  namespace: aic
  name: httpbin-external-domain
spec:
  ingressClassName: apisix
  externalNodes:
    - type: Domain
      name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  namespace: aic
  name: basic-auth-route
spec:
  ingressClassName: apisix
  http:
    - name: basic-auth-route
      match:
        paths:
          - /anything
      upstreams:
        - name: httpbin-external-domain
      plugins:
        - name: basic-auth
          enable: true
          config:
            _meta:
              disable: false

Apply the configuration to your cluster:

shell
kubectl apply -f basic-auth-ic.yaml
</TabItem> </Tabs> </TabItem> </Tabs>

To verify, send a request to the Route with the valid Credentials:

shell
curl -i "http://127.0.0.1:9080/anything" -u johndoe:john-key

You should see an HTTP/1.1 200 OK response similar to the following:

json
{
  "args": {},
  "data": "",
  "files": {},
  "form": {},
  "headers": {
    "Accept": "*/*",
    "Authorization": "Basic am9obmRvZTpqb2huLWtleQ==",
    "Host": "127.0.0.1",
    "User-Agent": "curl/8.6.0",
    "X-Amzn-Trace-Id": "Root=1-66ea8d64-33df89052ae198a706e18c2a",
    "X-Consumer-Username": "aic_johndoe",
    "X-Credential-Identifier": "cred-john-basic-auth",
    "X-Consumer-Custom-Id": "495aec6a",
    "X-Forwarded-Host": "127.0.0.1"
  },
  "json": null,
  "method": "GET",
  "origin": "192.168.65.1, 205.198.122.37",
  "url": "http://127.0.0.1/anything"
}

Rate Limit with Anonymous Consumer

The following example demonstrates how you can configure different rate limiting policies by regular and anonymous consumers, where the anonymous Consumer does not need to authenticate and has less quota.

<Tabs groupId="api" defaultValue="admin-api" values={[ {label: 'Admin API', value: 'admin-api'}, {label: 'ADC', value: 'adc'}, {label: 'Ingress Controller', value: 'aic'} ]}>

<TabItem value="admin-api">

Create a regular Consumer johndoe and configure the limit-count Plugin to allow for a quota of 3 within a 30-second window:

shell
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
  -H "X-API-KEY: ${admin_key}" \
  -d '{
    "username": "johndoe",
    "plugins": {
      "limit-count": {
        "count": 3,
        "time_window": 30,
        "rejected_code": 429,
        "policy": "local"
      }
    }
  }'

Create the basic-auth Credential for the Consumer johndoe:

shell
curl "http://127.0.0.1:9180/apisix/admin/consumers/johndoe/credentials" -X PUT \
  -H "X-API-KEY: ${admin_key}" \
  -d '{
    "id": "cred-john-basic-auth",
    "plugins": {
      "basic-auth": {
        "username": "johndoe",
        "password": "john-key"
      }
    }
  }'

Create an anonymous user anonymous and configure the limit-count Plugin to allow for a quota of 1 within a 30-second window:

shell
curl "http://127.0.0.1:9180/apisix/admin/consumers" -X PUT \
  -H "X-API-KEY: ${admin_key}" \
  -d '{
    "username": "anonymous",
    "plugins": {
      "limit-count": {
        "count": 1,
        "time_window": 30,
        "rejected_code": 429,
        "policy": "local"
      }
    }
  }'

Create a Route and configure the basic-auth Plugin to accept anonymous Consumer anonymous from bypassing the authentication:

shell
curl "http://127.0.0.1:9180/apisix/admin/routes" -X PUT \
  -H "X-API-KEY: ${admin_key}" \
  -d '{
    "id": "basic-auth-route",
    "uri": "/anything",
    "plugins": {
      "basic-auth": {
        "anonymous_consumer": "anonymous"
      }
    },
    "upstream": {
      "type": "roundrobin",
      "nodes": {
        "httpbin.org:80": 1
      }
    }
  }'
</TabItem> <TabItem value="adc">

Configure Consumers with different rate limits and a Route that accepts anonymous users:

yaml
consumers:
  - username: johndoe
    plugins:
      limit-count:
        count: 3
        time_window: 30
        rejected_code: 429
        policy: local
    credentials:
      - name: basic-auth
        type: basic-auth
        config:
          username: johndoe
          password: john-key
  - username: anonymous
    plugins:
      limit-count:
        count: 1
        time_window: 30
        rejected_code: 429
        policy: local
services:
  - name: anonymous-rate-limit-service
    routes:
      - name: basic-auth-route
        uris:
          - /anything
        plugins:
          basic-auth:
            anonymous_consumer: anonymous
    upstream:
      type: roundrobin
      nodes:
        - host: httpbin.org
          port: 80
          weight: 1

Synchronize the configuration to the gateway:

shell
adc sync -f adc.yaml
</TabItem> <TabItem value="aic">

<Tabs groupId="k8s-api" defaultValue="gateway-api" values={[ {label: 'Gateway API', value: 'gateway-api'}, {label: 'APISIX Ingress Controller', value: 'apisix-ingress-controller'} ]}>

<TabItem value="gateway-api">

Configure Consumers with different rate limits and a Route that accepts anonymous users:

yaml
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
  namespace: aic
  name: johndoe
spec:
  gatewayRef:
    name: apisix
  credentials:
    - type: basic-auth
      name: primary-key
      config:
        username: johndoe
        password: john-key
  plugins:
    - name: limit-count
      config:
        count: 3
        time_window: 30
        rejected_code: 429
        policy: local
---
apiVersion: apisix.apache.org/v1alpha1
kind: Consumer
metadata:
  namespace: aic
  name: anonymous
spec:
  gatewayRef:
    name: apisix
  plugins:
    - name: limit-count
      config:
        count: 1
        time_window: 30
        rejected_code: 429
        policy: local
---
apiVersion: v1
kind: Service
metadata:
  namespace: aic
  name: httpbin-external-domain
spec:
  type: ExternalName
  externalName: httpbin.org
---
apiVersion: apisix.apache.org/v1alpha1
kind: PluginConfig
metadata:
  namespace: aic
  name: basic-auth-plugin-config
spec:
  plugins:
    - name: basic-auth
      config:
        anonymous_consumer: aic_anonymous  # namespace_consumername
---
apiVersion: gateway.networking.k8s.io/v1
kind: HTTPRoute
metadata:
  namespace: aic
  name: basic-auth-route
spec:
  parentRefs:
    - name: apisix
  rules:
    - matches:
        - path:
            type: Exact
            value: /anything
      filters:
        - type: ExtensionRef
          extensionRef:
            group: apisix.apache.org
            kind: PluginConfig
            name: basic-auth-plugin-config
      backendRefs:
        - name: httpbin-external-domain
          port: 80

Apply the configuration to your cluster:

shell
kubectl apply -f basic-auth-ic.yaml
</TabItem> <TabItem value="apisix-ingress-controller">

Configure Consumers with different rate limits and a Route that accepts anonymous users:

yaml
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
  namespace: aic
  name: johndoe
spec:
  ingressClassName: apisix
  authParameter:
    basicAuth:
      value:
        username: johndoe
        password: john-key
  plugins:
    - name: limit-count
      enable: true
      config:
        count: 3
        time_window: 30
        rejected_code: 429
        policy: local
---
apiVersion: apisix.apache.org/v2
kind: ApisixConsumer
metadata:
  namespace: aic
  name: anonymous
spec:
  ingressClassName: apisix
  plugins:
    - name: limit-count
      enable: true
      config:
        count: 1
        time_window: 30
        rejected_code: 429
        policy: local
---
apiVersion: apisix.apache.org/v2
kind: ApisixUpstream
metadata:
  namespace: aic
  name: httpbin-external-domain
spec:
  ingressClassName: apisix
  externalNodes:
    - type: Domain
      name: httpbin.org
---
apiVersion: apisix.apache.org/v2
kind: ApisixRoute
metadata:
  namespace: aic
  name: basic-auth-route
spec:
  ingressClassName: apisix
  http:
    - name: basic-auth-route
      match:
        paths:
          - /anything
      upstreams:
        - name: httpbin-external-domain
      plugins:
        - name: basic-auth
          enable: true
          config:
            anonymous_consumer: aic_anonymous

Apply the configuration to your cluster:

shell
kubectl apply -f basic-auth-ic.yaml
</TabItem> </Tabs> </TabItem> </Tabs>

To verify, send five consecutive requests with johndoe's Credentials:

shell
resp=$(seq 5 | xargs -I{} curl "http://127.0.0.1:9080/anything" -u johndoe:john-key -o /dev/null -s -w "%{http_code}\n") && \
  count_200=$(echo "$resp" | grep "200" | wc -l) && \
  count_429=$(echo "$resp" | grep "429" | wc -l) && \
  echo "200": $count_200, "429": $count_429

You should see the following response, showing that out of the 5 requests, 3 requests were successful (status code 200) while the others were rejected (status code 429).

text
200:    3, 429:    2

Send five anonymous requests:

shell
resp=$(seq 5 | xargs -I{} curl "http://127.0.0.1:9080/anything" -o /dev/null -s -w "%{http_code}\n") && \
  count_200=$(echo "$resp" | grep "200" | wc -l) && \
  count_429=$(echo "$resp" | grep "429" | wc -l) && \
  echo "200": $count_200, "429": $count_429

You should see the following response, showing that only one request was successful:

text
200:    1, 429:    4