Signed-off-by: spacewander <spacewanderlzx@gmail.com>
12 KiB
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 | ||
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.
-
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 totrue
and that either an introspection endpoint has been configured throughintrospection_endpoint
, or that a public key has been configured throughpublic_key
. See the relevant sections below. -
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 tofalse
.
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:
- lua-resty-openidc's doc and source code.
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.