Skip to main content

Authorize M2M Requests with Auth0

Auth0 is a cloud identity platform that can issue access tokens to applications. Background services, scheduled jobs, command-line tools, and automation can use these tokens to call APIs without an end user signing in.

The OAuth 2.0 Client Credentials flow is designed for this type of machine-to-machine (M2M) communication. Apache APISIX can protect the target API by validating each token's signature, issuer, audience, and granted permissions before proxying the request.

The guide shows how to configure an Auth0 custom API and M2M application for APISIX. The application receives permission to read protected messages and uses its client credentials to request an access token. APISIX validates the token locally with Auth0's JSON Web Key Set (JWKS) and removes authentication data before forwarding the request to the sample upstream.

Prerequisite(s)

Configure Auth0

Register a custom API to define the token audience and permissions, then configure an M2M application that can request those permissions.

Create a Custom API

Sign in to the Auth0 Dashboard and create the API:

  1. Select Applications → APIs → Create API.
  2. Enter APISIX Protected API as the API name.
  3. Enter https://apisix.example.com as the identifier.
  4. Keep Auth0 as the JWT profile and RS256 as the signing algorithm.
  5. Select Create.

The API identifier becomes the audience of access tokens issued for this API. It identifies the API but does not need to resolve to a network endpoint.

Add an API Permission

On the API's Permissions tab, create the permission that the APISIX route will require:

  1. Enter read:messages as the permission.
  2. Enter Read protected messages as the description.
  3. Select Add.

Configure the M2M Application

Auth0 creates a test M2M application when a custom API is registered. Configure that application for this guide:

  1. Select Applications → Applications.
  2. Select APISIX Protected API (Test Application).
  3. On the Settings tab, rename the application to APISIX M2M Client and select Save Changes.
  4. Select API Access.
  5. In the APISIX Protected API row, select Edit.
  6. Select Client Access, select read:messages, and then select Save.

Grant the Auth0 M2M client access to the protected API

For production, register a separate M2M application for each calling service and grant only the permissions that the service requires.

Save the OAuth Configuration

On the M2M application's Settings tab, record the Domain, Client ID, and Client Secret. Save them with the API identifier as environment variables, replacing the example values:

export AUTH0_DOMAIN=your-tenant.us.auth0.com
export AUTH0_M2M_CLIENT_ID=replace-with-your-m2m-client-id
export AUTH0_M2M_CLIENT_SECRET=replace-with-your-m2m-client-secret
export AUTH0_API_AUDIENCE=https://apisix.example.com
export AUTH0_DISCOVERY="https://${AUTH0_DOMAIN}/.well-known/openid-configuration"

Keep the client secret confidential. Store production credentials in a secret manager and rotate them according to the organization's credential-rotation policy.

Configure APISIX

Configure a route that accepts Auth0 bearer tokens before forwarding requests to httpbin.org, a public HTTP request and response service. The /anything/m2m/* endpoint returns request details for verification.

Choose either the Admin API or ADC to configure the route.

Create a route that validates bearer tokens locally with Auth0's JWKS:

curl "http://127.0.0.1:9180/apisix/admin/routes/auth0-m2m" -X PUT \
--data-binary @- <<EOF
{
"uri": "/anything/m2m/*",
"plugins": {
"openid-connect": {
"client_id": "$AUTH0_API_AUDIENCE",
"discovery": "$AUTH0_DISCOVERY",
"bearer_only": true,
"use_jwks": true,
"claim_validator": {
"audience": {
"required": true,
"match_with_client_id": true
}
},
"required_scopes": ["read:messages"],
"set_access_token_header": false,
"set_id_token_header": false,
"set_userinfo_header": false
},
"proxy-rewrite": {
"headers": {
"remove": ["Authorization"]
}
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:80": 1
}
}
}
EOF

The client_id value is set to the Auth0 API identifier so that APISIX can compare it with the token's audience. The M2M application's client ID is used only when requesting an access token.

bearer_only and use_jwks: Require a bearer access token and validate its JWT signature locally with the public keys published by Auth0.

claim_validator.audience: Requires the token's aud claim to match the Auth0 API identifier configured as client_id.

required_scopes: Requires the access token to include the permission granted to the M2M application.

set_access_token_header, set_id_token_header, and set_userinfo_header: Set to false to prevent APISIX from adding the access token, ID token, and token claims to upstream request headers.

proxy-rewrite.headers.remove: Removes the original bearer token before APISIX proxies the request. Review these header settings if the upstream application must receive the access token or its claims.

Verify M2M Authorization

Request an access token for the protected API from Auth0:

export AUTH0_ACCESS_TOKEN="$(
curl -sS "https://${AUTH0_DOMAIN}/oauth/token" \
-H "Content-Type: application/x-www-form-urlencoded" \
--data-urlencode "client_id=${AUTH0_M2M_CLIENT_ID}" \
--data-urlencode "client_secret=${AUTH0_M2M_CLIENT_SECRET}" \
--data-urlencode "audience=${AUTH0_API_AUDIENCE}" \
--data-urlencode "grant_type=client_credentials" | \
jq -er '.access_token'
)"

Send the access token to the protected route:

curl -i "http://127.0.0.1:9080/anything/m2m/get" \
-H "Authorization: Bearer ${AUTH0_ACCESS_TOKEN}"

An HTTP/1.1 200 OK response verifies that APISIX accepted a token issued for the protected API with the required permission. The response body should contain fields similar to these:

{
"args": {},
"data": "",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Host": "localhost",
"User-Agent": "curl/8.7.1",
"X-Amzn-Trace-Id": "Root=1-...",
"X-Forwarded-Host": "localhost:9080"
},
"json": null,
"method": "GET",
"origin": "192.168.155.1, xxx.xxx.xxx.xxx",
"url": "http://localhost:9080/anything/m2m/get"
}

Header values and the reported origin address vary by client and network environment. The upstream request headers should not include Authorization, X-Access-Token, X-Id-Token, or X-Userinfo because the route prevents them from being proxied.

Send the same request without a token:

curl -i "http://127.0.0.1:9080/anything/m2m/get"

APISIX should return an HTTP/1.1 401 Unauthorized response because the route requires a bearer token.

Next Steps

You have now configured APISIX to authorize M2M requests using access tokens and permissions from Auth0. For browser-based user authentication, see Set Up SSO with Auth0. See the openid-connect plugin reference for more token-validation and authorization options.