aws-sdk-js-v3 icon indicating copy to clipboard operation
aws-sdk-js-v3 copied to clipboard

SESv2 ListContactsCommand InvalidSignatureException

Open rharrisuk opened this issue 2 years ago • 5 comments

Checkboxes for prior research

Describe the bug

I'm probably missing something here but when executing the ListContactsCommand, an InvalidSignatureException is always returned. All other SESv2 endpoints I've tried so far have worked as expected.

The IAM role has full access to SESv2.

Using credentials from Cognito Identity Pool.

SDK version number

@aws-sdk/[email protected]

Which JavaScript Runtime is this issue in?

Browser

Details of the browser/Node.js/ReactNative version

Chrome: 118.0.5993.118

Reproduction Steps

import { GetContactListCommand, GetContactListCommandOutput, ListContactsCommand, ListContactsCommandOutput, SESv2Client } from "@aws-sdk/client-sesv2";
import { fromCognitoIdentityPool } from "@aws-sdk/credential-providers";
import { Auth } from "@aws-amplify/auth";

const AWS_REGION = 'eu-west-2';
const AWS_IDENTITY_POOL_ID = 'eu-west-2:**************';
const AWS_COGNITO_ID = 'cognito-idp.eu-west-2.amazonaws.com/eu-west-2_********';

const getSESClient = (idToken: string): SESv2Client => {
    return new SESv2Client({
      region: AWS_REGION,
      credentials: 
        fromCognitoIdentityPool({
          clientConfig: { region: AWS_REGION },
          identityPoolId: AWS_IDENTITY_POOL_ID,
          logins: {
                  [AWS_COGNITO_ID]: idToken
              },
        })
    });
}

export const listContacts = async (contactListName: string): Promise<ListContactsCommandOutput> => {
    const token = (await Auth.currentSession()).getIdToken().getJwtToken();

    return await getSESClient(token).send(
        new ListContactsCommand({
            ContactListName: contactListName
        })
    );
}

export const getContactList = async (contactListName: string): Promise<GetContactListCommandOutput> => {
    const token = (await Auth.currentSession()).getIdToken().getJwtToken();

    return await getSESClient(token).send(
        new GetContactListCommand({
            ContactListName: contactListName
        })
    );
}

Observed Behavior

In the above simplified code snippet, getContactList works fine (as does every other SESv2 endpoint I've tried so far) but listContacts (https://email.eu-west-2.amazonaws.com/v2/email/contact-lists/MyContactList/contacts) always returns an InvalidSignatureException.

The IAM role has full access to all SESv2 operations.

Error:

{
    "name": "InvalidSignatureException",
    "$fault": "client",
    "$metadata": {
        "httpStatusCode": 403,
        "requestId": "06710683-ec0e-4ea9-b0fb-485191394389",
        "attempts": 1,
        "totalRetryDelay": 0
    },
    "message": "The request signature we calculated does not match the signature you provided. Check your AWS Secret Access Key and signing method. Consult the service documentation for details."
}

Network:

Request URL: https://email.eu-west-2.amazonaws.com/v2/email/contact-lists/ContactList/contacts

Request Method:
GET
Status Code:
403 Forbidden
Remote Address:
18.168.156.180:443
Referrer Policy:
strict-origin-when-cross-origin
Access-Control-Allow-Origin:
*
Access-Control-Expose-Headers:
x-amzn-RequestId,x-amzn-ErrorType,x-amzn-ErrorMessage,Date
Content-Encoding:
gzip
Content-Length:
159
Content-Type:
application/json
Date:
Mon, 30 Oct 2023 00:39:16 GMT
X-Amzn-Errortype:
InvalidSignatureException
X-Amzn-Requestid:
06710683-ec0e-4ea9-b0fb-485191394389
:authority:
email.eu-west-2.amazonaws.com
:method:
GET
:path:
/v2/email/contact-lists/ContactList/contacts
:scheme:
https
Accept:
*/*
Accept-Encoding:
gzip, deflate, br
Accept-Language:
en-US,en;q=0.9
Amz-Sdk-Invocation-Id:
2d2eddf2-86e8-46ee-a721-2407bf558fd7
Amz-Sdk-Request:
attempt=1; max=3
Authorization:
AWS4-HMAC-SHA256 Credential=ASIA6H65RUNKVCC6325C/20231030/eu-west-2/ses/aws4_request, SignedHeaders=amz-sdk-invocation-id;amz-sdk-request;content-length;content-type;host;x-amz-content-sha256;x-amz-date;x-amz-security-token;x-amz-user-agent, Signature=6030af2600f1624ea01e870ea72c9017d9347fc1b03da8aaa57422cfe5c04daf
Content-Type:
application/json
Origin:
http://localhost:3000
Referer:
http://localhost:3000/
Sec-Ch-Ua:
"Chromium";v="118", "Google Chrome";v="118", "Not=A?Brand";v="99"
Sec-Ch-Ua-Mobile:
?0
Sec-Ch-Ua-Platform:
"Windows"
Sec-Fetch-Dest:
empty
Sec-Fetch-Mode:
cors
Sec-Fetch-Site:
cross-site
User-Agent:
Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/118.0.0.0 Safari/537.36
X-Amz-Content-Sha256:
44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a
X-Amz-Date:
20231030T003915Z
X-Amz-Security-Token:
*******
X-Amz-User-Agent:
aws-sdk-js/3.438.0 ua/2.0 os/Windows#NT-10.0 lang/js md/browser#Chrome_118.0.0.0 api/sesv2#3.438.0

Expected Behavior

Receive a 200 response with the contacts for the contact list name.

Possible Solution

No response

Additional Information/Context

No response

rharrisuk avatar Oct 30 '23 01:10 rharrisuk

Hi @rharrisuk ,

Thanks for opening the issue. This is indeed odd. It seems like you are running this from a browser. I'm wondering if the browser might be adding / removing headers / changing the request in a way that causes the mismatch in signature.

Can you try to run this code directly from a node application and see if you are still seeing this?

Also as a side note: you should initialize the SDK client once, in the global scope, and not per API operation.

Thanks, Ran~

RanVaknin avatar Oct 30 '23 22:10 RanVaknin

This issue has not received a response in 1 week. If you still think there is a problem, please leave a comment to avoid the issue from automatically closing.

github-actions[bot] avatar Nov 07 '23 00:11 github-actions[bot]

Hi @RanVaknin

I have created a Node.js Codesandbox and that works as expected but a React Codesandbox fails with the same error. See screenshots.

Nodejs React exception

rharrisuk avatar Nov 07 '23 01:11 rharrisuk

My team is facing the same issue. Could you please advise on how to resolve it?

takahiro-ido-ye avatar Nov 15 '23 07:11 takahiro-ido-ye

Hey there.

As mentioned in my previous comment. Running this application from a browser might be changing the request headers that the request was signed with. That would cause the signature mismatch errors. Your headers might be overwritten or omitted altogether.

You can log the raw request as it is going from the sdk the following way:

client.middlewareStack.add(next => async (args) => {
 console.log(args.request)
 const response = await next(args);
 console.log(response);
 return response;
}, {step: 'finalizeRequest'})

Then, using your browser's developer tools, you need to inspect the network tab and under the request section check if any of the request parameters headers were changed.

Thanks Ran~

RanVaknin avatar Aug 07 '24 22:08 RanVaknin

This issue has not received a response in 1 week. If you still think there is a problem, please leave a comment to avoid the issue from automatically closing.

github-actions[bot] avatar Sep 27 '24 00:09 github-actions[bot]

This thread has been automatically locked since there has not been any recent activity after it was closed. Please open a new issue for related bugs and link to relevant comments in this thread.

github-actions[bot] avatar Oct 16 '24 00:10 github-actions[bot]