Calling Cognito Sign in from Lambda causes Timeout

0

I am implementing user login using AWS cognito user pool. So the flow is, Website will call an API Gateway, which will trigger a lambda function (node.js 18.x), which in turn will interact with Cognito user pool through the 'amazon-cognito-identity-js'. The node.js code authenticates user within a second in my local, but when I deploy it in lambda and run it there, it takes an excruciating 10 seconds to authenticate(Had to increase the timeout from the default 3 seconds). The sign-up, email verification flow, they work within a second in lambda, but I am facing issues with sign-in for now, haven't tried the forgot password flow yet. The lambda sign-in code is as follows:

import {CognitoUserPool,AuthenticationDetails,CognitoUser, CognitoUserAttribute} from 'amazon-cognito-identity-js';
import dotEnv from 'dotenv';

dotEnv.config();




const signIn=(cognitoUser,authDet)=>{
 return new Promise((resolve,reject)=>{
     cognitoUser.authenticateUser(authDet,{
         onSuccess:(session)=>{
             console.log(`Success: ${JSON.stringify(session)}`);
             resolve(session);
         },
         onFailure:(err)=>{
             console.log(`Failure: ${JSON.stringify(err)}`);
             reject(err);
         }
     })
 });
}

export const handler= async (event)=>{
 console.log(`The event: ${JSON.stringify(event)}`);
 const poolData={
     UserPoolId:process.env.COGNITO_POOL_ID,
     ClientId:process.env.CLIENT_ID
 }

 const userPool=new CognitoUserPool(poolData);
 let response={};

     console.log('Signing In');
     const requestBody=JSON.parse(event.body);
     const authDet=new AuthenticationDetails({
         Username:requestBody.email,
         Password:requestBody.password
     });

     const userData={
         Username:authDet.username,
         Pool:userPool
     }

     const cognitoUser=new CognitoUser(userData);
     try{
         const session=await signIn(cognitoUser,authDet);
         response={statusCode:200,
             headers:{'Content-Type':'application/json'},
             body:{state:"Success",
             session:session}
         }
     }catch(err){
         response={statusCode:200,
             headers:{'Content-Type':'application/json'},
             body:{state:"Failure",
             err:err}
         }
     }
     console.log(`Response to return: ${JSON.stringify(response)}`);
     return response;
 
 
   
}

The lambda configuration is the default one, with no VPC, or any other special network config. I just created a lambda function and deployed this node.js into it. Both the user pool and lambda are in the same region. The API gateway has a proxy integration with lambda.

I know AWS documentation talks about doing it the other way round, i.e, calling cognito directly from website and have post-confirmation and pre-token generation triggers. But, that way the pool id and client id remains exposed on client machine, so I thought of doing it this way. It baffles me why sign in is taking such a long time when done through lambda, but when I do it from website (or from local), it authenticates within a second or two.

If anyone could help me out in figuring out why the timeout occurs, or if there is something wrong with my code, then that would be great.

Thanks...

Monty
asked 8 months ago411 views
1 Answer
1

I don't know why it takes longer. However, I really don't think you should go that route. The authentication should happen on the client side and it should send the token to API Gateway. User pool ID and Client ID and not secrets. Your current design requires you to implement all the different use cases also on the back end. In addition, the auth endpoint on API Gateway is unprotected, which creates an option for denial of wallet by someone making a lot of calls to that endpoint, incurring cost on both the API Gateway and the Lambda function.

profile pictureAWS
EXPERT
Uri
answered 8 months ago
  • Thanks for Answering. The reason I feel uncomfortable having the authentication client side is, that way the User Pool Id and Client Id would be exposed to anyone. Theoretically, one can create dummy accounts using those information, although what benefit would someone gain by doing that, I am not sure. So thought of hiding that behind my server. But if it is industry standard to have the authentication happening client side (is it?), then I guess that might not be that big a deal, or is it a risk people accept? Your point about API gateway being unprotected is also valid, but what if I have it behind a WAF? Thanks Again.

  • As far as I know, it is the standard. As to your concern of creating dummy accounts, won't you provide that functionality anyway via the Lambda? So you do not actually protect.

    WAF can help, but that has cost as well, and not sure it will protect all cases.

    Short answer, all customers I work with do it directly from the client.

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions