We seem to have some users that either by mistake or on purpose
are signing up with email addresses that don't exist or are not theirs.
This issue's made worse by the fact that we've associated Google login emails
with the email password logins that the user enters.
This is starting to look like a major security issue.
Here, let me show you.
All right. So here's Walter.
And here we have an evil hacker.
Let's say that Walter logs in with Google and
that his Google account is associated with his Gmail account
which has the address americanguyw1521@gmail.com.
When this account was created it also creates a user in our database.
So he logs in and he's all happy and he makes some shopping lists.
Okay, so the hacker figures out Walter's Gmail address because
maybe Walter isn't too shy about sharing it.
He puts it up on a social networking site or something like that.
And then what the hacker does is he makes an account through email and
password, that uses the same email address.
And with how we've set things up, he can still choose whatever password he
likes and it's fine for him to use this email.
Because the real Walter never made a user in fire base with an email and
password, just with Google.
With the code as it is now.
These two accounts here are associated,
and they are considered to be the same user.
So the hacker has now essentially gotten into Walter's account
because the same email address was used for both.
And all those new permissions that we added such as only the owner can change
the name of the list, or only the owner can delete a list
are meaningless because well, the hacker has gotten into Water's account.
So he can rename Walter's list as much as he likes and
poor Walter is powerless to do anything about it.
As we start writing more code related to ownership of the app, Walter is going to
get the ability to make lists that are private to himself, but with this
security flaw, a hacker would be able to see all of Walter's items and lists.
Now you might be saying let's unassociate the two email addresses.
But this would still leave an issue that the hacker could enter the account and
sort of masquerade as Walter.
It would also mean that Walter could not use his own email address if he ever
decided to make an email password provider user.
So I think a better way to go about this is to try to think of a way that we
can have the user prove that they actually own the email address
that they've put in.
To do this,
you could employ a creative use of Firebase's password reset functionality.
Here I am in the Login and off tab.
And if you scroll down,
you'll see the section that's all about password resets.
In your code, you could trigger for a user to receive a password reset email.
And here's where you can configure what that email will will look like.
You can configure things like what the subject of the email will be
or who it's from.
And if you scroll down a little bit more,
here's the actual body of the email.
Now, this includes a token string and this token string is
basically the reset password that is generated for your user.
So with all of this in mind, here's the new flow that I'm thinking of.
First, when the user signs up, they'll no longer be asked for a password.
Instead, the screen will just take their email and their name.
This is the information that will be used in the call to create user.
We'll generate a sort of dummy password that we're going to throw away pretty
quickly, because if creating that user is successful,
we'll immediately reset the password using the resetPassword method.
Immediately after resetting the password,
an intent will open the user's default email app.
Now, resetPassword is the method that triggers that email to be sent to
the user and it uses the email address that they entered here so
as long as they're connected to the Internet they should
see that first email in their email inbox is the password reset email.
And they can go ahead and open that email and
get a randomly generated password.
They can then copy the password that's in their email and
navigate back to the app.
When they return to the app instead of seeing the create account activity
screen instead they'll see the log in activity screen.
And we can even be nice and
pre populate the email up here with whatever email they originally gave us.
Then if we instructed them to copy the password here,
they could paste it here and sign in.
And for now, the first time that the user signs in,
we can actually use fire bases change password method
to then change the random password that was originally generated for
the user, to the reset password that they just put in.
And then this way we can confirm that the user
at least has access to the email account that they put in here.
Okay, now this is by no means perfect.
For one, it makes the reset password the user's permanent password, and
the reset password's fairly hard to remember,
it's just some sort of random string of numbers and digits.
Also, when you call the resetPassword method,
whatever password is generated only works for 24 hours.
So there is a scenario where a user could create a new user,
get the reset email and then get busy and decide not to sign in,
and then try to sign in after 24 hours and lose access to their account.
But for beta version 0.3, I think this is a pretty good flow, and
it does remove the most glaring security flaws of our current login process.
Okay, so let me quickly show you these two methods that are new to you.
The reset code is pretty straightforward.
Just like everything else that we've been doing with authentication,
you should grab a Firebase ref.
You can then code reset password on that Firebase ref, and
all it really needs is an email address that's in the system,
which means an email address that you've called create user with.
If this reset password call is successful, it will send an email and
take it here, and if it's not successful you'll get the error down here.
This might happen for
example if you put in an email address here that doesn't exist in the system,
you'd get the user does not exist error that we've talked about before.
When the user signs in for the first time, you call change password method.
This will take that same email address of the user,
as well as the old password and the new password.
You can use the reset password for both of these.
Now you should only change the password
if this is the first time that the user is logging in.
I'll leave it up to you to decide how to check whether the user has logged in
before or hasn't logged in before.
And if you forgot why calling changePassword is important,
it's because the users reset password that they received in their email
is only valid for 24 hours.
Now if Shopping List Plus, Plus was going into production immediately,
what I'd have you do is create some extra screen so
the user could change their password from the reset password
to something that they could memorize a little bit easier.
But, again we'll start with this.
Okay the full spec is on the way, so good luck.