Now a
days most of an application need to know the user's identity to use
an application. Knowing a user's
identity allows an app to securely save user data in the cloud and
provide the same personalized experience across all of the user's
devices.
Firebase
Authentication provides backend services, easy-to-use SDKs, and
ready-made UI libraries to authenticate users to your app. It
supports authentication using passwords, popular federated identity
providers like Google, Facebook and Twitter, and more.
Firebase
Authentication integrates tightly with other Firebase services, and
it leverages industry standards like OAuth 2.0 and OpenID Connect, so
it can be easily integrated with your custom backend.
What
is Firebase?
Firebase
is a cloud service provider. It is now under google and this
service can replace your whole server side part of your application.
In many tutorials we had used MySQL and PHP for our database. But if
we will use Firebase we do not need any server side code or
configuration. We can directly use firebase. Firebase comes with a
bundle of many features.
Features of Firebase:
Key Capabilities:
-
FirebaseUI (beta) : The FirebaseUI Auth component implements best practices for authentication on mobile devices and websites, which can maximize sign-in and sign-up conversion for your app. It also handles edge cases like account recovery and account linking that can be security sensitive and error-prone to handle correctly.
- Email and Password based authentication: The Firebase Authentication SDK provides methods to create and manage users that use their email addresses and passwords to sign in. Firebase Authentication also handles sending password reset emails.
- Federated identity proivder integration: Authentication SDK provides methods to allow users to sign in with their Google,Facebook,Twitter, and Github accounts.
- Custom auth system integration: Connect your app's existing sign-in system to the Firebase Authentication SDK and gain access to Firebase Realtime Database and other Firebase services.
- Anonymous auth: Use Firebase features that require authentication without requiring users to sign in first by creating temporary anonymous accounts. If the user later chooses to sign up, you can upgrade the anonymous account to a regular account, so the user can continue where they left off.
Advantages of
Firebase:
Below are the steps you need to follow to configure firebase in your application.
Create a Firebase project in the Firebase console, if you don't already have one. If you already have an existing Google project associated with your mobile app, click Import Google Project. Otherwise, click Create New Project.
Available Libraries
The following libraries are available for the various Firebase features.
Configure Gradle
Then, in your module Gradle file (usually the
Various Social Firebase Authentication Types:
Firebase authentication provides different ways to authenticate users in your application.
Step#1 : To authenticate user with an email address
using Firebase Authetication you need to first initialize the
FirebaseAuth instance in your activities onCreate() method as below:
Step#2 : After initializing an instance you need to the user for their Email address and Password to authenticate them in an application using createUserWithEmailAndPassword() method from the Firebase instance object. This method takes two String paramteres for email and password and the OnCompletionListener to check for the task completion.
A Firebase User has fixed set of basic properties -a unique ID,a primary email address, a name and a photo URL- stored in the project's user database, that can be updated by the user.You can not add other properties to the Firebase User object directly; instead, you can store the additional properties in your Firebase Realtime Database.
The first time a user signs up to your app, the user's profile data is populated using the available information:
An auth listener gets notified in the following situations:
-
Super easy and quick to implement.
-
No server side configuration needed. No PHP Scripts and No
Database Designs.
-
Realtime update without using GCM.
-
Autoscaling built-in.
-
Can start for free (only need to start paying once we hit
50 connections)
-
Robust APIs for Javascript (including several frameworks
like Angular), iOS, and Android.
-
Built-in support for authentication services like Facebook,
Google, and Twitter.
-
Declarative Security Rules model allows us to enforce
read/write privileges and data validation throughout the tree.
-
Need to build indexes manually.
-
May need to build “event log” manually as well (in
separate sub-tree?).
-
Implementation of REST API could be difficult on embedded
platforms.
-
Data validation rules do not support complex objects
directly (you’d need to validate individual child nodes
separately).
Below are the steps you need to follow to configure firebase in your application.
Create a Firebase project in the Firebase console, if you don't already have one. If you already have an existing Google project associated with your mobile app, click Import Google Project. Otherwise, click Create New Project.
- Click Add Firebase to your Android app and follow the setup steps. If you're importing an existing Google project, this may happen automatically and you can just download the config file.
- When prompted, enter your app's package name. It's important to enter the package name your app is using; this can only be set when you add an app to your Firebase project.
- At the end,
you'll download a
google-services.json
file. You can download this file again at any time. - If you
haven't done so already, copy this into your project's module
folder, typically
app/
.
Available Libraries
The following libraries are available for the various Firebase features.
Configure Gradle
First, add rules to your project-level
build.gradle
file, to
include the google-services plugin: // Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.1.2'
//you need to add this line
classpath 'com.google.gms:google-services:3.0.0'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
task clean(type: Delete) {
delete rootProject.buildDir
}
Then, in your module Gradle file (usually the
app/build.gradle
),
add the apply plugin
line at the bottom
of the file to enable the Gradle plugin: apply plugin: 'com.android.application'
android {
compileSdkVersion 24
buildToolsVersion "24.0.0"
defaultConfig {
applicationId "net.simplifiedcoding.firebaseauthdemo"
minSdkVersion 15
targetSdkVersion 24
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
testCompile 'junit:junit:4.12'
compile 'com.android.support:appcompat-v7:24.0.0'
}
//add the following line
apply plugin: 'com.google.gms.google-services'
Various Social Firebase Authentication Types:
Firebase authentication provides different ways to authenticate users in your application.
-
Authenticate through Email
-
Authenticate through Google
-
Authenticate through Facebook
-
Authenticate through Twitter
1) Authenticate through
Email
public class SignupActivity extends FragmentActivity {
FirebaseAuth mFirebaseAuth;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_signup);
//initializing firebase auth object
mFirebaseAuth = FirebaseAuth.getInstance();
}
Step#2 : After initializing an instance you need to the user for their Email address and Password to authenticate them in an application using createUserWithEmailAndPassword() method from the Firebase instance object. This method takes two String paramteres for email and password and the OnCompletionListener to check for the task completion.
mFirebaseAuth.createUserWithEmailAndPassword(mEmail, mPassword).addOnCompleteListener
(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
if (task.isSuccessful()) {
Snackbar.make(pView, "Authentication Successfull!", Snackbar.LENGTH_SHORT).show();
} else {
Snackbar.make(pView, "Authentication Failed!", Snackbar.LENGTH_SHORT)
.show();
}
}
});
That's
it. FirebaseAuth API has made the authentication process so easy and
faster.
A Firebase User has fixed set of basic properties -a unique ID,a primary email address, a name and a photo URL- stored in the project's user database, that can be updated by the user.You can not add other properties to the Firebase User object directly; instead, you can store the additional properties in your Firebase Realtime Database.
The first time a user signs up to your app, the user's profile data is populated using the available information:
-
If the user signed up with an email address and password, only the primary email address property is populated
-
If the user signed up with a federated identity provider, such as Google or Facebook, the account information made available by the provider is used to populate the Firebase User's profile.
-
If the user signed up with your custom auth system, you must explicitly add the information you want to the Firebase User's profile.
Once a user account has been created,
you can reload the user's information to incorporate any changes the
user might have made on another device. But if the user signout the
Auth instance stops keeping a reference of the user object and no
longer persists its state; there is no current user available. One
way to track the current state of the Firebase Auth instance is the
listener.
An auth listener gets notified in the following situations:
-
The Auth object finishes initializing and a user was
already signed in from a previous session, or has been redirected
from an identity provider's sign-in flow.
-
A user signs in (the current user is set)
-
A user signs out (the current user becomes null)
-
The access token expires: this is a common
situation. The refresh token is used to get a new valid set of
tokens.
-
The user changes his password: Firebase issues new
access and refresh tokens and renders the old tokens expired. This
automatically signs out the user on every device, for security
reasons
-
The user re-authenticates: some actions require that
the user's credentials are recently issued; such actions include
deleting an account, setting a primary email address, and changing a
password. Instead of signing out the user and then signing in the
user again, get new credentials from the user, and pass the new
credentials to the re-authenticate method of the User object.
Auth Tokens generated by Firebase Auth:
When you perform authentication with Firebase, there are three kinds of auth tokens you might encounter:
Getting Signed In User's details
Firebase Auth allows you to access the basic details of the signed In user as below:
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null) {
// User is signed in
} else {
// No user is signed in
}
To get a user's profile
information, use the accessor methods of an instance of FirebaseUser
.
For example: FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
if (user != null) {
// Name, email address, and profile photo Url
String name = user.getDisplayName();
String email = user.getEmail();
Uri photoUrl = user.getPhotoUrl();
// The user's ID, unique to the Firebase project. Do NOT use this value to
// authenticate with your backend server, if you have one. Use
// FirebaseUser.getToken() instead.
String uid = user.getUid();
}
You can update User's basic Profile information i.e. User's name, a photo using updateProfile method.
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
UserProfileChangeRequest profileUpdates = new UserProfileChangeRequest.Builder()
.setDisplayName("Q. User")
.setPhotoUri(Uri.parse("https://example.com/profile.jpg"))
.build();
user.updateProfile(profileUpdates)
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "User profile updated.");
}
}
});
Update User's Email address
You can set a user's email address with the updateEmail
method.
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
user.updateEmail("user@example.com")
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "User email address updated.");
}
}
});
Send an Email Verification
You can send an address verification email to a user with the
sendEmailVerification
method. For
example:
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
user.sendEmailVerification()
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "Email sent.");
}
}
});
Update User's Password
You can set a user's password with the
updatePassword
method. For
example:
FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
String newPassword = "SOME-SECURE-PASSWORD";
user.updatePassword(newPassword)
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "User password updated.");
}
}
});
Send Password Re-set Email
You can send a password reset email to a user with the
sendPasswordResetEmail
method. For
example: FirebaseAuth auth = FirebaseAuth.getInstance();
String emailAddress = "user@example.com";
auth.sendPasswordResetEmail(emailAddress)
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "Email sent.");
}
}
});
Delete SignedIn User
You can customize the email template that is used in Authentication section of the Firebase console, on the Email Templates page. You can delete a user account with the
delete
method. For
example: FirebaseUser user = FirebaseAuth.getInstance().getCurrentUser();
user.delete()
.addOnCompleteListener(new OnCompleteListener<Void>() {
@Override
public void onComplete(@NonNull Task<Void> task) {
if (task.isSuccessful()) {
Log.d(TAG, "User account deleted.");
}
}
});
2) Authenticate through Google
You can let
your users authenticate with Firebase using their Google Accounts by
integrating Google Sign-In into your app. To
enable Google Sign-In follow integration steps.
Before authenticating from your Google account using Firebase, it is necessary to complete the following steps to enable Google Sign-In in Firebase:
-
Add
Firebase to your Android project.
-
Add the dependencies for Firebase Authentication and Google
Sign-In to your app-level
build.gradle
file:
- compile 'com.google.firebase:firebase-auth:9.6.0'
- compile 'com.google.android.gms:play-services-auth:9.6.0'
-
If you haven't yet connected your app to your Firebase
project, do so from the Firebase
console.
- Enable Google Sign-In in the Firebase console:
-
In the Firebase
console, open the Auth section.
-
On the Sign in method tab, enable the Google sign-in
method and click Save.
Authenticate Google with
Firebase
-
Integrate Google
Sign-In into your app by following the steps on the Integrating
Google Sign-In into Your Android App page. When you configure
the
GoogleSignInOptions
object, callrequestIdToken
:
// Configure Google Sign In
GoogleSignInOptions gso = new GoogleSignInOptions.Builder(GoogleSignInOptions.DEFAULT_SIGN_IN)
.requestIdToken(getString(R.string.default_web_client_id))
.requestEmail()
.build();
You
must pass your server's
client ID to the
requestIdToken
method. To
find the OAuth 2.0 client ID:-
Open the Credentials page in the API Console.
-
The Web application type client ID is your backend server's OAuth 2.0 client ID.
private void signIn() {
Intent signInIntent = Auth.GoogleSignInApi.getSignInIntent(mGoogleApiClient);
startActivityForResult(signInIntent, RC_SIGN_IN);
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
// Result returned from launching the Intent from GoogleSignInApi.getSignInIntent(...);
if (requestCode == RC_SIGN_IN) {
GoogleSignInResult result = Auth.GoogleSignInApi.getSignInResultFromIntent(data);
if (result.isSuccess()) {
// Google Sign In was successful, authenticate with Firebase
GoogleSignInAccount account = result.getSignInAccount();
firebaseAuthWithGoogle(account);
} else {
// Google Sign In failed, update UI appropriately
// ...
}
}
}
2. In your sign-in activity's onCreate()
method, get the shared instance of the FirebaseAuth
object: private FirebaseAuth mAuth;
// ...
mAuth = FirebaseAuth.getInstance();
3.Set up an AuthStateListener
that responds to changes in the user's sign-in state: private FirebaseAuth.AuthStateListener mAuthListener;
// ...
@Override
protected void onCreate(Bundle savedInstanceState) {
// ...
mAuthListener = new FirebaseAuth.AuthStateListener() {
@Override
public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
// User is signed in
Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
} else {
// User is signed out
Log.d(TAG, "onAuthStateChanged:signed_out");
}
// ...
}
};
// ...
}
@Override
public void onStart() {
super.onStart();
mAuth.addAuthStateListener(mAuthListener);
}
@Override
public void onStop() {
super.onStop();
if (mAuthListener != null) {
mAuth.removeAuthStateListener(mAuthListener);
}
}
4.After a user successfully signs in, get an ID token from the GoogleSignInAccount
object, exchange
it for a Firebase credential, and authenticate with Firebase using the Firebase credential:
private void firebaseAuthWithGoogle(GoogleSignInAccount acct) {
Log.d(TAG, "firebaseAuthWithGoogle:" + acct.getId());
AuthCredential credential = GoogleAuthProvider.getCredential(acct.getIdToken(), null);
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
Log.d(TAG, "signInWithCredential:onComplete:" + task.isSuccessful());
// If sign in fails, display a message to the user. If sign in succeeds
// the auth state listener will be notified and logic to handle the
// signed in user can be handled in the listener.
if (!task.isSuccessful()) {
Log.w(TAG, "signInWithCredential", task.getException());
Toast.makeText(GoogleSignInActivity.this, "Authentication failed.",
Toast.LENGTH_SHORT).show();
}
// ...
}
});
}
If the call to signInWithCredential
succeeds, the AuthStateListener
runs theonAuthStateChanged
callback.
In the callback, you can use thegetCurrentUser
method to get the user's account data. You can allow users to sign in to your app using multiple authentication providers by linking auth provider credentials to an existing user account.
3) Authenticate through FacebookYou can let your users authenticate with Firebase using their Facebook accounts by integrating Facebook Login into your app by follow below steps.
Steps of Facebook Integration:
-
Add
Firebase to your Android project.
-
If you haven't yet connected your app to your Firebase
project, do so from the Firebase
console.
-
Add the dependency for Firebase Authentication to your
app-level
build.gradle
file:
compile 'com.google.firebase:firebase-auth:9.6.0' -
On the Facebook
for Developers site, get the App ID and an App Secret for your
app.
-
Enable Facebook Login:
-
In the Firebase
console, open the Auth section.
-
On the Sign in method tab, enable the Facebook sign-in
method and specify the App ID and App Secret you got
from Facebook.
-
Then, make sure your OAuth redirect URI(e.g.
my-app-12345.firebaseapp.com/__/auth/handler
) is listed as one of your OAuth redirect URIs in your Facebook app's settings page on the Facebook for Developers site in the Product Settings > Facebook Login config.
-
In the Firebase
console, open the Auth section.
Integrate Facebook
Login into your app by following the developer's
documentation. When you configure the
LoginButton
or LoginManager
object, request
the public_profile
and email
permissions.
If you integrated Facebook Login using a LoginButton
,
your sign-in activity has code similar the following: // Initialize Facebook Login button
mCallbackManager = CallbackManager.Factory.create();
LoginButton loginButton = (LoginButton) findViewById(R.id.button_facebook_login);
loginButton.setReadPermissions("email", "public_profile");
loginButton.registerCallback(mCallbackManager, new FacebookCallback<LoginResult>() {
@Override
public void onSuccess(LoginResult loginResult) {
Log.d(TAG, "facebook:onSuccess:" + loginResult);
handleFacebookAccessToken(loginResult.getAccessToken());
}
@Override
public void onCancel() {
Log.d(TAG, "facebook:onCancel");
}
@Override
public void onError(FacebookException error) {
Log.d(TAG, "facebook:onError", error);
}
});
After a user successfully signs in, in the
LoginButton's
onSuccess
callback method, get an access
token for the signed-in user, exchange it for a Firebase credential,
and authenticate with Firebase using the Firebase credential: private void handleFacebookAccessToken(AccessToken token) {
Log.d(TAG, "handleFacebookAccessToken:" + token);
AuthCredential credential = FacebookAuthProvider.getCredential(token.getToken());
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
Log.d(TAG, "signInWithCredential:onComplete:" + task.isSuccessful());
// If sign in fails, display a message to the user. If sign in succeeds
// the auth state listener will be notified and logic to handle the
// signed in user can be handled in the listener.
if (!task.isSuccessful()) {
Log.w(TAG, "signInWithCredential", task.getException());
Toast.makeText(FacebookLoginActivity.this, "Authentication failed.",
Toast.LENGTH_SHORT).show();
}
}
});
}
If the call to signInWithCredential succeeds, the AuthStateListener runs the onAuthStateChanged callback. In the callback, you can use the getCurrentUser method to get user's account data.Note: For the Facebook authentication you have to make a registered user of facebook developer console live until and unless you won't be able to test its configuration flow. Otherwise, you will get an error like: App Not Setup: The developers of this app have not set up this app properly for Facebook Login. To resolve this error you need to make user live, as per given solution here: http://stackoverflow.com/a/26135600/1839336. After completing this configuration process you will be able to check the facebook authentication flow. Not up to here I also got the following error :
Given URL is not allowed by the Application configuration.: One or more of the given URLs is not allowed by the App's settings. It must match the Website URL or Canvas URL, or the domain must be a subdomain of one of the App's domains.
It has been solved after adding our application in platform tab with all the details and generate key hashes using Generate facebook Key Hashes: keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64 and mentioned solution as here: http://stackoverflow.com/a/16347026/1839336
4) Authenticate through TwitterWe can also let the users use their Twitter account to authenticate with Firebase.As you will have to sign in using Twitter, you will have to go through all the steps required to integrate Twitter in your app. If you haven't done so, follow the steps specified in Twitter For Developers.
Steps of Twitter Integration:
-
Add
Firebase to your Android project.
-
If you haven't yet connected your app to your Firebase
project, do so from the Firebase
console.
-
Add the dependency for Firebase Authentication to your
app-level
build.gradle
file:
compile 'com.google.firebase:firebase-auth:9.6.0' -
Register your app as a developer application on Twitter and get your app's API Key and API Secret.
-
Enable Twitter Login:
-
In the Firebase
console, open the Auth section.
-
On the Sign in method tab, enable the Twitter sign-in
method and specify the API Key and API
Secret you got from Twitter.
Then, make sure your OAuth redirect URI(e.g.my-app-12345.firebaseapp.com/__/auth/handler
) is set as your Callback URL in your app's settings page on your Twitter app's config.
-
In the Firebase
console, open the Auth section.
-
Integrate Sign in with Twitter into your app by following
the developer's
documentation. At the end of the Twitter sign-in flow, you will
receive an OAuth access token and an OAuth secret.
-
Initialize FirebaseAuth in
your activities onCreate method.
-
Set up an
AuthStateListener
that responds to changes in the user's sign-in state:
private FirebaseAuth.AuthStateListener mAuthListener;
@Override
protected void onCreate(Bundle savedInstanceState) {
mAuthListener = new FirebaseAuth.AuthStateListener() {
@Override
public void onAuthStateChanged(@NonNull FirebaseAuth firebaseAuth) {
FirebaseUser user = firebaseAuth.getCurrentUser();
if (user != null) {
// User is signed in
Log.d(TAG, "onAuthStateChanged:signed_in:" + user.getUid());
} else {
// User is signed out
Log.d(TAG, "onAuthStateChanged:signed_out");
}
}
};
}
@Override
public void onStart() {
super.onStart();
mAuth.addAuthStateListener(mAuthListener);
}
@Override
public void onStop() {
super.onStop();
if (mAuthListener != null) {
mAuth.removeAuthStateListener(mAuthListener);
}
}
4.After a user successfully signs in with Twitter, exchange the OAuth access token and OAuth secret for a
Firebase credential, and authenticate with Firebase using the Firebase credential:
private void handleTwitterSession(TwitterSession session) {
Log.d(TAG, "handleTwitterSession:" + session);
AuthCredential credential = TwitterAuthProvider.getCredential(
session.getAuthToken().token,
session.getAuthToken().secret);
mAuth.signInWithCredential(credential)
.addOnCompleteListener(this, new OnCompleteListener<AuthResult>() {
@Override
public void onComplete(@NonNull Task<AuthResult> task) {
Log.d(TAG, "signInWithCredential:onComplete:" + task.isSuccessful());
// If sign in fails, display a message to the user. If sign in succeeds
// the auth state listener will be notified and logic to handle the
// signed in user can be handled in the listener.
if (!task.isSuccessful()) {
Log.w(TAG, "signInWithCredential", task.getException());
Toast.makeText(TwitterLoginActivity.this, "Authentication failed.",
Toast.LENGTH_SHORT).show();
}
}
});
}
If the call to signInWithCredential
succeeds, the AuthStateListener
runs the onAuthStateChanged
callback.
In the callback, you can use the getCurrentUser
method to get the user's account data.
Signout From Firebase
You can signout from Firebase using the following: FirebaseAuth.getInstance().signOut();
Download Sourcecode
Reference