I'm trying to implement multi-factor authentication to my web application built with Angular, which throws the following error: "auth/code-expired", "The SMS code has expired. Please resend the verification code to try again." even though I enter the code in a minute.
I've manually registered my phone number(iPhone) to the ID platform, and able to receive a verification code to my phone. Also, if I enter my phone number and verification code into the ID platform for development purpose, I can sign in without any problem.
I've read this question but seems not applicable in my case as the auth state does not change when I receive verification codes. The sms code has expired. Please re-send the verification code to try again
Can anyone tell me what's wrong? Below is the code I have.
<section>
<h4>Sign in with MFA</h4>
<div class="flex">
<input placeholder="Email" [(ngModel)]="email">
<input placeholder="Password" [(ngModel)]="pass">
<button (click)="onAuth()">Submit</button>
</div>
</section>
<section>
<div style="position:relative;z-index:10;width:100%;margin-top:2em;margin-left:2em;margin-right:auto;">
<div id="recaptcha-container"></div>
</div>
</section>
<section>
{{ user$ | async | json }}
</section>
import { Component } from '@angular/core';
import { AngularFireAuth } from '@angular/fire/auth';
import * as firebase from 'firebase';
import { environment } from 'src/environments/environment';
firebase.default.initializeApp(environment.firebaseConfig);
@Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
email: string = 'myEmail@gmail.com';
pass = 'myPassword';
windowRef;
resolver;
user$: Observable<any>;
constructor(
private fireAuth: AngularFireAuth,
) { }
ngOnInit(): void {
this.user$ = this.fireAuth.user;
this.windowRef = window;
this.windowRef.recaptchaVerifier = new firebase.default.auth
.RecaptchaVerifier(
'recaptcha-container',
{
'size': 'invisible',
'callback': (response) => {
console.log('recapcha solved', response);
}
});
}
onAuth() {
this.fireAuth.signInWithEmailAndPassword(this.email, this.pass)
.then(result => {
alert('Sign in Success');
})
.catch(err => {
console.log('Sign-in catch block', err);
if (err.code === 'auth/multi-factor-auth-required') {
alert('MFA required');
this.resolver = err.resolver;
const selectedIndex = 0;
// Ask user which second factor to use.
if (this.resolver.hints[selectedIndex].factorId === firebase.default.auth.PhoneMultiFactorGenerator.FACTOR_ID) {
const phoneNumber = prompt('Enter your phone number with a country code (e.g. +18881231234).');
const phoneInfoOptions = {
multiFactorHint: this.resolver.hints[selectedIndex],
session: this.resolver.session,
phoneNumber
};
const phoneAuthProvider = new firebase.default.auth.PhoneAuthProvider();
// Send SMS verification code
return phoneAuthProvider.verifyPhoneNumber(phoneInfoOptions.phoneNumber, this.windowRef.recaptchaVerifier)
.then((verificationId) => {
// Ask user for the SMS verification code.
const verificationCode = prompt('Enter the 6 digits verification code you received.');
const cred = firebase.default.auth.PhoneAuthProvider.credential(verificationId, verificationCode);
const multiFactorAssertion =
firebase.default.auth.PhoneMultiFactorGenerator.assertion(cred);
const result = this.resolver.resolveSignIn(multiFactorAssertion);
console.log('result', result); // **throws auth/code-expired**
// Complete sign-in.
return result;
})
.then((userCredential) => {
// User successfully signed in with the second factor phone number.
console.log('MFA success', userCredential);
});
} else {
// Unsupported second factor.
console.log('Unsupported second factor.');
}
} else {
alert('Sign in Failed');
}
});
}
}
Thank you in advance.