使用增强的自定义身份验证调用自定义授权方 - AWS IoT
AWS 文档中描述的 AWS 服务或功能可能因区域而异。要查看适用于中国区域的差异,请参阅中国的 AWS 服务入门

使用增强的自定义身份验证调用自定义授权方

此功能目前处于公开测试阶段,仅在美国东部(弗吉尼亚北部)区域中可用。

本部分介绍如何使用增强的自定义身份验证,通过使用 HTTP 标头和查询字符串或 MQTT 用户名和密码,将客户端凭证传递给自定义授权方。

使用传输层安全性 (TLS) 协议连接到 AWS IoT 的设备和客户端必须发送服务器名称指示 (SNI) TLS 扩展,带有与相应域配置的域匹配的值。如果您的域配置中的 allowAuthorizerOverride 值设置为 true,则可以指定不是默认授权方的自定义授权方。有关配置 SNI 扩展的更多信息,请参阅 AWS IoT 中的传输安全

要在 MQTT 连接中使用增强的自定义身份验证,客户端还必须发送应用层协议协商 (ALPN) TLS 扩展,具有值 mqtt 并在端口 443 上进行连接。

注意

您可以在 V2 AWS IoT 设备软件开发工具包中找到这些 TLS 扩展的配置。有关更多信息,请参阅 AWS Labs GitHub 存储库

HTTPS 请求

对自定义授权方的请求可以使用以下任一方式传递令牌:HTTP 标头,HTTP 发布请求中的查询字符串,或者用于建立 WSS 上的 MQTT 会话的 HTTP 升级请求。以下示例使用 HTTP 标头向 AWS IoT 设备网关发送升级请求。

GET /mqtt HTTP/1.1 Host: your-endpoint Upgrade: WebSocket Connection: Upgrades x-amz-customauthorizer-signature: token-signature token-key-name: some-token sec-WebSocket-Key: any random base64 value sec-websocket-protocol: mqtt sec-WebSocket-Version: websocket version

请求不包含 x-amz-customauthorizer-name 的值,因此 AWS IoT 使用在域配置中指定的默认授权方。如果在授权方上禁用了签名,则 x-amz-customauthorizer-signature 的值可选。

以下示例演示如何使用查询字符串参数发出相同的请求。

GET /mqtt?x-amz-customauthorizer-signature=${sign}&token-name=${token-value} HTTP/1.1 Host: your-endpoint Connection: Upgrade Upgrade: websocket sec-WebSocket-Key: any random base64 value sec-websocket-protocol: mqtt sec-WebSocket-Version: websocket version

MQTT 用户名和密码

您可以使用 MQTT 消息的 usernamepassword 字段,将用户名和密码传递给自定义授权方。密码数据采用 base64 编码以支持任意二进制值。username 值可以选择包含将其他值(包括令牌、签名和授权方名称)传递给授权方的查询字符串。

以下示例包含一个 username 字符串,其中带有指定令牌和签名的额外参数。您可以使用此方法,通过使用持有者令牌对 MQTT 连接进行身份验证。

username?x-amz-customauthorizer-name=${name}&x-amz-customauthorizer-signature=${sign}&token-name=${token-value}

发送给自定义授权方的数据

AWS IoT 发送到自定义授权方 Lambda 函数的数据取决于连接中存在哪些协议和参数。对于 HTTP 请求(发布和 WSS 升级),AWS IoT 发送所有标头和查询参数(最多 8 KB 数据)。对于 MQTT 连接上的 WSS 升级,AWS IoT 还会发送所有 MQTT 数据。

如果启用了签名并且请求包含令牌和签名,则 AWS IoT 不会触发您的自定义授权方的 Lambda 功能,除非可以解密令牌签名以匹配请求中提供的令牌。您可以使用此方法,以便连接到您的域的其他用户不会过度触发 Lambda 函数。

重要

我们强烈建议您使用 AWS IoT 提供的签名验证功能。

以下是 AWS IoT 发送到自定义授权方的 Lambda 函数的示例负载。AWS IoT 仅填充请求包含的字段。

{ "token" :"aToken", "signatureVerified": boolean, // Indicates whether the device gateway has validated the signature. "protocols": ["tls", "http", "mqtt"], // Indicates which protocols to expect. "protocolData": { "tls" : { "serverName": "serverName" // The SNI host_name string. }, "http": { "headers": { "#{name}": "#{value}" }, "queryString": "?#{name}=#{value}" }, "mqtt": { "username": "myUserName", "password": "myPassword", // base64 encoded. "clientId": "myClientId" // Provided only when the device sends it. } }, "connectionMetadata": { "id": UUID // The connection ID. You can use this for logging. }, }
注意

所有密码数据都采用 base64 编码,您的 Lambda 函数需要对其进行解码。

与常规自定义身份验证一样,自定义授权方必须返回一个响应,指示它是否已授权对 AWS IoT 的请求。以下是来自自定义授权方的成功响应示例。

{ "isAuthenticated":true, "principalId": "xxxxxxxx", "disconnectAfterInSeconds": 86400, "refreshAfterInSeconds": 300, "policyDocuments": [ "{ \"Version\": \"2012-10-17\", \"Statement\": [ { \"Action\": \"...\", \"Effect\": \"Allow|Deny\", \"Resource\": \"...\" } ] }" ] }

AWS IoT 缓存与委托人关联的策略,持续时间在 refreshAfterInSeconds 的值中指定。在此期间,将对后续调用授权而无需重新对设备进行身份验证。自定义身份验证期间发生的故障会导致身份验证失败,从而停止连接。