在Kong网关快速入门指南 和 在Kong网关中使用JWT认证 一文中分别介绍了Key认证、HMAC认证和JWT认证,本文介绍在Kong网关中使用OAuth2认证。
说明:
OAuth2认证要求必须以HTTPS方式访问Kong。
因此需要先在Kong上开启HTTPS。
Kong提供了ACME 的官方插件用来支持集成Lestencrypt的SSL证书。
在Plugins,添加全局插件 Security / ACME:
account email: `admin@xdevops.cn` # replace as your email
注意,不要再参考一些过时的文档手工生成Lestencrypt的SSL证书,并手工将证书放到服务器或容器中。
在Servicedemo
下添加Authentication / OAuth2插件。
scopes # 默认为空
mandatory scope: NO # 默认为NO,为了演示,不需要提供scope
provision key # 默认为空,由Kong自动生成,后续获取Authorization Code时需要提供
token expiration: 7200 # 默认为7200s,即2小时
enable authorization code: YES # 开启Authorization Code Flow
点击眼睛图标,查看OAuth2插件配置:
{
"name": "oauth2",
"protocols": [
"grpc",
"grpcs",
"http",
"https"
],
"consumer": null,
"route": null,
"id": "8896f8bd-97a3-4437-9925-876570b34d0a",
"enabled": true,
"config": {
"enable_client_credentials": false,
"provision_key": "vZyQ1sC9TJzeSRwdC1AGZBtKO2cirRIA",
"accept_http_if_already_terminated": false,
"enable_authorization_code": true,
"enable_password_grant": false,
"token_expiration": 7200,
"refresh_token_ttl": 1209600,
"pkce": "lax",
"reuse_refresh_token": false,
"enable_implicit_grant": false,
"auth_header_name": "authorization",
"mandatory_scope": false,
"global_credentials": false,
"anonymous": null,
"hide_credentials": false,
"scopes": null
},
"service": {
"id": "b7b00526-4a6b-4d47-9e70-5ff7fc151b48"
},
"created_at": 1626858267,
"tags": null
}
说明:
provision_key
在后面获取Authorization Code时需要提供。这时如果访问https://192.168.0.102:8443/demo/anything,会报错:
{
"error": "invalid_request",
"error_description": "The access token is missing"
}
为demo-app
的consumer创建OAuth2 credential:
name: `demo-app-oauth2`
client_id # 默认为空,由Kong自动生成
client_secret # 默认为空,由Kong自动生成
rediect_uris: `https://192.168.0.102:8443/demo` # press enter to apply
注意,如果redirect_uris
为空,会一直报错:
{
"error": "invalid_client",
"error_description": "Invalid client authentication"
}
参见:
点击眼睛图标,查看OAuth2 credential:
{
"name": "demo-app-oauth2",
"tags": null,
"consumer": {
"id": "c3202163-d7b8-4604-8137-466109590fd2"
},
"client_type": "confidential",
"id": "dfb22e8c-ab99-4806-8b3e-4007c8226c34",
"redirect_uris": [
"https://192.168.0.102:8443/demo"
],
"client_secret": "xpE2MnLzLefYfOOFgxg9EciRWuxLnIYA",
"created_at": 1626858574,
"hash_secret": false,
"client_id": "zVERERaGrmwEsCyL9TUzmx3nOYL5dXu5"
}
说明:
client_id
和 client_secret
后面在调用OAuth2相关接口时会用到。CLIENT_ID=zVERERaGrmwEsCyL9TUzmx3nOYL5dXu5
PROVISION_KEY=vZyQ1sC9TJzeSRwdC1AGZBtKO2cirRIA
curl -X POST \
--url "https://192.168.0.102:8443/demo/oauth2/authorize" \
--data "response_type=code" \
--data "client_id=${CLIENT_ID}" \
--data "provision_key=${PROVISION_KEY}" \
--data "authenticated_userid=demo-app" \
--insecure
说明:
--insecure
表示不校验SSL证书。如果在Postman中测试,需要先需要先打开Postman设置,关闭SSL certificate Verification。authenticated_userid
为授权的用户ID,这里设置为Consumer的customer id,也可以设置为任意值。返回结果示例:
{"redirect_uri":"https://192.168.0.102:8443/demo?code=U3uDrndMxBfNnCyWbInSEv3PYNBjPyJH"}
CLIENT_SECRET=xpE2MnLzLefYfOOFgxg9EciRWuxLnIYA
curl -X POST \
--url "https://192.168.0.102:8443/demo/oauth2/token" \
--data "grant_type=authorization_code" \
--data "client_id=${CLIENT_ID}" \
--data "client_secret=${CLIENT_SECRET}" \
--data "code=U3uDrndMxBfNnCyWbInSEv3PYNBjPyJH" \
--insecure
说明:
code
为”获取Authorization Code这一步的返回值的redirect_uri
里面的code
。code
(Authroization Code)是一次性的,一旦使用后就失效。返回结果示例:
{
"token_type": "bearer",
"expires_in": 7200,
"access_token": "D0oeJF1vLfv8HeMN8YsV1Zz9aQ2rjZco",
"refresh_token": "VMV3N5wUHbPMhzMGG1Z86uns8yI1DEDv"
}
说明:
ACCESS_TOKEN=D0oeJF1vLfv8HeMN8YsV1Zz9aQ2rjZco
curl -X GET https://192.168.0.102:8443/demo/anything \
-H "Authorization: Bearer ${ACCESS_TOKEN}" \
--insecure
在Access Token过期后,可以用Refresh Token重新获取Access Token。
REFRESH_TOKEN=VMV3N5wUHbPMhzMGG1Z86uns8yI1DEDv
curl -X POST \
--url "https://192.168.0.102:8443/demo/oauth2/token" \
--data "grant_type=refresh_token" \
--data "client_id=${CLIENT_ID}" \
--data "client_secret=${CLIENT_SECRET}" \
--data "refresh_token=${REFRESH_TOKEN}" \
--insecure
说明:
返回示例:
{
"token_type": "bearer",
"expires_in": 7200,
"access_token": "icbdVoAQqyGBJsAk8eqy1GgV4R0BAAYb",
"refresh_token": "MWqaWFUBBFA93KmWTcwfqpvtiPSWQ3ao"
}
Kong OAuth2 插件只支持将Kong来作为OAuth2的Authorization Server,如果需要与外部IDP集成,还需要收费的OAuth2 Introspection 插件支持