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.
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!