当前位置: 首页 > 工具软件 > OAuth Plugin > 使用案例 >

在Kong网关中使用OAuth2认证

锺超英
2023-12-01

在Kong网关中使用OAuth2认证

前言

Kong网关快速入门指南在Kong网关中使用JWT认证 一文中分别介绍了Key认证、HMAC认证和JWT认证,本文介绍在Kong网关中使用OAuth2认证。

说明:

  • 本文Kong的IP为192.168.0.102

在Kong上开启HTTPS

OAuth2认证要求必须以HTTPS方式访问Kong。

因此需要先在Kong上开启HTTPS。

Kong提供了ACME 的官方插件用来支持集成Lestencrypt的SSL证书。

在Plugins,添加全局插件 Security / ACME:

account email: `admin@xdevops.cn` # replace as your email

注意,不要再参考一些过时的文档手工生成Lestencrypt的SSL证书,并手工将证书放到服务器或容器中。

OAuth2认证

添加OAuth2插件

在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"
}

创建Consumer的OAuth2 credential

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_idclient_secret 后面在调用OAuth2相关接口时会用到。

测试OAuth2 Authorization Flow

获取Authorization Code

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"}

获取Access Token

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的默认有效时间为7200s,即2小时。
  • 在Access Token过期后,可以用Refresh Token重新获取Access Token。

用Access Token来调用接口

ACCESS_TOKEN=D0oeJF1vLfv8HeMN8YsV1Zz9aQ2rjZco

curl -X GET https://192.168.0.102:8443/demo/anything \
  -H "Authorization: Bearer ${ACCESS_TOKEN}" \
  --insecure

用Refresh Token来重新获取Access Token

在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
  

说明:

  • 为安全起见,Refresh Token是一次性的,一旦使用后就失效。

返回示例:

{
    "token_type": "bearer",
    "expires_in": 7200,
    "access_token": "icbdVoAQqyGBJsAk8eqy1GgV4R0BAAYb",
    "refresh_token": "MWqaWFUBBFA93KmWTcwfqpvtiPSWQ3ao"
}

与IDP集成

Kong OAuth2 插件只支持将Kong来作为OAuth2的Authorization Server,如果需要与外部IDP集成,还需要收费的OAuth2 Introspection 插件支持 

参考文档

 类似资料: