mirror of
https://gitee.com/iresty/apisix.git
synced 2024-12-15 17:31:45 +08:00
222 lines
12 KiB
Markdown
222 lines
12 KiB
Markdown
---
|
|
title: openid-connect
|
|
---
|
|
|
|
<!--
|
|
#
|
|
# Licensed to the Apache Software Foundation (ASF) under one or more
|
|
# contributor license agreements. See the NOTICE file distributed with
|
|
# this work for additional information regarding copyright ownership.
|
|
# The ASF licenses this file to You under the Apache License, Version 2.0
|
|
# (the "License"); you may not use this file except in compliance with
|
|
# the License. You may obtain a copy of the License at
|
|
#
|
|
# http://www.apache.org/licenses/LICENSE-2.0
|
|
#
|
|
# Unless required by applicable law or agreed to in writing, software
|
|
# distributed under the License is distributed on an "AS IS" BASIS,
|
|
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
# See the License for the specific language governing permissions and
|
|
# limitations under the License.
|
|
#
|
|
-->
|
|
|
|
## Summary
|
|
|
|
- [**Name**](#name)
|
|
- [**Attributes**](#attributes)
|
|
- [**Modes of operation**](#modes-of-operation)
|
|
- [**Token Introspection**](#token-introspection)
|
|
- [**Introspecting with public key**](#introspecting-with-public-key)
|
|
- [**Troubleshooting**](#troubleshooting)
|
|
|
|
## 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.
|
|
|
|
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](../../../assets/images/plugin/oauth-1.png)
|
|
|
|
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.
|
|
|
|
```bash
|
|
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.
|
|
|
|
```bash
|
|
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](https://github.com/zmartzone/lua-resty-openidc)'s doc and source code.
|
|
2. `exp` field in the RFC's [Introspection Response](https://tools.ietf.org/html/rfc7662#section-2.2) 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.
|
|
|
|
```bash
|
|
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 CERTIFICATE-----
|
|
{public_key}
|
|
-----END CERTIFICATE-----"
|
|
}
|
|
},
|
|
"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.
|
|
|
|
```bash
|
|
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.
|