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 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 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 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 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 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 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 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 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 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?