openid-connect
#
DescriptionOpenID Connect (OIDC) is an authentication protocol based on the OAuth 2.0. It allows the client to obtain user information from the identity provider (IdP), e.g., Keycloak, Ory Hydra, Okta, Auth0, etc. API Gateway Apache APISIX supports to integrate with the above identity providers to protect your APIs.
#
AttributesName | Type | Required | Default | Valid values | Description |
---|---|---|---|---|---|
client_id | string | True | OAuth client ID. | ||
client_secret | string | True | OAuth client secret. | ||
discovery | string | True | Discovery endpoint URL of the identity server. | ||
scope | string | False | "openid" | Scope used for authentication. | |
realm | string | False | "apisix" | Realm used for authentication. | |
bearer_only | boolean | False | false | When set to true , APISIX will only check if the authorization header in the request matches a bearer token. | |
logout_path | string | False | "/logout" | Path for logging out. | |
post_logout_redirect_uri | string | False | URL to redirect to after logging out. | ||
redirect_uri | string | False | "ngx.var.request_uri" | URI to which the identity provider redirects back to. | |
timeout | integer | False | 3 | [1,...] | Request timeout time in seconds. |
ssl_verify | boolean | False | false | When set to true, verifies the identity provider's SSL certificates. | |
introspection_endpoint | string | False | URL of the token verification endpoint of the identity server. | ||
introspection_endpoint_auth_method | string | False | "client_secret_basic" | Authentication method name for token introspection. | |
token_endpoint_auth_method | string | False | Authentication method name for token endpoint. The default will get the first supported method specified by the OP. | ||
public_key | string | False | Public key to verify the token. | ||
use_jwks | boolean | False | false | When set to true , uses the JWKS endpoint of the identity server to verify the token. | |
use_pkce | boolean | False | false | when set to true , the "Proof Key for Code Exchange" as defined in RFC 7636 will be used. | |
token_signing_alg_values_expected | string | False | Algorithm used for signing the authentication token. | ||
set_access_token_header | boolean | False | true | When set to true, sets the access token in a request header. | |
access_token_in_authorization_header | boolean | False | false | When set to true, sets the access token in the Authorization header. Otherwise, set the X-Access-Token header. | |
set_id_token_header | boolean | False | true | When set to true and the ID token is available, sets the ID token in the X-ID-Token request header. | |
set_userinfo_header | boolean | False | true | When set to true and the UserInfo object is available, sets it in the X-Userinfo request header. | |
set_refresh_token_header | boolean | False | false | When set to true and a refresh token object is available, sets it in the X-Refresh-Token request header. | |
session | object | False | When bearer_only is set to false, openid-connect will use Authorization Code flow to authenticate on the IDP, so you need to set the session-related configuration. | ||
session.secret | string | True | Automatic generation | 16 or more characters | The key used for session encrypt and HMAC operation. |
unauth_action | string | False | "auth" | Specify the response type on unauthenticated requests. "auth" redirects to identity provider, "deny" results in a 401 response, "pass" will allow the request without authentication. | |
proxy_opts | object | False | HTTP proxy server be used to access identity server. | ||
proxy_opts.proxy_opts.http_proxy | string | False | http://proxy-server:port | HTTP proxy server address. | |
proxy_opts.proxy_opts.https_proxy | string | False | http://proxy-server:port | HTTPS proxy server address. | |
proxy_opts.http_proxy_authorization | string | False | Basic [base64 username:password] | Default Proxy-Authorization header value to be used with http_proxy . | |
proxy_opts.https_proxy_authorization | string | False | Basic [base64 username:password] | As http_proxy_authorization but for use with https_proxy (since with HTTPS the authorisation is done when connecting, this one cannot be overridden by passing the Proxy-Authorization request header). | |
proxy_opts.no_proxy | string | False | Comma separated list of hosts that should not be proxied. |
NOTE: encrypt_fields = {"client_secret"}
is also defined in the schema, which means that the field will be stored encrypted in etcd. See encrypted storage fields.
#
Scenariostip
This plugin offers two scenorios:
Authentication between Services: Set
bearer_only
totrue
and configure theintrospection_endpoint
orpublic_key
attribute. In this scenario, APISIX will reject requests without a token or invalid token in the request header.Authentication between Browser and Identity Providers: Set
bearer_only
tofalse.
After successful authentication, this plugin can obtain and manage the token in the cookie, and subsequent requests will use the token. In this mode, the user session will be stored in the browser as a cookie and this data is encrypted, so you have to set a key for encryption viasession.secret
.
#
Token introspectionToken introspection validates a request by verifying the token with an OAuth 2.0 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:
The example below shows how you can enable the Plugin on Route. The Route below will protect the Upstream by introspecting the token provided in the request header:
curl http://127.0.0.1:9180/apisix/admin/routes/5 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"uri": "/get",
"plugins":{
"openid-connect":{
"client_id": "${CLIENT_ID}",
"client_secret": "${CLIENT_SECRET}",
"discovery": "${DISCOVERY_ENDPOINT}",
"introspection_endpoint": "${INTROSPECTION_ENDPOINT}",
"bearer_only": true,
"realm": "master",
"introspection_endpoint_auth_method": "client_secret_basic"
}
},
"upstream":{
"type": "roundrobin",
"nodes":{
"httpbin.org:443":1
}
}
}'
Now, to access the Route:
curl -i -X GET http://127.0.0.1:9080/get -H "Host: httpbin.org" -H "Authorization: Bearer {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.0 authorization server returns an expire time with the token, it is cached in APISIX until expiry. For more details, read:
- lua-resty-openidc's documentation and source code.
exp
field in the RFC's Introspection Response section.
#
Introspecting with public keyYou 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:
curl http://127.0.0.1:9180/apisix/admin/routes/5 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"uri": "/get",
"plugins":{
"openid-connect":{
"client_id": "${CLIENT_ID}",
"client_secret": "${CLIENT_SECRET}",
"discovery": "${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 example, the Plugin can only enforce that the access token should be set in the request headers.
#
Authentication through OIDC Relying Party flowWhen 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:
curl http://127.0.0.1:9180/apisix/admin/routes/5 -H 'X-API-KEY: edd1c9f034335f136f87ad84b625c8f1' -X PUT -d '
{
"uri": "/get",
"plugins": {
"openid-connect": {
"client_id": "${CLIENT_ID}",
"client_secret": "${CLIENT_SECRET}",
"discovery": "${DISCOVERY_ENDPOINT}",
"bearer_only": false,
"realm": "master"
}
},
"upstream": {
"type": "roundrobin",
"nodes": {
"httpbin.org:443": 1
}
}
}'
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.
#
TroubleshootingIf APISIX cannot resolve/connect to the identity provider (e.g., Okta, Keycloak, Authing), check/modify the DNS settings in your configuration file (
conf/config.yaml
).If you encounter the error
the error request to the redirect_uri path, but there's no session state found,
please confirm whether the currently accessed URL carriescode
andstate,
and do not directly accessredirect_uri.
If you encounter the error
the error request to the redirect_uri path, but there's no session state found
, please check theredirect_uri
attribute : APISIX will initiate an authentication request to the identity provider, after the authentication service completes the authentication and authorization logic, it will redirect to the address configured byredirect_uri
(e.g.,http://127.0.0.1:9080/callback
) with ID Token and AccessToken, and then enter APISIX again and complete the function of token exchange in OIDC logic. Theredirect_uri
attribute needs to meet the following conditions:
redirect_uri
needs to be captured by the route where the current APISIX is located. For example, theuri
of the current route is/api/v1/*
,redirect_uri
can be filled in as/api/v1/callback
;scheme
andhost
ofredirect_uri
(scheme:host
) are the values required to access APISIX from the perspective of the identity provider.