Search code examples
node.jstypescriptamazon-web-servicesamazon-dynamodb

Cannot access Amazon DynamoDB


everyone. I'm here to ask a help with Amazon DynamoDB configuration in Node.js + Typescript backend. I'm trying to create a record to the dynamoDB database. I'm using Node.js + Express for the backend and faced this error when I try to access DynamoDB

Error: Resolved credential object is not valid
    at SignatureV4.validateResolvedCredentials (D:\morgan (2)\React + Node.js\DWQ\server\node_modules\.pnpm\@smithy+signature-v4@2.0.15\node_modules\@smithy\signature-v4\dist-cjs\SignatureV4.js:182:19)   
    at SignatureV4.signRequest (D:\morgan (2)\React + Node.js\DWQ\server\node_modules\.pnpm\@smithy+signature-v4@2.0.15\node_modules\@smithy\signature-v4\dist-cjs\SignatureV4.js:107:14) {
  '$metadata': { attempts: 1, totalRetryDelay: 0 }
}

Here is my code.

// dbconfig.ts

import { DynamoDBClient } from "@aws-sdk/client-dynamodb";

// Create Amazon DynamoDB service client object
const ddbClient: DynamoDBClient = new DynamoDBClient({
  region: process.env.REGION,
  credentials: {
    accessKeyId: process.env.AWS_ACCESS_KEY_ID!,
    secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY!,
  },
});

export { ddbClient };
// ddbDocClient.ts

import { DynamoDBDocumentClient } from "@aws-sdk/lib-dynamodb";
import { ddbClient } from "./dbconfig";

const marshallOptions = {
  convertEmptyValues: false, // Whether to automatically convert empty strings, blobs, and sets to `null`
  removeUndefinedValues: true, // Whether to remove undefined values while marshalling
  convertClassInstanceToMap: false, // Whether to convert typeof object to map attribute.
};

const unmarshallOptions = {
  wrapNumbers: false, // Whether to return numbers as a string instead of converting them to native JavaScript numbers.
};

// Create the DynamoDB document client.
const ddbDocClient = DynamoDBDocumentClient.from(ddbClient, {
  marshallOptions,
  unmarshallOptions,
});

export { ddbDocClient };
// UserController.ts

static async register(req: Request, res: Response) {
    const parsedData: RegisterUserInput = RegisterUserSchema.parse(req.body);
    const { confirm, creditNumber, expireMonth, expireYear, creditCode, creditZip, creditOwner, ...filteredInput } = parsedData;
    const hashedPassword: string = await bcrypt.hash(filteredInput.password, 12);

    // Query command finds user by email
    const queryParams: QueryCommandInput = {
        TableName: "users",
        KeyConditionExpression: "email = :email",
        ExpressionAttributeValues: {
            ":email": filteredInput.email,
        },
    };

    // Create a new user data
    const putParams: PutCommandInput = {
        TableName: "users",
        Item: {
            _id: uuidv4(),
            ...filteredInput,
            password: hashedPassword
        }
    };

    await ddbDocClient.send(new QueryCommand(queryParams))
        .then(existUser => {
            // If the user email exists in the database
            if (existUser.Items && existUser.Items.length > 0) {
                res.status(200).json({
                    success: false,
                    message: "User email already exists.",
                });
            } else {
                // Create a new user if it doesn't exist
                // const data = await ddbDocClient.send(new PutCommand(putParams));

                res.status(201).json({
                    success: true,
                    message: "Successfully registered!",
                    result: data,
                });
             }
        })
        .catch(error => {
            console.log(error);

            // Return error response from the server
            res.status(500).json({
                success: false,
                message: "Internal Server Error",
                error
            });
        });
}

I can be sure that I have set env variables correctly. Please help me with that.


Solution

  • I would first strongly advise you from coding credentials directly into a client, you should resolve them from role ideally.

    However, the exception you are seeing is because you are passing the wrong values as your credentials. My suggestion is to check the values of process.env.AWS_ACCESS_KEY_ID! & process.env.AWS_SECRET_ACCESS_KEY!