亚马逊AWS官方博客
通过Keycloak结合OAuth2.0协议进行AWS API Gateway鉴权
1. 简介
本文介绍了如何通过Keycloak,并结合AWS API Gateway内置的授权功能,完成对AWS资源请求的鉴权过程。API Gateway帮助开发者安全的的创建、发布、维护并管理API的访问。在中国区,由于Cognito仍未上线,因此使用Keycloak作为API调用的鉴权服务,具有重要的实际意义。
本文共分为四大模块:
简介:对Keycloak、OAuth2.0以及AWS API Gateway Authorizer进行了介绍;
配置说明:对环境的设定进行了详细的说明,包括DynamoDB的设定以及Keycloak环境的搭建和设置;
验证JWT Authorizer:通过Postman对API Gateway的授权功能进行验证;
总结:对全文的总结。
1.1 关于Keycloak
Keycloak是一个开源并广泛应用于用户身份管理与授权的解决方案。Keycloak支持多种协议和标准,包括OpenID Connect,OAuth2.0和SAML2.0。同时Keycloak可以集成与已有的LDAP或者Active Directory 服务集成,用于单点登录。基于OAuth2.0,Keycloak还可以通过JWT Token完成对API的鉴权,本文基于此场景,结合Keycloak通过AWS Gateway的Authorizer完成请求的鉴权。
1.2 关于OAuth2.0
OAuth2.0全称为Open Authorization 2.0,为用于鉴权的协议。通过OAuth协议,可以授权第三方应用请求用户的资源,而不需要资源的拥有者直接向第三方提供任何验证凭据信息。
OAuth2.0鉴权流程
1.3 关于AWS API Gateway Authorizer
在本文中,我们以HTTP API为例,利用HTTP API已内置的授权功能进行API请求的鉴权。如果使用REST API,则需要通过结合Lambda进行JWT Token的校验,可参照此说明文档进行配置。
2. 配置说明
在本设计中,用户通过调用API Gateway中定义好的API,访问AWS上的数据库资源。我们通过定义2个路由,并集成Lambda函数,完成对DynamoDB数据的读/写。
- GET /items:不需要进行鉴权,可以直接通过API Gateway获取DynamoDB数据。
- POST /items:需要进行鉴权,通过API Gateway校验请求Token,验证成功后,向DynamoDB写入数据。
2.2 预置条件
- 创建一个DynamoDB Table,DemoTable。
- 在AWS API Gateway创建HTTP API,并与Lambda进行集成。
DynomoDB设置
- 分区键:pk
- 排序键:sk
- 其他保留默认配置
API Gateway设置
创建API Gateway,为API Gateway创建2条路由,并关联Lambda函数,列表如下:
路由 | Lambda 函数名 | Runtime | Permission | 环境变量 | |
GET /items | GetItemsLambda | Python 3.9 | GetItemsLambdaRole | 键 | DDB_TABLE |
值 | demoDDB | ||||
POST /items | CreateItemsLambda | Python 3.9 | CreateItemsLambdaRole | 键 | DDB_TABLE |
值 | demoDDB |
Lambda函数样例
- GetItemsLambda
- GetItemsLambdaRole Policy:
- CreateItemsLambda:
- CreateItemsLambdaRole Policy:
2.3 Keycloak的设定
2.3.1 Keycloak的安装
关于Keycloak的安装,请参照blog:使用SAML和Keycloak建立AWS SSO登陆Console
2.3.2 Keycloak realm的建立
Realm 可以理解为域,用于管理用户、用户凭据、角色和用户组。通常我们需要在realm里创建client,不同的应用客户端应在realm中配置不同的client。当进行鉴权时,请求资源的应用客户端会向鉴权服务器请求Auth Code,正如上文中OAuth2.0鉴权流程 第2步所示。为了完成Keycloak realm的建立,我们可以:
- 登陆keycloak admin console,点击 “Administration Console”并登陆;
- 创建一个realm,并进入到realm中;
2.3.3 Keycloak Client的建立
- 在realm中点击“Configure-> Clients-> Create”;
- 按照下面的说明输入相关信息;注意选择Standard Flow Enabled,这将会使client的鉴权按照0的“Authorization Code Flow”完成,即OAuth2.0鉴权流程 所示。
注意,如没有特别的需求,尽量避免使用“Implicit Flow”即关闭“Implicit Flow Enabled”。这种方式没有授权码这个中间步骤,所以称为(授权码)”隐藏式”(implicit)。这将会把Token直接传给前端,是很不安全的,因此,只能用于一些安全要求不高的场景。
- 在“Credentials tab”中,选择Client Id and Secret,此时会生成一串随机字符串作为Secret。在上文中OAuth2.0鉴权流程 第6步中交换Token的过程中,Secret将作为client_secret的值,在应用客户端的POST Body中被发送到Keycloak Client中,以确保向Client交换的Token颁布给了正确的应用客户端。
2.3.4 Keycloak User的建立
- 创建测试用的User,点击左侧“Manage-> Users-> Add user”;
- 输入User信息;
- 设定密码,输入密码,并输入Password Confirmation,点击Reset Password以完成设置。
2.4 API Gateway Authorizer的设定
- 进入到上文创建的API Gateway中,由于我们的目的是在创建item时,需要进行API鉴权,因此只在POST /items的路由上附加授权方即可:
- 输入相关信息;
- 身份来源:通常情况下,在请求资源服务器时,会将JWT Token写入到请求头中的Authorization字段,因此可以保留默认。
- 发布者URL:针对Keycloak为https://{Keycloak_URL}/auth/realms/{realm}/
- 受众:关联的受众,此处输入account
3. 验证JWT Authorizer
3.1 请求Auth Code
- 根据OAuth2.0鉴权流程,当用户请求资源时,应用客户端将会向鉴权服务器发送GET请求,以请求Auth Code;
- 在此过程中,鉴权服务器将会返回Keycloak的登陆界面,要求用户输入其用户名密码,在此处,我们输入Keycloak User的建立章节中创建的User的用户名和密码。
- 输入正确的用户名和密码后,Keycloak将会通过Query String返回Auth Code,如下图所示;
3.2 交换JWT Token
- 接下来,我们通过Postman模仿应用客户端,模拟通过POST Auth Code换取JWT Token的过程;
- client_id: Keycloak的client ID,为Keycloak Client的建立 章节中创建;
- grant_type: 0的鉴权模式,我们通过authorization code模式鉴权,这也是最常见的模式;
- client_secret: 用于Client应用客户端的验证;
- code:Auth Code,由鉴权服务器返回,用于交换Token。
- 将Postman的请求用curl实现:
Response:
3.3 向API Gateway 请求创建资源
- 通过Postman模仿应用客户端,模拟创建item的过程;
- Authorization:将2中返回的
access_token
粘贴在Authorization header中,格式为:Bearer {access_token}
- 将Postman的请求用curl实现:
Response:
- 通过浏览器GET /item 查看item是否写入成功:
4. 总结
由于当前Cognito在中国区仍不可用,Keycloak可以作为一个替代方案,完成用户的单点登录和API的鉴权。本blog提供了如何结合API Gateway 的HTTP API,利用Keycloak和JWT进行API鉴权的演示。通过这种方式,应用客户端在请求AWS资源时,需要通过Keycloak服务器进行校验,并换取有效的JWT Token,以获得访问资源的权限。
如有兴趣了解本文提到的更多技术,请参照:
使用 SAML 和 Keycloak 建立 AWS SSO 登录 Console
How to secure API Gateway HTTP endpoints with JWT authorizer