Send OTP on email instead of SMS -Cognito - amazon-cognito

Is there a way to send OTP by email instead of SMS?
SMS's have a bunch of limitations and regulations in different countries and TOTP happens to be so not friendly to non-technical users.
I understand I can have custom flow but we would like to continue using Amplify for the login. What's the most straightforward way to achieve this in the cognito service?

There isn't an email solution out-of-box, but the setup is relatively straightforward using custom flow, lambda triggers and amazon SES. You can follow this tutorial on the AWS blog: https://aws.amazon.com/blogs/mobile/extending-amazon-cognito-with-email-otp-for-2fa-using-amazon-ses/

No, you can't be using the Amplify
import { Auth } from 'aws-amplify';
##You can select preferred mfa type, for example:
##Select TOTP as preferred
Auth.setPreferredMFA(user, 'TOTP').then((data) => {
console.log(data);
// ...
}).catch(e => {});
// Select SMS as preferred
Auth.setPreferredMFA(user, 'SMS');
// Select no-mfa
Auth.setPreferredMFA(user, 'NOMFA');

Related

Change Password with firebase cloud functions

I have found documents (Manage Users ** Firebase Official docs) on how to change a password but not how to use a cloud function. The user.updatePassword(newPassword).then(() => { does not work for a cloud function. --> At lease that i am aware of...
My Goal if possible, is to pass the users userid and new password in a similar fashion to the above and have it change. Any examples or firebase doc's i might have missed would be great.
Cheers
Inside Cloud Function you're using the Firebase Admin SDK to access Firebase Authentication, so you can update the user through that to set their password. From that link:
getAuth()
.updateUser(uid, {
password: 'newPassword',
})

How to disable/enable Sign Ups for a specific application with Auth0?

Is there a way to disable or enable sign ups for a specific application which is independent of the “Disable Sign Ups”-toggle in the dashboard for login with passwordless email (Authentication/Passwordless/Email)?
Only partly.
It's possible via Pre-User-Registration Hook and/or or Rule with some caveats.
Pre-User-Registration Hooks :
https://auth0.com/docs/customize/hooks/extensibility-points/pre-user-registration
Something like this:
module.exports = function (user, context, cb) {
return cb(new PreUserRegistrationError('Denied user registration in Pre-User Registration Hook', 'You are not allowed to register.'));
}
};
Here you can just fail the registration at all times.
Problem with Hooks is that that the Pre-User-Registration Hook does not trigger for social connections / federation, only Database Connections and Passwordless.
Alternatively via Rule:
https://auth0.com/docs/customize/rules
This will always work, but the downside is that the user gets created in Auth0, they will just not be able to further proceed.
In the Rule you basically check the number of logins, if it's 0, you know that it's a new user, and block the login that follows right after user creation (signup) as well as any other time.
Example rule:
https://auth0.com/rules/disable-social-signup
Related earlier answer of mine regarding this, in the Auth0 forum:
https://community.auth0.com/t/disable-signup-from-auth0-ui-and-enable-social-login/29227/2
I just figured out I can create another 'Tenant' (from the dashboard) with a different setting for Sign Up from the dashboard :-)
You could implement a custom Universal Login SPA for sign-up/in that only allows users to sign-in. Pre-registration hook to safeguard against people bypassing the UX.

Adding “Sign In with Apple” in Expo react native app that uses Firebase auth

I have a react native app that uses Expo (managed, not detached) and that uses Firebase auth to provide Facebook login and email/password login.
I now need to implement “Sign in with Apple” as per Apple’s new rules.
Expo provides a way to do this, and it works, returning the user’s info. But because all users are managed through Firebase auth, I need to take what Apple sends me and pass it to Firebase auth.
The Firebase docs explain how to do this using signInWithCustomToken. But that requires that I create the token. In Node this would be simple, but this app is serverless and I haven’t found a tool that can generate an RS256 token on the client. From the Firebase docs it seems that RS256 is a requirement. I’ve tried using expo-jwt with HS256 and Firebase returns an error that the token is badly formed. But besides using HS256 instead of RS256 I see no other possible problems. The token is encoded and decoded successfully as follows.
const appleJwt = JWT.encode(
{
familyName: 'M',
givenName: 'Greg',
email: 'apple_user#example.com',
alg: 'HS256',
iss:
'https://identitytoolkit.googleapis.com/google.identity.identitytoolkit.v1.IdentityToolkit',
sub: serviceAccountEmail,
aud: serviceAccountEmail,
iat: Math.floor(Date.now() / 1000),
exp: Math.floor(Date.now() / 1000) + 3600,
uid: appleUid
},
key,
{
algorithm: 'HS256'
}
);
console.log('TCL: loginWithApple -> appleJwt', appleJwt);
const appleJwtDecoded = JWT.decode(appleJwt, key);
console.log('TCL: loginWithApple -> appleJwtDecoded', appleJwtDecoded);
It’s only when I try to use it with Firebase auth that it returns an error that the token is badly formatted.
return Firebase.auth().signInWithCustomToken(appleJwt).then(...
Note that the key and the serviceAccountEmail were retrieved from the firebase console.
I’m wondering if perhaps there’s some simpler solution that I’m overlooking. The community is awaiting word from Firebase on if they’ll provide out of the box login with Apple, like they do for other providers, so maybe I just need to be patient. But I’d prefer to find a solution.
A big thanks in advance for any advice.
Update 2019-10-15
I built a simple node server with an API that my app could use to generate the token with RS256, but Firebase still responds that the token is badly formatted when I pass it to signInWithCustomToken. Can’t see what’s wrong with it.
So, since I had the node server built, I just configured the Firebase Admin SDK and used the provided createCustomToken to generate the token. Firebase accepts it now when I pass it to signInWithCustomToken, which was my problem, so this issue is settled for me. After the custom Firebase sign in succeeds the first time, I write all the user data to Firestore. For subsequent sign ins, it just updates the last login date in Firestore. Hopefully Firebase will still provide their own solution soon too, since having a separate node server just for this is not ideal.
Firebase Auth now supports Apple sign in across all 3 platforms:
https://firebase.google.com/docs/auth/ios/apple
https://firebase.google.com/docs/auth/android/apple
https://firebase.google.com/docs/auth/web/apple
The Firebase team is working on implementing this in the official sdk
https://github.com/firebase/firebase-ios-sdk/issues/3145#issuecomment-510178359

Is a full sign-in required to verify a phone number using Firebase Phone Auth?

A question about firebase auth for authentication via phone number.
I was wondering if it was possible to link a "Phone Provider" to say a Google Auth Provider. There is no explicit mention of it in the docs.
The thing that had me scratching my head is - the Link Multiple Auth Provider docs talk about starting to authenticate with the new provider (phone provider) you want to link to the existing provider (google provider), but then stopping short of calling FirebaseAuth.signInWithXXX.
So in theory that would work like:
The user logs in via google (google idp provider)
The user kicks off the phone auth (phone number provider) - and gets an sms message.
The SMS should trigger an automatic verification in some cases or he types in the 6 digit code from the sms message
But based on the docs on account-linking, rather than call FirebaseAuth.signInWithXXX here, we can instead call FirebaseUser.linkWithCredential(PhoneAuthCredential).
So i was wondering if a phone number verification is considered complete without an explicit sign-in with the PhoneAuthCredential ?
You can link a PhoneAuthCredential to an existing user, in your case, a user with a GoogleAuthProvider.
After you sign in the user with Google.
You then go through PhoneAuthProvider.getInstance().verifyPhoneNumber(phoneNumber, ...)
This would resolve with a PhoneAuthCredential or a verification ID. You can then ask for the SMS code and instantiate a PhoneAuthCredential via PhoneAuthProvider.getCredential.
You can then link that credential to the currentUser: currentUser.linkWithCredential(phoneAuthCredential)
For future comers and javascript users here is a way to achieve that:
const phoneCreds = firebase.auth.PhoneAuthProvider.credential(this.windowRef.confirmationResult.verificationId, phoneConfirmCode);
firebase.auth().currentUser.linkAndRetrieveDataWithCredential(phoneCreds)
.then(response => {
console.log('*********', response);
// Manage other firestore data
})
.catch((error) => {
console.log('error', error);
});

Firebase Auth linking anonymous auth user with custom auth user

So I saw here: https://firebase.google.com/docs/auth/web/account-linking#link-auth-provider-credentials-to-a-user-account That it is now possible to link user accounts in Firebase. I also saw that Firebase provides the functionality of anonymous authentication, where it creates a user session for a user, without any credentials.
In our application we normally use CustomAuthentication with Firebase, as we have our own authentication service. This works perfectly, and we are able to use the same Auth system in-between systems that use Firebase, and the ones that don't.
Now we got to the point where we wanted to take advantage of the anonymous authentication of Firebase, to allow users to use the apps without registering, and just transfer their details after they log in. So I thought that account linking is what I need. But I can't find a way to link an anonymous account with a custom authentication account. Is something like this possible with Firebase?
I have not found linking between anonymous and custom signIns too, so I just use signInAnonymously and pass it's uid to signInWithCustomToken.
Step 1.
To be able acheive this, you should grab an uid from signInAnonymously function like this:
var uid;
auth().signInAnonymously().then(user => {
uid = user.uid;
});
Step 2.
Save current user data like this:
database().ref(`users/${uid}`).set({ some: 'data' });
Step 3.
Send this uid to your server which returns custom token. On your server you just pass this uid to firebase.auth().createCustomToken(uid) function and send this custom token back. It will contain the uid.
Step 4.
When you receive custom token, you can sign in with it like this:
auth().signInWithCustomToken(authKey);
And that's it. You are signed in with your custom token and can access your anonymous user data saved on the step 2.
I had a similar problem but I believe Firebase does not allow this type of linking because it would require linking two separate firebase user ids: the id of the custom token created user and the id of the anonymous user.
Firebase docs say:
Users are identifiable by the same Firebase user ID regardless of the authentication provider they used to sign in.
So handling linking between two user ID's would cause inconsistencies.
I got around this problem by doing a merge of the data between the two accounts.
For example (from Firebase docs):
// Get reference to the currently signed-in user
var prevUser = auth.currentUser;
// Sign in user with another account
auth.signInWithCredential(credential).then(function(user) {
console.log("Sign In Success", user);
var currentUser = user;
// Merge prevUser and currentUser accounts and data
// ...
}, function(error) {
console.log("Sign In Error", error);
});
Caveat: I've never done this. Have you seen this page? Down at the bottom, under the heading "Email-password sign-in", it lists this code fragment:
var credential = firebase.auth.EmailPasswordAuthProvider.credential(email, password);
You can then (apparently) link the credential like this:
auth.currentUser.link(credential).then(function(user) {
console.log("Anonymous account successfully upgraded", user);
}, function(error) {
console.log("Error upgrading anonymous account", error);
});