Firebase simple authentication with email/password - firebase

I'm new to Firebase and I'm attempting to set-up a simple authentication system using e-mail/password. The initial concept is simple: you register. Then, after logging in, you can access the rest of the mobile app.
In the past, I could set this up with PHP in just a few minutes. But with Firebase, this has become a battle that I can't seem to win.
Using the light documentation found on Firebase's site, I was finally able to successfully register and authenticate a user. Great.
Unfortunately, people can still access the rest of the app whether they are logged in or not. How do I keep the app protected from non-authenticated users?
Also, how do I associated data submitted on a page with an authenticated user?
I've looked at Firebase's documentation. It lacks practical examples for authentication. It keeps referring me to the Firefeed app as a sample. I've looked at Firefeed's code and the authentication system seems 1) excessively complicated for a login system and 2) too intricately tied in to news feeds to be a practical example to learn from.
On the other hand, perhaps I'm just missing something obvious and fundamental. If someone could point me in the right direction, that would be great. Thanks! :-)
(By the way, I tried e-mailing this question to firebase-talk#googlegroups.com, as suggested on Firebase's site... but the group does not appear to exist, according to the bounce-back message from Google.)

Stepping back for a moment, it's worth noting that Firebase Simple Login is an abstraction built on top of Firebase Custom Login for convenience. You can still use your existing authentication with Firebase using Custom Login, if you like.
Firebase Simple Login eliminates the need for you to run a server just for authentication. However, there is no 1-to-1 parallel to the PHP example where the server would govern request access based upon a detected session on the server because all of your logic, templates, etc. lives in client-side code.
In most cases, your client-side logic, templates, assets, etc. will be static and public. What you're really looking to secure is user and application data, and this is where Firebase Authentication (whether using Simple Login or Custom Login) comes in. Firebase Authentication is essentially token generation - taking confirmed, identifiable user data and passing it securely to Firebase so that it cannot be spoofed.
Read / write access to different paths in your Firebase data tree is governed by Firebase Security Rules, which allow you to write JavaScript-like expressions to control which clients can access which data.
Here's an example:
Suppose you have a user list, where each user is keyed by user id,
such as /users/<user-id>/<data>, and you want to ensure that only
the logged in user can read / write their own data. With Simple Login,
this is really easy!
Looking at the After
Authenticating
section of Email / Password authentication docs, we see that the
auth variable in our security rules will contain a number of fields
after authenticating, including id, the user's unique user id. Now
we can write our security rules:
{
"rules": {
".read": false,
".write": false,
"users": {
"$userid": {
".read": "auth != null && auth.uid == $userid",
".write": "auth != null && auth.uid == $userid"
}
}
}
}
What's going on here? Firebase Authentication (using Simple Login)
securely generated a token containing your verified user data upon
login, and that token data becomes available in your security rules
via the auth variable for the connection. Now, in order for a client
connection to read or write to /users/xyz, the user must be
authenticated and authenticated as user xyz.
Most of the above is covered in the Security Quickstart but it is admittedly a little hard to wrap your head around.
Back to your initial question, if you want to redirect away from certain paths when a user is not authenticated, you can do the following:
var ref = new Firebase(...);
var auth = new FirebaseSimpleLogin(ref, function(error, user) {
if (!user) {
// we're logged out, so redirect to somewhere else
} else {
// we're logged in! proceed as normal
}
});
Hope that helps!

Please note:
Login is now a core feature of Firebase. Simple Login has been
deprecated and documentation for this client is now available on
Github.
See this page for more info:
https://www.firebase.com/docs/web/guide/user-auth.html

Related

Firebase createUser with Email/password authentication [duplicate]

I am using the Simple Login Email / Password Authentication functionality of Firebase.
I would like to manage users through Forge only. I don't want users to be created via the client app.
However I would still like to let them login/logout though.
Is this possible?
You can't prevent users from being created on the client using simple login. There are two options you can utilize instead:
Simple Login "accounts" are really just tokens
Simple Login is just a convenience wrapper that creates Firebase tokens. There is no limit on how many accounts can be stored and they have no affect on your Firebase usage. With this in mind, there's really no reason you need to restrict creation of accounts.
Instead, just utilize security rules to control access to data. When an admin creates an account, have them also add a profile into the data. If only an admin in Forge is allowed to create the profile, then someone could create an account, but it would be superfluous and pointless, since all it does is give them an inert token.
A security rule to enforce access to data:
".write": "root.child('valid_account/'+auth.uid).exists()"
A security rule that allows users to edit their profile but only Forge (admin: true) to create them:
"profiles": {
"$uid": {
".write": "data.exists() && auth.uid === $uid && newData.exists()"
}
}
Creating your own tokens allows complete control
If you're terribly OCD and don't like that approach, then you can cut out Simple Login. As stated previously, it just creates tokens on your behalf. So simply create your own.
In this way you have complete control over account creation and token generation.

Firebase Simple Login - Prevent New Users

I am using the Simple Login Email / Password Authentication functionality of Firebase.
I would like to manage users through Forge only. I don't want users to be created via the client app.
However I would still like to let them login/logout though.
Is this possible?
You can't prevent users from being created on the client using simple login. There are two options you can utilize instead:
Simple Login "accounts" are really just tokens
Simple Login is just a convenience wrapper that creates Firebase tokens. There is no limit on how many accounts can be stored and they have no affect on your Firebase usage. With this in mind, there's really no reason you need to restrict creation of accounts.
Instead, just utilize security rules to control access to data. When an admin creates an account, have them also add a profile into the data. If only an admin in Forge is allowed to create the profile, then someone could create an account, but it would be superfluous and pointless, since all it does is give them an inert token.
A security rule to enforce access to data:
".write": "root.child('valid_account/'+auth.uid).exists()"
A security rule that allows users to edit their profile but only Forge (admin: true) to create them:
"profiles": {
"$uid": {
".write": "data.exists() && auth.uid === $uid && newData.exists()"
}
}
Creating your own tokens allows complete control
If you're terribly OCD and don't like that approach, then you can cut out Simple Login. As stated previously, it just creates tokens on your behalf. So simply create your own.
In this way you have complete control over account creation and token generation.

Does Firebase create accounts for all authentication types?

Email registrations are seen as a new record under the Simple Login → Email tab in our forge.
But what happens when a user Signs In using one of the OAuth2 logins like Facebook or Google?
Take the example right off the site and apply multiple contexts to it:
{
"rules": {
".read": true,
"comments": {
"$comment": {
".write": "auth != null",
".validate": "auth.id == newData.child('userid').val() && newData.hasChildren(['userid', 'body']) && newData.child('body').isString()"
}
}
}
}
If a user logs in with a Facebook account will Firebase create a new auth record and scope security rules in the same context as an Email/Password login?
If so are those registrations viewable in the same way as our Email auth type? Do you perform operations on those records like (delete) in the same way?
What would be the best way to scheme a master userId collection that enables a user to tie multiple account types together? (Facebook, Google, and Email all tied together)
Keep in mind that "creating a user" in that console (and in Firebase Simple Loign email / password auth. in general) only generates a new mapping between an email address and a password, and gives that account a unique, auto-incrementing id.
Firebase Simple Login will not automatically store any data in your Firebase, though upon login, it will automatically generate a new Firebase auth. token against which you may write security rules making use of the auth variable.
Login methods using any other provider currently store no data, though in the future there may be more functionality there. Logging in with Facebook / Google / etc. will also fetch a bunch of useful user metadata and send it down to the client, in addition to creating a Firebase auth. token for use in security rules. To see the contents of the auth variable across all providers, see the 'After Authenticating' section on each of the Simple Login Providers docs pages, for example: Facebook. There is no notion of a delete for any provider except for the email / password provider.
If you'd like to have user accounts that are linked to multiple social credentials, it can be done, though it is a little clunky (and manual) at present. See How can I login with multiple social services with Firebase? for a thorough walkthrough.

How do I modify the user properties managed by FirebaseSimpleLogin?

It seems like the only thing that can be changed is the password (via auth.changePassword()). How do I let a user change their email address or display name?
The firebase Auth object is pretty simple but it will provide you the user id generated when the user authenticates to your system. You would then take this user id and map it to a Users location where you can store additional information such as display name.
For example, after the user has authenticated and you have your auth object with id value, you could do:
new Firebase('https://your_fb_url.firebase.io').child('users/'+id).set({email: email, name: name}, function(err) {})
You'd want to have read/write rules setup on that location to only allow the authenticated user to see & make changes. Something like:
{
"rules": {
"users": {
"$user": {
".read": "$user == auth.uid",
".write": "$user == auth.uid",
}
}
}
}
6/12/2015 - UPDATE - Below is Outdated
As for changing the actual login e-mail (for Firebase Simple Login Web), that I'm not so sure about. I know they provide a change password method but I haven't seen any documentation about a change login/email method.
The underlying code for firebase simple password doesn't appear to include any methods for changing the login e-mail address associated with the account. The changePassword method eventually performs a jsonp call out to /auth/firebase/update with the email, old password, and new password.
I'd hate to suggest using a combination of removeUser/createUser to remove the old account, create a new account, and update any user id associations you have you in your app - but I don't see a straightforward "changeEmail" method. The remove/create route would require the user to enter their password again - though that's a pretty common practice for updating logins these days anyway.
6/12/2015 - UPDATE - New API
Firebase has moved away from Firebase Simple Login as a separate module and now the core Firebase 2.x library has authentication related methods baked in. Including a method to change the e-mail account used for the authWithPassword methods.
See updated 2.x docs for changeEmail()

Securing Firebase CRUD operations with users

Due to the thin AngularFire documentation and the differences between it and the default web documentation for Firebase, I'm a little lost on how best to secure Create, Read, Update, and Delete operations with users.
In short, say I have an application that manages stores. Users can be owners of the stores or patrons. Owners should read and edit their own stores in their view and patrons should read all but edit no stores in their view.
I'm concerned about the security of suggested methods by Firebase docs such as
So for example, we could have a rule like the following to allow users
to create comments as long as they store their user id with the
comment:
{
"rules": {
".read": true,
"$comment": {
".write": "!data.exists() && newData.child('user_id').val() == auth.id"
}
}
}
To me, this means that I could hack my application's data by simply passing in my victim's user id when I want to post a comment as them. Am I wrong?
I've read the security documentation thoroughly, several times. I think I need further explanation here. Identifying by a client-exposed parameter is the only method I can find so far.
In the example shown here, auth refers to the authenticated user's token data. This is a special variable set by Firebase during auth() events, and thus not something you could hack at the client. In other words, you would only be able to write a comment if you set the user_id value to your own account id.
The contents of the auth object depend on how the client authenticates. For example, SimpleLogin's password provider puts the following into the auth token: provider, email, and id; any of which could be utilized in the security rules.
It's also possible to sign your own tokens from a server, and of course the sky is the limit here.
But the bottom line is that the token's internal values are provided by a trusted process and not by the client, and thus cannot be altered by a user.

Resources