openid-connect

Description

The openid-connect Plugin provides authentication and introspection capability to APISIX with OpenID Connect.

Attributes

NameTypeRequiredDefaultValid valuesDescription
client_idstringTrueOAuth client ID.
client_secretstringTrueOAuth client secret.
discoverystringTrueDiscovery endpoint URL of the identity server.
scopestringFalse“openid”Scope used for authentication.
realmstringFalse“apisix”Realm used for authentication.
bearer_onlybooleanFalsefalseWhen set to true, the Plugin will check for if the authorization header in the request matches a bearer token.
logout_pathstringFalse“/logout”Path for logging out.
post_logout_redirect_uristringFalseURL to redirect to after logging out.
redirect_uristringFalse“ngx.var.request_uri”URI to which the identity provider redirects back to.
timeoutintegerFalse3[1,…]Request timeout time in seconds.
ssl_verifybooleanFalsefalseWhen set to true, verifies the identity provider’s SSL certificates.
introspection_endpointstringFalseURL of the token verification endpoint of the identity server.
introspection_endpoint_auth_methodstringFalse“client_secret_basic”Authentication method name for token introspection.
public_keystringFalsePublic key to verify the token.
use_jwksbooleanFalseWhen set to true, uses the JWKS endpoint of the identity server to verify the token.
token_signing_alg_values_expectedstringFalseAlgorithm used for signing the authentication token.
set_access_token_headerbooleanFalsetrueWhen set to true, sets the access token in a request header.
access_token_in_authorization_headerbooleanFalsefalseWhen set to true, sets the access token in the Authorization header. Otherwise, set the X-Access-Token header.
set_id_token_headerbooleanFalsetrueWhen set to true and the ID token is available, sets the ID token in the X-ID-Token request header.
set_userinfo_headerbooleanFalsetrueWhen set to true and the UserInfo object is available, sets it in the X-Userinfo request header.

Modes of operation

The openid-connect Plugin offers three modes of operation:

  1. The Plugin can be configured to just validate an access token that is expected to be present in a request header. In such cases, requests without a token or with an invalid token are rejected. This requires the bearer_only attribute to be set to true and either introspection_endpoint or public_key attribute to be configured. This mode of operation can be used for service-to-service communication where the requester can reasonably be expected to obtain and manage a valid token by itself.

  2. The Plugin can be configured to authenticate requests without a valid token against an identity provider through OIDC authorization. The Plugin then acts as an OIDC Relying Party. In such cases, after successful authentication, the Plugin obtains and manages an access token in a session cookie. Subsequent requests that contain the cookie will use the access token. This requires the bearer_only attribute to be set to false. This mode of operation can be used to support cases where the client or the requester is a human interacting through a web browser.

  3. The Plugin can also be configured to support both the scenarios by setting bearer_only to false and also configuring either the introspection_endpoint or public_key attribute. In such cases, 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, it 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 an Upstream service. You can learn more about this on the sections below.

Token introspection

Token introspection validates a request by verifying the token with an OAuth 2 authorization server.

You should first create a trusted client in the identity server and generate a valid JWT token for introspection.

The image below shows an example token introspection flow via a Gateway:

token introspection

The example below shows how you can enable the Plugin on Route. The Rouet below will protect the Upstream by introspecting the token provided in the request header:

  1. curl http://127.0.0.1:9080/apisix/admin/routes/5 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
  2. {
  3. "uri": "/get",
  4. "plugins": {
  5. "proxy-rewrite": {
  6. "scheme": "https"
  7. },
  8. "openid-connect": {
  9. "client_id": "api_six_client_id",
  10. "client_secret": "client_secret_code",
  11. "discovery": "full_URL_of_the_discovery_endpoint",
  12. "introspection_endpoint": "full_URL_of_introspection_endpoint",
  13. "bearer_only": true,
  14. "realm": "master",
  15. "introspection_endpoint_auth_method": "client_secret_basic"
  16. }
  17. },
  18. "upstream": {
  19. "type": "roundrobin",
  20. "nodes": {
  21. "httpbin.org:443": 1
  22. }
  23. }
  24. }'

Now, to access the Route:

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

In this example, the Plugin enforces that the access token and the Userinfo object be set in the request headers.

When the OAuth 2 authorization server returns an expire time with the token, it is cached in APISIX until expiry. For more details, read:

  1. lua-resty-openidc‘s documentation 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 for verification. If you have provided a public key and a token introspection endpoint, the public key workflow will be executed instead of verification through an identity server. This is useful if you want to reduce network calls and speedup the process.

The example below shows how you can add public key introspection to a Route:

  1. curl http://127.0.0.1:9080/apisix/admin/routes/5 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
  2. {
  3. "uri": "/get",
  4. "plugins": {
  5. "proxy-rewrite": {
  6. "scheme": "https"
  7. },
  8. "openid-connect": {
  9. "client_id": "api_six_client_id",
  10. "client_secret": "client_secret_code",
  11. "discovery": "full_URL_of_the_discovery_endpoint",
  12. "bearer_only": true,
  13. "realm": "master",
  14. "token_signing_alg_values_expected": "RS256",
  15. "public_key" : "-----BEGIN PUBLIC KEY-----
  16. {public_key}
  17. -----END PUBLIC KEY-----"
  18. }
  19. },
  20. "upstream": {
  21. "type": "roundrobin",
  22. "nodes": {
  23. "httpbin.org:443": 1
  24. }
  25. }
  26. }'

In this example, the Plugin can only enforce that the access token should be set in the request headers.

Authentication through OIDC Relying Party flow

When an incoming request does not contain an access token in its 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.

Once the user has authenticated with the identity provider, the Plugin will obtain and manage the access token and further interaction with the identity provider. The access token will be stored in a session cookie.

The example below adds the Plugin with this mode of operation to the Route:

  1. curl http://127.0.0.1:9080/apisix/admin/routes/5 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
  2. {
  3. "uri": "/get",
  4. "plugins": {
  5. "proxy-rewrite": {
  6. "scheme": "https"
  7. },
  8. "openid-connect": {
  9. "client_id": "api_six_client_id",
  10. "client_secret": "client_secret_code",
  11. "discovery": "full_URL_of_the_discovery_endpoint",
  12. "bearer_only": false,
  13. "realm": "master"
  14. }
  15. },
  16. "upstream": {
  17. "type": "roundrobin",
  18. "nodes": {
  19. "httpbin.org:443": 1
  20. }
  21. }
  22. }'

In this example, the Plugin can enforce that the access token, the ID token, and the UserInfo object to be set in the request headers.

Troubleshooting

If APISIX cannot resolve/connect to the identity provider, check/modify the DNS settings in your configuration file (conf/config.yaml).