Skip to main content
Version: 3.17

Forward Authentication (forward-auth)

Description#

The forward-auth Plugin supports the integration with an external authorization service for authentication and authorization. If the authentication fails, a customizable error message will be returned to the client. If the authentication succeeds, the request will be forwarded to the Upstream service along with the following request headers that APISIX added:

  • X-Forwarded-Proto: scheme
  • X-Forwarded-Method: HTTP method
  • X-Forwarded-Host: host
  • X-Forwarded-Uri: URI
  • X-Forwarded-For: source IP

Attributes#

NameTypeRequiredDefaultValid valuesDescription
uristringTrueURI of the external authorization service.
ssl_verifybooleanFalsetrueIf true, verify the authorization service's SSL certificate.
request_methodstringFalseGETGET or POSTHTTP method APISIX uses to send requests to the external authorization service. When set to POST, APISIX will send POST requests along with the request body to the external authorization service. If the authorization decision depends on request parameters from a POST body, it is recommended to extract the necessary fields using $post_arg.* and pass them via the extra_headers field instead.
max_req_body_sizeintegerFalse67108864>= 1Maximum request body size in bytes buffered and forwarded to the external authorization service when request_method is POST. Requests whose body exceeds this limit are rejected with 413. Prevents unbounded memory buffering of large request bodies.
request_headersarrayFalseClient request headers that should be forwarded to the external authorization service. If not configured, only headers added by APISIX are forwarded, such as X-Forwarded-*.
upstream_headersarrayFalseExternal authorization service response headers that should be forwarded to the Upstream service. If not configured, no headers are forwarded to the Upstream service.
client_headersarrayFalseExternal authorization service response headers that should be forwarded to the client when authentication fails. If not configured, no headers are forwarded to the client.
extra_headersobjectFalseAdditional headers to send to the authorization service. Support NGINX variables in values.
timeoutintegerFalse3000between 1 and 60000 inclusiveTimeout for the external authorization service HTTP call in milliseconds.
keepalivebooleanFalsetrueIf true, keep the connections open for multiple requests.
keepalive_timeoutintegerFalse60000>= 1000Idle time in milliseconds after which the established HTTP connections will be closed.
keepalive_poolintegerFalse5>= 1Maximum number of connections in the connection pool.
allow_degradationbooleanFalsefalseIf true, allow APISIX to continue handling requests without the Plugin when the Plugin or its dependencies become unavailable.
status_on_errorintegerFalse403between 200 and 599 inclusiveHTTP status code to return to the client when there is a network error with the external authorization service.

Examples#

The examples below demonstrate how you can use forward-auth for different scenarios.

note

You can fetch the admin_key from config.yaml and save to an environment variable with the following command:

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

To follow along the first two examples, please have your external authorization service set up, or create a mock auth service using the serverless-pre-function Plugin as shown below:

Forward Designated Headers to Upstream Resource#

The following example demonstrates how to set up forward-auth on a Route to regulate client access to the resources Upstream based on a value in the request header. It also allows passing a specific header from the authorization service to the Upstream resource.

Create a Route with the forward-auth Plugin as such:

Send a request to the Route with authorization detail in the header:

curl "http://127.0.0.1:9080/headers" -H 'Authorization: 123'

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

{
"headers": {
"Accept": "*/*",
"Authorization": "123",
...
}
}

To verify if the X-User-ID header set by the authorization service will be forwarded to the Upstream service, send a request to the Route with the corresponding authorization detail:

curl "http://127.0.0.1:9080/headers" -H 'Authorization: 321'

You should see an HTTP/1.1 200 OK response of the following, showing the header is forwarded to the Upstream:

{
"headers": {
"Accept": "*/*",
"Authorization": "123",
"X-User-ID": "i-am-user",
...
}
}

Return Designated Headers to Clients on Authentication Failure#

The following example demonstrates how you can configure forward-auth on a Route to regulate client access to the Upstream resources. It also passes a specific header returned by the authorization service to the client when the authentication fails.

Create a Route with the forward-auth Plugin as such:

Send a request without any authentication information:

curl -i "http://127.0.0.1:9080/headers"

You should receive an HTTP/1.1 403 Forbidden response:

...
X-Forward-Auth: Fail
Server: APISIX/3.x.x

<html>
<head><title>403 Forbidden</title></head>
<body>
<center><h1>403 Forbidden</h1></center>
<hr><center>openresty</center>
<p><em>Powered by <a href="https://apisix.apache.org/">APISIX</a>.</em></p></body>
</html>

Authorize Based on POST Body#

This example demonstrates how to configure the forward-auth Plugin to control access based on POST body data, pass values as headers to the authorization service, and reject the request when authorization fails per the body data.

Please have your external authorization service set up, or create a mock auth service using the serverless-pre-function Plugin. The function checks if the tenant_id header is 123 and returns 200 OK if it is, otherwise it returns 403 with an error message.

Create a Route with the forward-auth Plugin as such:

Send a POST request with tenant_id in the body:

curl -i "http://127.0.0.1:9080/post" -X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
-d 'tenant_id=123'

You should receive an HTTP/1.1 200 OK response.

Send a POST request with a different tenant_id in the body:

curl -i "http://127.0.0.1:9080/post" -X POST \
-H "Content-Type: application/x-www-form-urlencoded" \
-d 'tenant_id=000'

You should receive an HTTP/1.1 403 Forbidden response of the following:

tenant_id is 000 but expecting 123