Last active
August 12, 2023 07:49
-
-
Save praveen001/57b0d8262e1a2ef0c539d0715a3649e1 to your computer and use it in GitHub Desktop.
Passwordless Phone number authentication using AWS Amplify and Cognito
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import Amplify, { Auth } from 'aws-amplify'; | |
| Amplify.configure({ | |
| Auth: { | |
| region: 'us-east-1', | |
| userPoolId: '**********', | |
| userPoolWebClientId: '******************', | |
| } | |
| }); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| try { | |
| const data = await Auth.currentAuthenticatedUser(); | |
| } catch { | |
| // User not logged in | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| const AWS = require('aws-sdk'); | |
| function sendSMS(phone, code) { | |
| const params = { | |
| Message: code, /* required */ | |
| PhoneNumber: phone, | |
| }; | |
| return new AWS.SNS({apiVersion: '2010-03-31'}).publish(params).promise(); | |
| } | |
| exports.handler = async (event) => { | |
| console.log("CUSTOM_CHALLENGE_LAMBDA", event.request); | |
| let secretLoginCode; | |
| if (!event.request.session || !event.request.session.length) { | |
| // Generate a new secret login code and send it to the user | |
| secretLoginCode = Date.now().toString().slice(-4); | |
| try { | |
| await sendSMS(secretLoginCode); | |
| } catch { | |
| // Handle SMS Failure | |
| } | |
| } else { | |
| // re-use code generated in previous challenge | |
| const previousChallenge = event.request.session.slice(-1)[0]; | |
| secretLoginCode = previousChallenge.challengeMetadata.match(/CODE-(\d*)/)[1]; | |
| } | |
| console.log(event.request.userAttributes); | |
| // Add the secret login code to the private challenge parameters | |
| // so it can be verified by the "Verify Auth Challenge Response" trigger | |
| event.response.privateChallengeParameters = { secretLoginCode }; | |
| // Add the secret login code to the session so it is available | |
| // in a next invocation of the "Create Auth Challenge" trigger | |
| event.response.challengeMetadata = `CODE-${secretLoginCode}`; | |
| return event; | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| exports.handler = async (event, context, callback) => { | |
| console.log(event.request); | |
| // If user is not registered | |
| if (event.request.userNotFound) { | |
| event.response.issueToken = false; | |
| event.response.failAuthentication = true; | |
| throw new Error("User does not exist"); | |
| } | |
| if (event.request.session.length >= 3 && event.request.session.slice(-1)[0].challengeResult === false) { // wrong OTP even After 3 sessions? | |
| event.response.issueToken = false; | |
| event.response.failAuthentication = true; | |
| throw new Error("Invalid OTP"); | |
| } else if (event.request.session.length > 0 && event.request.session.slice(-1)[0].challengeResult === true) { // Correct OTP! | |
| event.response.issueTokens = true; | |
| event.response.failAuthentication = false; | |
| } else { // not yet received correct OTP | |
| event.response.issueTokens = false; | |
| event.response.failAuthentication = false; | |
| event.response.challengeName = 'CUSTOM_CHALLENGE'; | |
| } | |
| return event; | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| exports.handler = async (event) => { | |
| event.response.autoConfirmUser = true; | |
| event.response.autoVerifyPhone = true; | |
| return event; | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| try { | |
| const cognitoUser = await Auth.signIn(phoneNumber); | |
| } catch { | |
| // Handle sign in errors | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| try { | |
| await Auth.signUp({ | |
| username: phoneNumber, | |
| password: Date.now().toString() | |
| }); | |
| } catch { | |
| // Handle sign up error | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| try { | |
| const cognitoUser = await Auth.sendCustomChallengeAnswer(user, OTP); | |
| } catch { | |
| // Handle 3 error thrown for 3 incorrect attempts. | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| exports.handler = async (event) => { | |
| console.log(event.request); | |
| const expectedAnswer = event.request.privateChallengeParameters.secretLoginCode; | |
| if (event.request.challengeAnswer === expectedAnswer) { | |
| event.response.answerCorrect = true; | |
| } else { | |
| event.response.answerCorrect = false; | |
| } | |
| return event; | |
| }; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
how can i test it? is there a way as an admin to not send SMS so i can test my api with mocha?
also would this still work with my facebook login or will the triggers break the facebook flow?