kyoshida
kyoshida

Reputation: 293

I am getting an authentication error in aws-sdk v3 "UnrecognizedClientException: the security token included in the request is invalid."

I am creating a dynamoDB operation with aws-sdk v3. When testing I get the error "UnrecognizedClientException: The security token included in the request is invalid."

  Unit test for DynamoDb ' verifies successful response

    UnrecognizedClientException: The security token included in the request is invalid.

      25 | const command = new GetItemCommand(params);
      26 | console.log(command)
    > 27 | const result = await this.client.send(command);
         | ^ ^
      28 | return { body: JSON.stringify(unmarshall(result.Item || {})) }; }
      29 | } catch (err: unknown) {
      30 | throw err;

Here is the code.

import { BatchGetItemCommand, BatchWriteItemCommand, BatchWriteItemCommandOutput, DynamoDBClient, GetItemCommand, PutItemCommand, UpdateItemCommand } from '@aws-sdk/client-dynamodb';
import { marshall, unmarshall } from '@aws-sdk/util-dynamodb';

export class DynamoDb {
    private readonly tableName: string;
    private readonly client: DynamoDBClient;

    constructor(tableName = '') {
        this.client = new DynamoDBClient({
            region: 'ap-northeast-1',
            credentials: {
                accessKeyId: 'xxxx',
                secretAccessKey: 'xxxxx',
            },
        });
        this.tableName = tableName ? tableName : '';
    }

    public async get(keyName: string, key: string | number) {
        try {
            const params = {
                TableName: this.tableName,
                Key: marshall({ [keyName]: key }),
            };
            const command = new GetItemCommand(params);
            console.log(command)
            const result = await this.client.send(command);
            return { body: JSON.stringify(unmarshall(result.Item || {})) };
        } catch (err: unknown) {
            throw err;
        }
    }

    public async put(item: object) {
        try {
            const params = {
                TableName: this.tableName,
                Item: marshall(item),
            };
            const command = new PutItemCommand(params);
            return await this.client.send(command);
        } catch (err: unknown) {
            throw err;
        }
    }

    public async update(keyName: string, key: string | number, updateExpression: string, expressionAttributeValues: { [key: string]: any }) {
        try {
            const params = {
                TableName: this.tableName,
                Key: marshall({ [keyName]: key }),
                UpdateExpression: updateExpression,
                ExpressionAttributeValues: marshall(expressionAttributeValues),
                ReturnValues: 'ALL_NEW', // Return the updated attributes of the item
            };
            const command = new UpdateItemCommand(params);
            const result = await this.client.send(command);
            return { body: JSON.stringify(unmarshall(result.Attributes || {})) };
        } catch (err: unknown) {
            throw err;
        }
    }

    public async batchGet(keys: { [keyName: string]: string | number }[]) {
        try {
            const params = {
                RequestItems: {
                    [this.tableName]: {
                        Keys: keys.map((key) => marshall(key)),
                    },
                },
            };
            const command = new BatchGetItemCommand(params);
            const result = await this.client.send(command);
            const responses = result.Responses?.[this.tableName] || [];
            const items = responses.map((response) => unmarshall(response) as object);
            return { body: JSON.stringify(items) };
        } catch (err: unknown) {
            throw err;
        }
    }

    public async batchPut(items: object[]) {
        try {
            const putRequests = items.map((item) => ({
                PutRequest: {
                    Item: marshall(item),
                },
            }));

            const params = {
                RequestItems: {
                    [this.tableName]: putRequests,
                },
            };
            const command = new BatchWriteItemCommand(params);
            const result: BatchWriteItemCommandOutput = await this.client.send(command);
            return { body: JSON.stringify(result) };
        } catch (err: unknown) {
            throw err;
        }
    }
}

I have explicitly written the access key and secret key, what am I doing wrong? This key is used in another code and I can connect to DynamoDB without any problems.

Upvotes: 0

Views: 916

Answers (1)

Leeroy Hannigan
Leeroy Hannigan

Reputation: 19883

There must be an issue with your credential keys, ensure that they are correct and still valid.

Also ensure that the role does not enforce MFA, if it does you will have to include a AWS_SESSION_TOKEN as part of your credentials.

I would also suggest that you don't hard code credentials, ever! Not even for testing. If your testing in AWS use an IAM role. If your testing locally, use aws configure to configure credentials locally.

Upvotes: 0

Related Questions