Firebase Auth on Web - How to add spam protection for email/password login - firebase

For my website, I want to build my own login form for email/password based authentication using Firebase authentication instead of using FirebaseUI Web. I'll be using createUserWithEmailAndPassword JS function to create new user accounts. But how can I prevent spam registrations? Usually for web based forms, I would use Google Recaptcha and validate the recaptcha on my server. But here, I'm not using my server for creating the user accounts. I'm making a call on the client side to create the user accounts.
Of course, I'll be using email verification in the flow, but how would I prevent bots from creating the accounts in the first place?
I also understand that Firebase has some sort of limit for the number of requests per min from a single IP, but I would like to go further and try to prevent those registrations.
firebase.auth().createUserWithEmailAndPassword(email, password).catch(function(error) {
// Handle Errors here.
var errorCode = error.code;
var errorMessage = error.message;
// ...
});
Thanks.

After 2 years, this question is still valid and as far as I see, it is not possible. You probably do not need an answer to this question anymore but it may help others. Even if you succeed in doing something manually, those js functions will stay there and can be called manually by any user who knows how to do it.
If there are no hidden, top secret options which are not available in the documentation, this is not possible. There is a recaptcha option but it is only for Phone Authentication. So, it seems like you have 2 options.
Ignore and delete users who do not verify their email address.
Disable email option from Firebase console and implement your own
email authentication. Generate your own token and log user into
Firebase with that custom token. https://firebase.google.com/docs/auth/web/custom-auth

I'm following up on frankish's answer. He is totally correct, and I agree I think it's strange that Firebase automatically integrates ReCaptcha when doing phone authentication (and now when doing Phone MFA), but does not provide support in createUserWithEmailAndPassword for passing a recaptcha verifier. Thus, the only way to really get around this is to do something like the following:
Set up ReCaptcha (either V2 or V3) manually on your signup page. Do NOT use firebase. auth. RecaptchaVerifier, that is only for integration with phone authentication.
Immediately after calling createUserWithEmailAndPassword, you need to make a call to your own server that passes up the recaptcha token. There is a Firebase blog post here about how to do that with a Firebase Function: https://firebase.googleblog.com/2017/08/guard-your-web-content-from-abuse-with.html. Note I think it's a bit strange that Firebase documented how to do this with server-side functions but didn't directly integrate this with account creation.
The final point is that in your server-side code, after you make the call to validate the recaptcha token, you need to set a custom claim on the Firebase user with the Firebase Admin API. That claim can be something like recaptchaPassed: true (or false). For details on custom claims see https://firebase.google.com/docs/auth/admin/custom-claims.
After that, you can then do things based on the value of that custom claim. For example you could read that custom claim in other server-side calls, or you can use it in Firestore security rules (good blog post on this, https://medium.com/google-developers/controlling-data-access-using-firebase-auth-custom-claims-88b3c2c9352a). You could also choose to immediately delete the user server-side (using the admin API), if recaptcha verification fails.
Note it's important to understand that there is nothing that guarantees that some malicious script will call your server-side token verification function after the code on the client calls createUserWithEmailAndPassword. Thus, the only way the rest of your code can guarantee that a particular Firebase user passed recaptcha verification is by looking for your custom claim that you set on the user server-side.

Related

How to disable user account in Firebase Web JS SDK?

I am using Firebase Auth to authenticate users using the Email/Password Method. Sometimes I detect spam users that create a lot of accounts from one IP address. I want to block them to protect my app.
I know that there is a method called "Disable User Account" in Firebase Console. I want to use it in my project.
I searched in Stack Overflow as well as the Firebase Docs and found that this only can be done in Admin SDK but I want to use it in the Firebase Web JS SDK. So is there a method to do that like user.DisableAccount?
There is no method to disable a specific user's account in the client-side Firebase SDKs, as that would be a security risk.
But if you look at the documentation for updating a user with the Admin SDK, you'll see there is a property disabled that you can set to true.
From that moment in, that user won't be able to sign in or refresh their ID token. Their existing ID token is still valid though, and by default, that means it may take up to an hour for them to get signed out of your app. If that interval is a concern for your use case, have a look at the documentation on managing user sessions, specifically the section on detecting ID token revocation. While more work, this allows you more granular control of the expiration of the token.

Firebase create user with customClaim

I'm using the Firebase SDK on a React Native app. I'm authenticating users with onAuthStateChanged - works great.
If it doesn't return a user, they can sign up using their phone number.
For that I use the following on submitting the phone activation code:
...
const credential = firebase.auth.PhoneAuthProvider.credential(
verificationId,
verificationCode
);
await firebase.auth().signInWithCredential(credential).then((response) => {// creating a record on firestore. onAuthStateChanged will be re-triggered and store the user and token in state});
...
I would also like to set custom claims for the user. How do I do that? I cannot use admin SDK since this is the frontend and I also don't want to. I could fire a call to my graphQL to do it, but there is probably a way to add a custom claim in the flow above. How?
There is no supported way to modify custom claims from within a client app. Since custom claims are normally used to give special secure authorizations, it obviously be a security hole to allow user to assign claims to themselves. That's why it's recommended to use the Admin SDK on a secure backend you control.
Custom claims can only be set from a trusted environment. Otherwise anyone could make any claim they want about themselves, which defeats their purpose of securely adding information to a user profile.

How to integrate LINE login into Firebase Auth

I did some research and experiments on integrating LINE login with Firebase Auth using Flutter. I have some questions:
Looks like in Firebase Auth, there are AuthProvider, and in Flutter source code, I also found an OAuthProvider. There you can create Credential to include your idToken and access token. But I don't know how to specify the providerId in that Credential. I guess it is not possible, because Firebase hasn't integrate LINE login. The client side api: logInWithCredential can ONLY work with Firebase supported login methods, and you have to enable them in your Firebase console. Am I right?
So it looks like now I have to setup my own server to exchange LINE access token to Firebase custom token. In my server, I first verify access token and grab the LINE user profile, then I create a custom token, but there I have to decide a UID, which I have to use some pattern like LINE:${LINE_UID}. This looks like some hacking, is there a better way?
Admin API to create custom token only accept UID or optionally a user claim, I have no way to set its display name or some other basic info. So if I directly send the token with UID like LINE:${LINE_UID} to a client, then the client logInWithToken, it will create a user without display name if it doesn't exist. The only workaround I can image is, in the server-side, generate the LINE:${LINE_UID} and look up it in Admin API, if it doesn't exist, then I create a user with a proper display name. This looks again not so good, because the document said if you do logInWithToken, it will create one if it is not there, and we cannot use that because I want to set it's display name when it is created. Any better solution?
I want to link a user with multiple auth provider. I saw in the Firebase JWT, they are well included, that is cool. But those linked elements are user profile get via credential. So can we link a user to a LINE login? Which is not built-in Firebase Auth Provider? Is auth provider linking only valid for Firebase built-in provider?
Regards,
Xiang.
You're asking way too much in a single post, which makes it hard to help. I'll try to address below, but please follow the advice on How do I ask a good question going forward.
The general approach for adding LINE as an authentication provider is shown in this blog post: Authenticate your Firebase users with LINE Login. There is also a example, which shows how to use Cloud Functions as the server component for this. If you get stuck implementing those for Flutter, post the minimal, complete/standalone code that reproduces this issue.
The client side api: logInWithCredential can ONLY work with Firebase supported login methods, and you have to enable them in your Firebase console. Am I right?
Nope, you're wrong. You can also provide your own sign-in provider for Firebase, and use the tokens you mint there with the Firebase Authentication SDK.
This looks like some hacking, is there a better way?
The UID can be whatever you want, but you'll have to ensure it is unique. A common way to ensure global uniqueness is to embed some identifier for the provider in the UID. If you prefer another way to ensure global uniqueness, you're free to use that too of course.
I have no way to set its display name or some other basic info [when creating the account]
This is indeed a common problem with some providers, as you for example can't set the display name for the email+password provider until after the account has been created. With a custom provider you can put whatever information you want in the initial JWT already though.
can we link a user to a LINE login? Which is not built-in Firebase Auth Provider?
See Linking custom auth provider with Firebase
Late to the party .
but This article helps you which I publish on Medium.
I'm using A Flutter plugin LINE's native SDKs in Flutter apps with Dart. The plugin helps you integrate LINE Login features in your app. You can redirect users to LINE or a web page where they log in with their LINE credentials. package
Also, I make a git hub repo for the same.
Did you check out the firebase_auth plugin? It has lots of helpfull features.
https://pub.dev/packages/firebase_auth

How to communicate between vueJS app & symfony with Google Token?

I am implementing Google Sign in in my VueJS App and I have a few questions before starting:
How to create a user when a user clicks on Google sign in button?
Do I have to create a custom route just for that?
Do I have to generate a random password because it is mandatory?
When a user is already registered and clicks on Google Sign in.
Do I have to pass Google Token from Vue JS to Symfony, then with google API, verify if token is valid and generate a token from my symfony application?
If you have some good documentation, I'll take it.
To get this started, it's actually a relatively complicated functionality to implement. This is because you'll have to use custom (maybe multiple if one can both login with Google account or register to your own website) guard authenticators. Moreover, you will need to use an OAuth bundle like KnpUOAuth2ClientBundle or HWIOAuthBundle.
The answer to your questions:
You have to create a custom route for that but you do not need to generate a random password, you can just make password nullable and add checks that it is null only for users logged in through Google (if it's not possible for you then just add something random as password). Additionally, I would propose to add a field provider to your User entity if you are providing both google and your own authentication. You should set this to 'google' or 'website respectively.
The user authentication process is being handled by Google and you are getting an access token as response that contains user's information like name, email etc, so you do not really have to worry about validating passwords etc.
This article helps you get started with KnpUOAuth2ClientBundle.

Directly validate Firebase token from react native app

I implemented Auth with Firebase + Facebook. To be able to use the Auth with my custom backend I implemented the admin SDK on my node Server. Now I am trying to validate if my Firebase token is still valid to know when I need to show the login screen. I could probably send the token to my custom backend. But since I don't need anything else from the backend, it would be easier to directly call firebase from the client.
Does someone know if a function like that exists?
Firebase client SDKs periodically refresh the ID tokens and keep them alive. Therefore the token will remain valid, until the client explicitly invokes a sign out operation. See this discussion for more details: https://groups.google.com/forum/#!msg/firebase-talk/rjR0zYiiEhM/Clt9aFtgAwAJ (It is a little old, but still relevant

Resources