Skip to content

Latest commit

 

History

History
224 lines (188 loc) · 12.9 KB

openid-connect.md

File metadata and controls

224 lines (188 loc) · 12.9 KB
title
openid-connect

Summary

Name

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

Attributes

Name Type Requirement Default Valid Description
client_id string required OAuth client ID
client_secret string required OAuth client secret
discovery string required URL of the discovery endpoint of the identity server
scope string optional "openid" Scope used for the authentication
realm string optional "apisix" Realm used for the authentication
bearer_only boolean optional false Setting this true will check for the authorization header in the request with a bearer token
logout_path string optional "/logout"
redirect_uri string optional "ngx.var.request_uri"
timeout integer optional 3 [1,...] Timeout in seconds
ssl_verify boolean optional false
introspection_endpoint string optional URL of the token verification endpoint of the identity server
introspection_endpoint_auth_method string optional "client_secret_basic" Authentication method name for token introspection
public_key string optional The public key to verify the token
use_jwks boolean optional Use the jwks endpoint of the identity server to verify the token
token_signing_alg_values_expected string optional Algorithm used to sign the token
set_access_token_header boolean optional true Whether to ensure the access token is set in a request header.
access_token_in_authorization_header boolean optional false If set to true, ensure that the access token is set in the Authorization header, otherwise use the X-Access-Token header.
set_id_token_header boolean optional true Whether to ensure the ID token, if available, is set in the X-ID-Token request header.
set_userinfo_header boolean optional true Whether 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.

token introspection

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.