All Products
Search
Document Center

Microservices Engine:OAuth plug-in

Last Updated:Mar 11, 2026

The OAuth plug-in issues OAuth 2.0 access tokens as JSON Web Tokens (JWTs) that comply with RFC 9068. Use this plug-in to authenticate API consumers with the Client Credentials grant type on the MSE cloud-native gateway.

Plug-in type: Authentication

How it works

The OAuth plug-in handles two responsibilities: token issuance and request authentication.

  1. A consumer sends a token request with its client_id and client_secret to the gateway's token endpoint (default: /oauth2/token).

  2. The gateway validates the credentials against the configured consumers list and issues a signed JWT.

  3. The consumer includes the JWT in subsequent API requests via the Authorization: Bearer <token> header.

  4. The gateway verifies the JWT signature, expiration, and clock skew before forwarding the request to the backend service.

  5. After successful authentication, the gateway adds an X-Mse-Consumer header to the upstream request, identifying the consumer.

Important

The examples in this topic use the Client Credentials grant type (client_credentials).

Configuration fields

Authorization settings

FieldTypeRequiredDefaultDescription
consumersarray of objectYes-Consumers authorized to request tokens. See Consumer fields for the object schema.
issuerstringNoHigress-GatewayValue of the iss claim in issued JWTs.
auth_pathstringNo/oauth2/tokenPath suffix that triggers token issuance instead of request forwarding. When configured at the route level, the route must match this path. If you use the API management feature, create an API with the same path.
global_credentialsboolNotrueWhen true, a token issued on any route is accepted by all routes that share the same plug-in configuration. When false, tokens are scoped to the route that issued them.
auth_header_namestringNoAuthorizationRequest header from which the gateway reads the JWT.
token_ttlnumberNo7200Token time to live (TTL) in seconds.
clock_skew_secondsnumberNo60Allowed clock skew in seconds when validating the exp and iat claims.
keep_tokenboolNotrueWhen true, the JWT is retained in the request forwarded to the backend service. Set to false to strip the token before forwarding.
global_autharray of stringNo (required for instance-level configurations)-Instance-level only. When set to true, authentication applies to all routes and domain names. When set to false, authentication applies only to routes and domain names that have the plug-in configured. If omitted, authentication applies globally only when no route- or domain-level configuration exists.

Consumer fields

Each object in the consumers array requires these fields:

FieldTypeRequiredDescription
namestringYesUnique consumer name. This value appears in the X-Mse-Consumer upstream header after authentication.
client_idstringYesOAuth 2.0 client identifier.
client_secretstringYesOAuth 2.0 client secret.

Access control (route or domain level)

Configure the allow field at the route or domain level to restrict which consumers can access specific routes or domain names.

FieldTypeRequiredDescription
allowarray of stringNo (route or domain level only)List of consumer names permitted to access the route or domain. Not configurable at the instance level.
Important

The allow field and the consumers field cannot coexist in the same configuration rule. Define consumers at the instance level, then use allow at the route or domain level.

Token endpoint behavior

Important
  • When a route has the plug-in enabled and the request path matches auth_path, the gateway issues a token instead of forwarding the request to the backend service.

  • If global_credentials is false, do not use exact match on the route with the plug-in enabled. A coexisting route that uses prefix match may cause unexpected behavior.

Configuration examples

Route-scoped tokens

Apply this configuration to both route-a and route-b:

consumers:
- name: consumer1
  client_id: 12345678-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  client_secret: abcdefgh-xxxx-xxxx-xxxx-xxxxxxxxxxxx

With this setup, a token issued through route-a is valid only for route-a. The same token cannot access route-b, and vice versa.

Shared tokens across routes

To share tokens across all routes that use the same configuration, set global_credentials to true:

global_credentials: true
consumers:
- name: consumer1
  client_id: 12345678-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  client_secret: abcdefgh-xxxx-xxxx-xxxx-xxxxxxxxxxxx

A token issued on any route is now accepted by all routes sharing this configuration.

Instance-level consumers with route-level access control

Define consumers at the instance level and restrict access per route or domain.

Instance-level configuration:

global_auth: false
consumers:
- name: consumer1
  client_id: 12345678-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  client_secret: abcdefgh-xxxx-xxxx-xxxx-xxxxxxxxxxxx
- name: consumer2
  client_id: 87654321-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  client_secret: hgfedcba-xxxx-xxxx-xxxx-xxxxxxxxxxxx

Route-level configuration (applied to route-a and route-b):

allow:
- consumer1

Domain-level configuration (applied to *.example.com and test.com):

allow:
- consumer2

In this setup:

  • Requests matching route-a or route-b are accessible only to consumer1.

  • Requests matching *.example.com or test.com are accessible only to consumer2.

  • All other consumers are denied access.

  • If a JWT matches multiple JSON Web Key Sets (JWKSs), the first matching consumer in the configuration sequence takes precedence.

Gateway-wide authentication

Require all requests to authenticate before reaching any backend service:

global_auth: true
consumers:
- name: consumer1
  client_id: 12345678-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  client_secret: abcdefgh-xxxx-xxxx-xxxx-xxxxxxxxxxxx
- name: consumer2
  client_id: 87654321-xxxx-xxxx-xxxx-xxxxxxxxxxxx
  client_secret: hgfedcba-xxxx-xxxx-xxxx-xxxxxxxxxxxx

Request examples

All examples use the Client Credentials grant type to obtain an access token, then use the token to call a protected API.

Obtain an access token

GET request (recommended):

curl 'http://test.com/oauth2/token?grant_type=client_credentials&client_id=12345678-xxxx-xxxx-xxxx-xxxxxxxxxxxx&client_secret=abcdefgh-xxxx-xxxx-xxxx-xxxxxxxxxxxx'

POST request:

curl 'http://test.com/oauth2/token' \
  -H 'content-type: application/x-www-form-urlencoded' \
  -d 'grant_type=client_credentials&client_id=12345678-xxxx-xxxx-xxxx-xxxxxxxxxxxx&client_secret=abcdefgh-xxxx-xxxx-xxxx-xxxxxxxxxxxx'
Note

The POST method requires a route that points to a real backend service. Otherwise, the gateway does not read the request body.

Response:

{
  "token_type": "bearer",
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6ImFwcGxpY2F0aW9uXC9hdCtqd3QifQ.eyJhdWQiOiJkZWZhdWx0IiwiY2xpZW50X2lkIjoiMTIzNDU2NzgteHh4eC14eHh4LXh4eHgteHh4eHh4eHh4eHh4IiwiZXhwIjoxNjg3OTUxNDYzLCJpYXQiOjE2ODc5NDQyNjMsImlzcyI6IkhpZ3Jlc3MtR2F0ZXdheSIsImp0aSI6IjEwOTU5ZDFiLThkNjEtNGRlYy1iZWE3LTk0ODEwMzc1YjYzYyIsInN1YiI6ImNvbnN1bWVyMSJ9.NkT_rG3DcV9543vBQgneVqoGfIhVeOuUBwLJJ4Wycb0",
  "expires_in": 7200
}
FieldDescription
token_typeToken type. Always bearer.
access_tokenSigned JWT. Include this value in the Authorization header for subsequent requests.
expires_inToken validity period in seconds. Matches the configured token_ttl (default: 7200).

Call a protected API

Include the access token in the Authorization header:

curl 'http://test.com' \
  -H 'Authorization: Bearer eyJhbGciOiJIUzI1NiIsInR5cCI6ImFwcGxpY2F0aW9uXC9hdCtqd3QifQ.eyJhdWQiOiJkZWZhdWx0IiwiY2xpZW50X2lkIjoiMTIzNDU2NzgteHh4eC14eHh4LXh4eHgteHh4eHh4eHh4eHh4IiwiZXhwIjoxNjg3OTUxNDYzLCJpYXQiOjE2ODc5NDQyNjMsImlzcyI6IkhpZ3Jlc3MtR2F0ZXdheSIsImp0aSI6IjEwOTU5ZDFiLThkNjEtNGRlYy1iZWE3LTk0ODEwMzc1YjYzYyIsInN1YiI6ImNvbnN1bWVyMSJ9.NkT_rG3DcV9543vBQgneVqoGfIhVeOuUBwLJJ4Wycb0'

Upstream headers

After successful authentication, the gateway adds the following header to the request forwarded to the backend service:

HeaderDescription
X-Mse-ConsumerThe name of the authenticated consumer. Use this header in your backend service to identify which consumer sent the request and implement consumer-specific logic.

Error codes

HTTP status codeError messageCauseWhat to check
401Invalid Jwt token.The request has no JWT, the JWT format is invalid, or the JWT has expired.Verify that the Authorization header contains a valid Bearer <token> value. Check whether the token has exceeded its token_ttl. If the error occurs near token expiration boundaries, increase clock_skew_seconds.
403Access Denied.The consumer is authenticated but not authorized to access the requested route or domain.Check the allow list on the target route or domain configuration. Make sure the consumer's name is included.