Description
Checklist
- I have looked into the Readme, Examples, and FAQ and have not found a suitable solution or answer.
- I have looked into the API documentation and have not found a suitable solution or answer.
- I have searched the issues and have not found a suitable solution or answer.
- I have searched the Auth0 Community forums and have not found a suitable solution or answer.
- I agree to the terms within the Auth0 Code of Conduct.
Description
I have a backend project running on AWS Lambda with Node.js and TypeScript. I am using serverless framework - more specifically serverless-bundle with inversify
The problem is auth0 does not initializes with inversify. This was a not a problem before but has suddenly started happening across all my projects wherever auth0 is being used.
I had raised another issue #815 with auth0 and even updated my project's auth0 version to latest one but it still fails.
Since the inversify container is being initialized from lambda, auth0 failure is causing the entire lambda failure for the project.
Reproduction
My lambda handler
'use strict';
import { APIGatewayProxyHandler } from 'aws-lambda';
import serverlessExpress from '@vendia/serverless-express';
import app from './auth-express.app';
import SQLDbConnectionService from './services/sqldb-connection-service';
import MongoDbConnectionService from './services/mongodb';
export const handler: APIGatewayProxyHandler = async (
event,
context,
callback,
) => {
context.callbackWaitsForEmptyEventLoop = false;
const authHeaders = (event.requestContext || {}).authorizer || {};
['principalId'].forEach((headerKey) => {
if (authHeaders[headerKey]) {
event.headers[headerKey] = authHeaders[headerKey];
}
});
await Promise.all([
SQLDbConnectionService.connect(),
MongoDbConnectionService.connect(),
]);
const serverlessExpressInstance = serverlessExpress({ app });
return serverlessExpressInstance(event, context, callback);
};
In the above lambda handler one line number 3, I am initializing my express server, which looks like the following
'use strict';
import cors from 'cors';
import express from 'express';
import compression from 'compression';
import 'reflect-metadata';
import { ExpressRouter } from './routes/auth-routes';
import helmet from 'helmet';
import { ContainerFactory } from './factories/container-factory';
class ExpressApplication {
public app: express.Express;
private readonly router: express.Router;
constructor() {
const container = ContainerFactory.getContainer();
const expressRouter = new ExpressRouter();
this.app = express();
this.router = express.Router();
this.app.use(cors());
this.app.use(helmet());
this.app.use(compression());
this.app.use(express.json());
this.app.use(express.urlencoded({ extended: true }));
expressRouter.setRoutes(this.app, this.router, container);
}
}
const app = new ExpressApplication();
export default app.app;
in the express code above, I am setting the inversify container from container-factory
which looks like this
import 'reflect-metadata';
import { Container } from 'inversify';
//import service identifiers
import TYPES from "../utilities/types";
//import service interfaces
import Auth0ServiceInterface from 'interfaces/auth0-service-interface';
.
.
.
//import services and implementations
import { Auth0Service } from '../services/auth0-service';
.
.
.
export class ContainerFactory {
public static getContainer(): Container {
const container = new Container({ skipBaseClassChecks: true });
ContainerFactory.configureServices(container);
return container;
}
private static configureServices(container: Container) {
//binding auth0 service
container.bind<Auth0ServiceInterface>(TYPES.Auth0Service).to(Auth0Service);
//binding other services
.
.
.
}
}
in the code above I am importing the interfaces and services and binding them. You can see that I am also binding my auth0 service - which is where the problem starts.
The auth0 service looks like this (have removed the functions for readability)
import { AuthenticationClient, ManagementClient, User } from 'auth0';
import Auth0ServiceInterface from 'interfaces/auth0-service-interface';
import { Auth0ClinicianMetaData } from 'interfaces/auth0-user-interfaces';
import { injectable } from 'inversify';
const AUTH0_AUDIENCE = process.env.AUTH0_AUDIENCE;
let AUTH0_DOMAIN = process.env.AUTH0_DOMAIN || '';
AUTH0_DOMAIN = AUTH0_DOMAIN.replace('https://', '');
let AUTH0_DOMAIN_NOT_CUSTOM = process.env.AUTH0_DOMAIN_NOT_CUSTOM || '';
AUTH0_DOMAIN_NOT_CUSTOM = AUTH0_DOMAIN_NOT_CUSTOM.replace('https://', '');
const AUTH0_M2M_CLIENT_ID = process.env.AUTH0_M2M_CLIENT_ID || '';
const AUTH0_M2M_SECRET = process.env.AUTH0_M2M_SECRET || '';
const AUTH0_REGULAR_WEB_CLIENT_ID = process.env.AUTH0_REGULAR_WEB_CLIENT_ID || '';
const AUTH0_REGULAR_WEB_CLIENT_SECRET = process.env.AUTH0_REGULAR_WEB_CLIENT_SECRET || '';
@injectable()
export class Auth0Service implements Auth0ServiceInterface {
private managementClient: ManagementClient;
private authenticationClient: AuthenticationClient;
constructor() {
this.managementClient = new ManagementClient({
domain: AUTH0_DOMAIN_NOT_CUSTOM,
clientId: AUTH0_M2M_CLIENT_ID,
clientSecret: AUTH0_M2M_SECRET,
scope: 'read:users create:users update:users',
});
this.authenticationClient = new AuthenticationClient({
domain: AUTH0_DOMAIN,
clientId: AUTH0_REGULAR_WEB_CLIENT_ID,
clientSecret: AUTH0_REGULAR_WEB_CLIENT_SECRET,
});
}
//... functions for implementing the auth0 service - have removed for the sample
}
I get this kind of error when the lambda function is called
2023-05-17T10:16:31.760Z undefined ERROR Uncaught Exception {
"errorType": "TypeError",
"errorMessage": "M is not a function",
"stack": [
"TypeError: M is not a function",
" at Object.91738 (/var/task/src/auth-lambda.js:540:5226)",
" at __webpack_require__ (/var/task/src/auth-lambda.js:3143:2090854)",
" at Object.59458 (/var/task/src/auth-lambda.js:540:15606)",
" at __webpack_require__ (/var/task/src/auth-lambda.js:3143:2090854)",
" at Object.16135 (/var/task/src/auth-lambda.js:2839:1079)",
" at __webpack_require__ (/var/task/src/auth-lambda.js:3143:2090854)",
" at Object.81557 (/var/task/src/auth-lambda.js:2726:36831)",
" at __webpack_require__ (/var/task/src/auth-lambda.js:3143:2090854)",
" at Object.96781 (/var/task/src/auth-lambda.js:2726:41526)",
" at __webpack_require__ (/var/task/src/auth-lambda.js:3143:2090854)"
]
}
If I comment the auth0 function binding in my container-factory
then my lambda runs smoothly.
Here are the dependencies and dev-dependencies in my project
//dependencies
"auth0": "^3.4.0"
"express": "^4.17.1",
"inversify": "^6.0.1",
//dev dependencies
"@types/auth0": "^3.3.2",
"@types/aws-lambda": "^8.10.84",
"@types/express": "^4.17.13",
Additional context
My lambda is running on Node.js version 14
node-auth0 version
3.4.0
Node.js version
14