问题
I'm trying to have users of my app sign in by email + link, password-less. The client (written in React Native) asks for the sign-in link using the Javascript SDK like so, based on this answer:
var actionCodeSettings = {
// URL you want to redirect back to. The domain (www.example.com) for this
// URL must be in the authorized domains list in the Firebase Console.
url: `${BASE_URL}/verifyEmail?email=${email}`,
// This must be true.
handleCodeInApp: true,
iOS: {
bundleId: BUNDLE_ID
},
android: {
packageName: BUNDLE_ID,
installApp: true,
minimumVersion: '12'
},
dynamicLinkDomain: 'myapp.page.link'
};
await firebase.auth().sendSignInLinkToEmail(email, actionCodeSettings)
}
Then the user opens the email and follows the sign-in link. Ideally it deep links back to the app, but in case that doesn't happen (e.g. they do it on a different device), I still need it to verify their email address on my server, which is NodeJS. My /verifyEmail
handler should do that. According to this answer, the Firebase admin SDK can't verify action codes anymore. It suggests using the Firebase admin REST API, which says to effectively do:
curl 'https://identitytoolkit.googleapis.com/v1/accounts:update?key=AIzaSyCrFbTvuObVGlmGv9MK2sZ9MyS-VCkN--8' \
-H 'Content-Type: application/json' --data-binary '{"oobCode":"9LRoycB4fFrycmyLreYnjcAzxsGnwIpd9ub5tkpX_EQAAAF2-d9GoQ"}'
But I'm getting INVALID_OOB_CODE
as a result. To test, I copied the OOB code from the email link, without clicking it, directly into that cURL command.
What am I doing wrong? Looking at the Javascript client SDK's source, it seems that applyActionCode calls the same endpoint I'm calling here in the same way. I'm thinking maybe this method only works for verifying an email/password signup, but if so, how do I sign up someone without a password?
The only workaround I can think of is in /verifyEmail
to hash the oobCode, truncate the hash down to a user-friendly verification code, store the verification link on the server side, and ask the user to input that code in the app in order to retrieve the verification link to be used with EmailAuthProvider.credentialWithLink
. And reject if too much time passes. That's undesirable.
回答1:
I ended up doing the workaround mentioned in the last paragraph of the post. It works, and the one downside is that the user has to copy the code. It's the oobCode SHA256 hashed and truncated to a 6-digit hexadecimal string. With my 5 minute expiration time, an attacker would have to make 16^6 / (5 * 60) = ~55924
guesses per second to crack it. Good enough for my app; it's not a high-stakes situation.
This really needs to be easier from Firebase. I should just be able to call their API on my backend to check the validity of the email verification code.
来源:https://stackoverflow.com/questions/65695558/verifying-password-less-email-signup-in-firebase-admin