使用AWS_IAM授权对AWS WebSocket API网关的请求

时间:2020-01-29 09:56:35

标签: amazon-web-services websocket aws-api-gateway amazon-iam api-gateway

我已经使用WebSocket协议设置了API网关。在“ $ connect”路由请求设置上,我选择了“ AWS_IAM”作为授权方法。用户通过Cognito登录后,Web应用程序需要与此WebSocket API建立连接。然后如何通过Web应用程序上的JavaScript授权WebSocket API请求?使用HTTP API网关,我可以根据访问密钥和会话令牌生成签名,这些签名已传递到请求标头中。但是我无法在WebSocket请求中传递标头。

3 个答案:

答案 0 :(得分:2)

我从AWS支持部门得到了答案。我将需要签署wss URL。因此,签名信息将传递给查询字符串参数中的url,而不是在HTTP请求中设置请求标头。签名的wss URL看起来像:wss://API_ID.execute-api.region.amazonaws.com/dev?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=ACCESSKEY/20200131/region/execute-api/aws4_request&X-Amz-Date=20200131T100233Z&X-Amz-Security-Token=SECURITY_TOKEN&X-Amz-SignedHeaders=host&X-Amz-Signature=SIGNATURE

要生成签名的URL,可以使用@ aws-amplify / core库中的Signer.signUrl方法。

答案 1 :(得分:2)

这是一些对我有用的示例/伪代码:

使用AWS Amplify身份验证用户:

import { w3cwebsocket as W3CWebSocket } from "websocket"
import { Auth, Signer } from "aws-amplify"

let wsClient: any = null

export const client = async () => {
  if (wsClient) return wsClient

  if ((await Auth.currentUserInfo()) === null) return wsClient

  const credentials = await Auth.currentCredentials()

  const accessInfo = {
    access_key: credentials.accessKeyId,
    secret_key: credentials.secretAccessKey,
    session_token: credentials.sessionToken,
  }

  const wssUrl = "wss://YOUR-API-ID.execute-api.REGION.amazonaws.com/dev"

  const signedUrl = Signer.signUrl(wssUrl, accessInfo)

  wsClient = new W3CWebSocket(signedUrl)

  wsClient.onerror = function () {
    console.log("[client]: Connection Error")
  }

  wsClient.onopen = function () {
    console.log("[client]: WebSocket Client Connected")
  }

  wsClient.onclose = function () {
    console.log("[client]: Client Closed")
  }

  wsClient.onmessage = function (e: any) {
    if (typeof e.data === "string") {
      console.log("Received: '" + e.data + "'")
    }
  }

  return wsClient
}

然后还使用AWS Cognito需要此权限:

{
  "Action": ["execute-api:Invoke"],
  "Resource": "arn:aws:execute-api:REGION:ACCOUNT-ID-OR-WILDCARD:*/*/$connect",
  "Effect": "Allow"
}

答案 2 :(得分:0)

我实现了此 Dart 代码,用于签署 AWS 请求 URL。这对于连接到受 IAM 保护的 WebSocket API 网关特别有用。

https://github.com/MohammedNoureldin/aws-url-signer

我知道不鼓励在答案中放置链接,但是在这里复制整个 100 行代码是没有意义的。

我的实现的用法如下所示:

String getSignedWebSocketUrl(
    {String apiId,
    String region,
    String stage,
    String accessKey,
    String secretKey,
    String sessionToken})