One Cognito user pool, but multiple front-ends with different authentication flows
See original GitHub issueWhich Category is your question related to? Cognito, authentication
What AWS Services are you utilizing? Amazon Cognito identity SDK for Javascript/ AWS-Amplify
Provide additional details e.g. code snippets
Hey, I am looking to implement an authentication flow for users of 2 different apps, but with a one common Cognito user pool and dynamo DB user table. My problem is that for each of the apps, we want to use a different authentication method:
- passwordless login with magic link ( or confirmation code) that gets sent through an email
- passwordless login with confirmation code that is sent through an SMS
Eventually there might be another 3rd app, where users sign up and sign in with their email and password., but for now users are created only based on their email address and a randomly generated string as a password. I use a pre-sign up lambda to automatically verify their e-mail address/phone.
Attempt 1 - lambda triggers and AWS Amplify
At first I tried to implement this with lambda triggers. For defineAuthChallenge, createAuthChallenge and verifyAuthChallenge lambdas I followed mainly this example: https://aws.amazon.com/blogs/mobile/implementing-passwordless-email-authentication-with-amazon-cognito/
While this enabled me to send a verification code through email or phone, I could not find any great way to implement magic link sending, but whats even worse - I could not find a way to tell createAuthChallenge lambda in which app I am trying to sign in to and therefore whether it should send an email or an SMS with the confirmation code to the user. Is there a way to pass some additional param to the createAuthChallenge lambda that determines which authentication flow to use? Something like:
if (authType === 'email-code'){
sendConfirmationThroughEmail() // make use of SES
}
if ( authType === 'sms-code'){
sendConfirmationThroughSMS() //make use of SNS
}
if (authType === 'password'){
logUserInWithPassword()
}
Attempt 2 - separate backend with Amazon Cognito Identity SDK
After I wasn’t able to implement this with lambda triggers, I tried using a separate backend for this. The advantage is that I can pass any parameter I want to the login request to the backend, which then can determine which authentication flow to use. For passwordless login via email I use Amazon SES to send user a with magic link (but this could also be a code). The magic link contains a jsonwebtoken - upon clicking the link, the app gets opened and another POST request with user’s email and this token is made to the backend, which evaluates whether the token is valid for the user. If so, I try to authenticate the Cognito user using Amazon Cognito Identity SDK (following this example: https://docs.aws.amazon.com/cognito/latest/developerguide/using-amazon-cognito-user-identity-pools-javascript-examples.html) - only in this case I need user’s password in the authenticationData in order to log the user in successfully. Only this backend does not know anything about the user’s password as this is randomly generated upon signUp in a worker environment.
My question in this case is - would it be safe security wise to save a hashed version of this randomly generated password in dynamoDB, so that my backend can extract/decrypt it and use it authenticate the user in Cognito?
If anyone can suggest a better way for achieving different authentication flows for different front-ends, but with one common Cognito user pool, please let me know. Any help/suggestions are appreciated! Thank you!
Issue Analytics
- State:
- Created 4 years ago
- Reactions:2
- Comments:10 (2 by maintainers)
Top GitHub Comments
+1. This issue still exists because Cognito has no way of distinguishing between different CUSTOM_AUTH flows sent from a single client.
I have abandoned my approach with amplify and instead have decided to authenticate user from my backend by using cognito lambda triggers (create, define and verifyAuthChallenge) and using CognitoIdentityServiceProvider methods initiateAuth() and respondToAuthChallenge(). (a good example on this: https://www.youtube.com/watch?v=8DDIxqIW1sM around 50 mins in).
This way I am still not able to customize weather the code is sent through email for one app and through phone for another, so for now I am sticking only to email, however I run into anothe rbig problem: the Sessions string parameter which needs to passed on to respondToAuthChallenge() function is valid for only 3 min (as mentioned here: https://aws.amazon.com/blogs/mobile/customizing-your-user-pool-authentication-flow/) - I dont think that user will always be able to go to his email, retrieve and copy the verification code, then return to the app and send it within 3 minutes - how can I increase the expiration time for the session?