Skip to main content
Version: 2.13

openid-connect

Description#

The OAuth 2 / Open ID Connect(OIDC) plugin provides authentication and introspection capability to APISIX.

Attributes#

NameTypeRequirementDefaultValidDescription
client_idstringrequiredOAuth client ID
client_secretstringrequiredOAuth client secret
discoverystringrequiredURL of the discovery endpoint of the identity server
scopestringoptional"openid"Scope used for the authentication
realmstringoptional"apisix"Realm used for the authentication
bearer_onlybooleanoptionalfalseSetting this true will check for the authorization header in the request with a bearer token
logout_pathstringoptional"/logout"
post_logout_redirect_uristringoptionalURL want to redirect when request logout_path
redirect_uristringoptional"ngx.var.request_uri"
timeoutintegeroptional3[1,...]Timeout in seconds
ssl_verifybooleanoptionalfalse
introspection_endpointstringoptionalURL of the token verification endpoint of the identity server
introspection_endpoint_auth_methodstringoptional"client_secret_basic"Authentication method name for token introspection
public_keystringoptionalThe public key to verify the token
use_jwksbooleanoptionalUse the jwks endpoint of the identity server to verify the token
token_signing_alg_values_expectedstringoptionalAlgorithm used to sign the token
set_access_token_headerbooleanoptionaltrueWhether to ensure the access token is set in a request header.
access_token_in_authorization_headerbooleanoptionalfalseIf set to true, ensure that the access token is set in the Authorization header, otherwise use the X-Access-Token header.
set_id_token_headerbooleanoptionaltrueWhether to ensure the ID token, if available, is set in the X-ID-Token request header.
set_userinfo_headerbooleanoptionaltrueWhether to ensure the UserInfo object, if available, is set in the X-Userinfo request header.

Modes of operation#

The plugin supports different modes of operation.

1) It can be configured to just validate an access token that is expected to be present in a request header. In this case, requests without a token or where the token is invalid are always rejected. This requires bearer_only be set to true and that either an introspection endpoint has been configured through introspection_endpoint, or that a public key has been configured through public_key. See the relevant sections below.

2) Alternatively, the plugin can also be configured to authenticate a request without a valid token against an identity provider by going through the OIDC Authorization Code flow. The plugin then acts as an OIDC Relying Party. In this scenario, when the requesting user has authenticated successfully, the plugin will obtain and manage an access token and further user claims on behalf of the user in a session cookie. Subsequent requests that contain the cookie will use the access token stored in the cookie. In this case, bearer_only must be set to false.

The first option is typically appropriate for service-to-service communication where the requesting side can be reasonably expected to obtain and manage a valid access token by itself. The second option is convenient to support web browser interaction with endpoints through a human user that may still need to be authenticated when accessing for the first time.

The plugin can also be configured to support both scenarios by setting bearer_only to false, but still configuring either an introspection endpoint or a public key. In this case, introspection of an existing token from a request header takes precedence over the Relying Party flow. That is, if a request contains an invalid token, the request will be rejected without redirecting to the ID provider to obtain a valid token.

The method used to authenticate a request also affects the headers that can be enforced on the request before sending it to upstream. The headers that can be enforced are mentioned below in each relevant section.

Token Introspection#

Token introspection helps to validate a request by verifying the token against an Oauth 2 authorization server. As prerequisite, you should create a trusted client in the identity server and generate a valid token(JWT) for introspection. The following image shows an example(successful) flow of the token introspection via the gateway.

The following is the curl command to enable the plugin to an external service. This route will protect https://httpbin.org/get(echo service) by introspecting the token provided in the header of the request.

curl http://127.0.0.1:9080/apisix/admin/routes/5 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"uri": "/get",
"plugins": {
"proxy-rewrite": {
"scheme": "https"
},
"openid-connect": {
"client_id": "api_six_client_id",
"client_secret": "client_secret_code",
"discovery": "full_URL_of_the_discovery_endpoint",
"introspection_endpoint": "full_URL_of_introspection_endpoint",
"bearer_only": true,
"realm": "master",
"introspection_endpoint_auth_method": "client_secret_basic"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:443": 1
}
}
}'

The following command can be used to access the new route.

curl -i -X GET http://127.0.0.1:9080/get -H "Host: httpbin.org" -H "Authorization: Bearer {replace_jwt_token}"

In this case, the plugin can enforce that the access token and the UserInfo object get set in respective configured request headers.

When the Oauth 2 authorization server returns an expire time with the token, the token will be cached in APISIX until it is expired. For more details, please read:

  1. lua-resty-openidc's doc and source code.
  2. exp field in the RFC's Introspection Response section.

Introspecting with public key#

You can also provide the public key of the JWT token to verify the token. In case if you have provided a public key and a token introspection endpoint, the public key workflow will be executed instead of verifying with the identity server. This method can be used if you want to reduce additional network calls and to speedup the process.

The following configurations shows how to add a public key introspection to a route.

curl http://127.0.0.1:9080/apisix/admin/routes/5 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"uri": "/get",
"plugins": {
"proxy-rewrite": {
"scheme": "https"
},
"openid-connect": {
"client_id": "api_six_client_id",
"client_secret": "client_secret_code",
"discovery": "full_URL_of_the_discovery_endpoint",
"bearer_only": true,
"realm": "master",
"token_signing_alg_values_expected": "RS256",
"public_key" : "-----BEGIN PUBLIC KEY-----
{public_key}
-----END PUBLIC KEY-----"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:443": 1
}
}
}'

In this case, the plugin can only enforce that the access token gets set in the configured request headers.

Authentication through OIDC Relying Party flow#

When an incoming request does not contain an access token in a header, nor in an appropriate session cookie, the plugin can act as an OIDC Relying Party and redirect to the authorization endpoint of the identity provider to go through the OIDC Authorization Code flow; see https://openid.net/specs/openid-connect-core-1_0.html#CodeFlowAuth. Once the user has authenticated against the identity provider, the plugin will obtain and manage an access token and further information from the identity provider on behalf of the user. The information is currently stored in a session cookie that the user agent can submit on subsequent requests. The plugin will recognize the cookie and use the information therein to avoid having to go through the flow again.

The following command adds this mode of operation to a route.

curl http://127.0.0.1:9080/apisix/admin/routes/5 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"uri": "/get",
"plugins": {
"proxy-rewrite": {
"scheme": "https"
},
"openid-connect": {
"client_id": "api_six_client_id",
"client_secret": "client_secret_code",
"discovery": "full_URL_of_the_discovery_endpoint",
"bearer_only": false,
"realm": "master"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:443": 1
}
}
}'

In this case, the plugin can enforce that the access token, the ID token, and the UserInfo object get set in respective configured request headers.

Troubleshooting#

Check/modify the DNS settings (conf/config.yaml) if APISIX cannot resolve/connect to the identity provider.