Search code examples
node.jsamazon-web-servicesazurelambda

@azure/identity node.js v18 aws lambda - ClientSecretCredential is not a constructor


I have started learning how to implement AWS Lambda functions and want to be able to authenticate with Azure AD to create/update users. I'm getting the following error:

ClientSecretCredential is not a constructor.

I understand what the error means but I cannot find anywhere why this might be happening - every code example I've seen uses the same approach and it seems to work for them!

Has anyone come across this before, I would really appreciate any pointers.

Here is my function code:

const { ClientSecretCredential } = import("@azure/identity");
const { GraphRbacManagementClient } = import("@azure/graph");

export const handler = async (event, context) => {
  try {
    // Azure AD authentication parameters
    const tenantId = process.env.TENANT_ID || 'YOUR_TENANT_ID';
    const clientId = process.env.CLIENT_ID || 'YOUR_CLIENT_ID';
    const clientSecret = process.env.CLIENT_SECRET || 'YOUR_CLIENT_SECRET';

    // Azure Graph API client
    const credential = new ClientSecretCredential(tenantId, clientId, clientSecret);
    const graphClient = new GraphRbacManagementClient(credential, tenantId);

    // User details for update
    const userId = process.env.USER_ID || 'USER_OBJECT_ID';
    const updatedUserProperties = {
      accountEnabled: true,
      // Add other properties you want to update
    };

    // Update user in Azure AD
    const updatedUser = await graphClient.users.update(userId, updatedUserProperties);

    console.log('User updated:', updatedUser);
    
    return {
      statusCode: 200,
      body: JSON.stringify({ message: 'User updated successfully' }),
    };
  } catch (error) {
    console.error('Error:', error);

    return {
      statusCode: 500,
      body: JSON.stringify({ message: 'Internal Server Error' }),
    };
  }
};

This is the output from the console log: Test Event Name (unsaved) test event

Response { "statusCode": 500, "body": "{"message":"Internal Server Error"}" }

Function Logs START RequestId: bdf79a4c-6d4d-40d8-b57d-58166e57e13c Version: $LATEST 2023-10-02T12:03:09.302Z bdf79a4c-6d4d-40d8-b57d-58166e57e13c ERROR Error: TypeError: ClientSecretCredential is not a constructor at Runtime.handler (file:///var/task/index.mjs:12:24) at Runtime.handleOnceNonStreaming (file:///var/runtime/index.mjs:1147:29) END RequestId: bdf79a4c-6d4d-40d8-b57d-58166e57e13c REPORT RequestId: bdf79a4c-6d4d-40d8-b57d-58166e57e13c Duration: 503.37 ms Billed Duration: 504 ms Memory Size: 1024 MB Max Memory Used: 94 MB Init Duration: 188.92 ms

Thanks in advance.

I'm not expecting to receive the ClientSecretCredential is not a constructor error message.


Solution

  • The import statement is only allowed in ES modules and cannot be used in embedded scripts without the type attribute set to module.

    You need to add "type": "module" to your package.json file in order to tell Node.js to use ES modules instead of traditional ES5 syntax, or use the .mjs file extension.

    The docs refer to this:

    By default, Lambda treats files with the .js suffix as CommonJS modules. Optionally, you can designate your code as an ES module. You can do this in two ways: specifying the type as module in the function's package.json file, or by using the .mjs file name extension. In the first approach, your function code treats all .js files as ES modules, while in the second scenario, only the file you specify with .mjs is an ES module. You can mix ES modules and CommonJS modules by naming them .mjs and .cjs respectively, as .mjs files are always ES modules and .cjs files are always CommonJS modules.