如何使用node.js解码和验证AWS SigV4请求的签名 我的设置

如何使用node.js解码和验证AWS SigV4请求的签名 我的设置,node.js,amazon-web-services,aws-api-gateway,amazon-iam,aws-iam-authenticator,Node.js,Amazon Web Services,Aws Api Gateway,Amazon Iam,Aws Iam Authenticator,我有一个对api网关端点的请求,该端点使用AWS Sigv4签名 请求的标题如下所示 { "host": "localhost:3100", "connection": "keep-alive", "content-length": "78", "sec-ch-ua": "\"Google Chrome\";v=

我有一个对api网关端点的请求,该端点使用AWS Sigv4签名

请求的标题如下所示

{
  "host": "localhost:3100",
  "connection": "keep-alive",
  "content-length": "78",
  "sec-ch-ua": "\"Google Chrome\";v=\"87\", \" Not;A Brand\";v=\"99\", \"Chromium\";v=\"87\"",
  "sec-ch-ua-mobile": "?0",
  "authorization": "AWS4-HMAC-SHA256 Credential=ASIA2DP7X6SIMAVM65UJ/20201223/ap-southeast-1/execute-api/aws4_request, SignedHeaders=accept;content-length;content-type;host;x-amz-date;x-amz-security-token, Signature=edc00f240870f9f1e0e8fc66f1ef98c3dac4bfbc1f1a8ab36dacc4b68b32b2a3",
  "content-type": "application/json",
  "accept": "*/*",
  "user-agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 11_1_0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4280.88 Safari/537.36",
  "x-amz-security-token": "IQoJb3JpZ2luX2VjEAwaDmFwLXNvdXRoZWFzdC0xIkYwRAIgF+XX6C0F+P5XgVewIKXVvPt+ahQkHVOj6rHPC5nzAaQCIEq8ldeNs5vv1xvt76Fl+osd/cPZZTbjhrDCYJqeyy7mKqEGCLX//////////wEQABoMNjk0NzEwNDMyOTEyIgyGVcLvP4mHok3ZyIQq9QUBEp/j5AeqnRV6D3IEl4dCiLUhdJaTLX+8JdBinM3eiTSyAlOQUucsNStudFc4qMVPztBnBFpx7diDDjh9FqM3Wx+Xs+qTfWIP6s3dgZioPh+M526e7SUiI4aoSjBhmDzrzAgoVvI5azbNCl3nvfONC7uvGzQC8zZc/W+4/1icnny6vuaooZnQUZn3t8GHasfepVJ1zcDjUUN+76cw+txiuBB7mzoFhnhfvEEDdN1aHgZoMUAYWUhvlAq+gLZa8CdwX4mThkpZodf6t04n8QLkqRmUb1KQd0sG4Vux6OzXbO+j3mtgasbHEtxS7kM2ZY++ZYG9A5tyNhXSxfjtk6HkpaEi5WOHTfH94fk8/VG5gmPj19z48uBoxa1ct4jThsrg81kmcrC00gbNwrXqHh4l0/4ufAvfuO8MWxvHqkXks6U2WU4rzu0QVhSg2cIxHP7mH1FQyYAA31D1Pz23QpYB45o6TppSa/j8VmzsYZ8NCn+fwuVeP7RCxzic0YWdbKc1d5Ts0ID9M8Pg+d/0CgJSVfrlBD0QOytIjLbhvFAwkSJeiDk/Mw6rI4nRNXtQy2EgoUsspaTo4buePIr/eflEUm1dpAEu33CX0TzUhszFmFmq8lLFlQUEl1VKVvw6Jdz0x8uhX2vdT33ixnpavQpWXA3eKu4RVuzSIyvat+OhQX7ywIzpyhbcSsIQR+zq62RfM7RDd6iNG41tzBPNk/dQpJhBmMJdqQE8fX4Uw2PgJaEGEyyFRpvYMT2OtMG+2CUNj6FiyTSCsa00H+ZKR/knXRXhnyHmOdDsQDbbgPjdr5wougoQTxx5BPk9/6lOSXdsGhg9oT1FkOsGOIZgoaaRA+cRvMAzMERQd4hAboeqGmuoP+7dAwgE4QcwChx+vK3kdCWQ8MRfeYs3MQTWvd4R9fx0VOeCfza0nYBEqqsfBs2YBCDYPHJl9nNKU8xrspn1kDnQ03m3P1hwM81FqmuNXpZaTiUnDjHj+sWSDE0e/6f023UzMNWKi/8FOogCS99u4WOLBdmKnHFptz2yH8fM9ewGniGeSE6J40rRxRmGKjfoBiipYeY2XQgRE5TLzxO5RlqRxgcYQ+Y4fddYR66hjQSi0YJPe30aPNgXNolvmabeh5mi17NEeeNklauHeuM1Te81N8dnZSYiubxtpiwbb3EyTZhmM/mi3w22hfQcz+ufrtwZYjBlzCYc+szynuRS5mbS4HnwPhIgeyZyrpPWW/mDwXjWPnV437Cp2654UZkaWi0/HTHuwcnNs0JEOZ81cq9LXwqCUYqyjHzWf25JSTn06q/kVVhW8RZgULDabEcvl3DKgG6dau+dK2sTbVwmOKGHw7lsx2RrCmbA1gqjscOb9zt3",
  "x-amz-date": "20201223T041933Z",
  "origin": "http://localhost:3000",
  "sec-fetch-site": "same-site",
  "sec-fetch-mode": "cors",
  "sec-fetch-dest": "empty",
  "referer": "http://localhost:3000/",
  "accept-encoding": "gzip, deflate, br",
  "accept-language": "en,en-US;q=0.9"
}
当我运行“向api端点添加IAM授权人”时,我看到AWS验证了该签名,如下所示

{
  "identity": {
    "cognitoIdentityPoolId": "ap-southeast-1:776d43fa-1a9a-4911-b06c-8a6580ae1bcd",
    "accountId": "694710432912",
    "cognitoIdentityId": "ap-southeast-1:053f57cd-6a21-486d-b4b5-5fd27e17420b",
    "caller": "AROA2DP7X6SILQ2KYY6MJ:CognitoIdentityCredentials",
    "sourceIp": "103.252.202.229",
    "principalOrgId": null,
    "accessKey": "ASIA2DP7X6SIGUWRHSN3",
    "cognitoAuthenticationType": "unauthenticated",
    "cognitoAuthenticationProvider": null,
    "userArn": "arn:aws:sts::694710432912:assumed-role/Cognito_MyPoolUnauth_Role/CognitoIdentityCredentials",
    "userAgent": "PostmanRuntime/7.26.8",
    "user": "AROA2DP7X6SILQ2KYY6MJ:CognitoIdentityCredentials"
  }
}
我的问题 我可以用nodejs(typescript)自己验证签名吗? 任何对这些头进行解码以产生这样一个标识的脚本示例都将非常棒

我为什么要这么做
用于在本地模拟我的api和授权逻辑。此外,我可能想在网关中试用自定义lambda授权程序,而不是默认的AWS IAM授权程序(以便对授权逻辑进行更多控制)。

对您的问题的回答有点复杂。简言之:是的,你可以!较长的答案是:从技术上讲是可能的,但在实践中却不是

签名过程非常简单。它是完全记录在案的。要验证签名(授权标题),只需重复该过程并检查结果是否等于标题中的签名。问题是:要重复此过程,您必须拥有
访问密钥\u ID
机密访问密钥。您可以使用AWS主体访问密钥和密码使其工作。但是您使用的是Cognito身份池,在这种情况下,您将永远无法访问
SECRET\u access\u KEY

如果您的意图只是在本地模仿您的逻辑,那么它将起作用。但如果你允许,我建议不要在家里尝试。如果您的目的只是模拟逻辑,那么简单的方法是绕过API网关,并使用“解码/模拟”标识令牌将一个关于API网关事件格式的模拟对象直接发送到函数


另一件事:如果您使用Cognito标识池(您正在使用的)移动到自定义授权器,您将需要手动执行许多任务,例如验证签名和解码标识令牌(我相信这是
x-amz-security-token
的内容)。总之,您需要手动执行IAM授权人执行的所有任务。

对您的问题的回答有点复杂。简言之:是的,你可以!较长的答案是:从技术上讲是可能的,但在实践中却不是

签名过程非常简单。它是完全记录在案的。要验证签名(授权
标题),只需重复该过程并检查结果是否等于标题中的签名。问题是:要重复此过程,您必须拥有
访问密钥\u ID
机密访问密钥。您可以使用AWS主体访问密钥和密码使其工作。但是您使用的是Cognito身份池,在这种情况下,您将永远无法访问
SECRET\u access\u KEY

如果您的意图只是在本地模仿您的逻辑,那么它将起作用。但如果你允许,我建议不要在家里尝试。如果您的目的只是模拟逻辑,那么简单的方法是绕过API网关,并使用“解码/模拟”标识令牌将一个关于API网关事件格式的模拟对象直接发送到函数


另一件事:如果您使用Cognito标识池(您正在使用的)移动到自定义授权器,您将需要手动执行许多任务,例如验证签名和解码标识令牌(我相信这是
x-amz-security-token
的内容)。总之,您需要手动执行IAM授权人执行的所有任务。

Hi。谢谢你的回复。是的,我曾考虑过“使用“解码/模拟”身份令牌将一个与API网关事件格式相关的模拟对象直接发送到函数”。但我的问题是,不同的角色将具有不同级别的身份验证,并且该逻辑在我的lambda中(在授权者和解码角色后面)。(例如,具有角色x的用户可以编辑书籍角色y只能添加书籍)。我是否可以解码授权标头以查看所声明的角色?我不需要验证声明,只需为每个请求模拟正确的标识即可。在您的解决方案中有一些问题尚不清楚。我知道您正在使用与Cognito用户池集成的Cognito标识池。如果是这样的话,我几乎可以肯定您不会在令牌中获得角色信息。要在令牌中拥有角色,我相信您需要使用Cognito Authorizer。但是这样,您将失去拥有未经身份验证的用户的能力。如果您使用Cognito Authorizer,当事件传递给Lambda函数时,角色将出现在identity对象中。如果您不使用Cognito授权器(能够进行未经验证的调用,如您的示例中),我猜您将需要获取用户ID并使用
标识。cognitoAuthenticationProvider
转到用户池,并使用
identity.caller
identity/user
获取经过身份验证的用户的角色(或者在最坏的情况下,您需要查询Id池以发现用户池Id)。您好。谢谢你的回复。是的,我曾考虑过“使用“解码/模拟”身份令牌将一个与API网关事件格式相关的模拟对象直接发送到函数”。但我的问题是,不同的角色将具有不同级别的身份验证,并且该逻辑在我的lambda中(在授权者和解码角色后面)。(例如,具有角色x的用户可以编辑书籍角色y只能添加书籍)。我是否可以解码授权标头以查看所声明的角色?我不需要验证声明,只需为每个请求模拟正确的标识即可。在您的解决方案中有一些问题尚不清楚。我知道您正在使用与Cog集成的Cognito标识池