Previously I demonstrated how to use Oauth in an Ionic Framework 1 Android and iOS mobile application, but with Ionic 2 becoming all the rage, I figured my old guide needed a refresher.
Modern applications are always making use of APIs and data from third party services. The problem is, these remote services require a special kind of authentication to happen in order to work with the data they manage. The most common form of authentication for web services is Oauth.
In my Ionic Framework 1 tutorial I demonstrated Google Oauth, but this time we’re going to see how to use Facebook Oauth in an Ionic 2 application.
As you probably know already, Ionic 2 uses Angular. To best understand what we’re doing, it is best to make a fresh Ionic 2 application. From the Command Prompt (Windows) or Terminal (Mac and Linux), execute the following commands:
ionic start ExampleProject blank --v2
cd ExampleProject
ionic platform add ios
ionic platform add android
It is important to note that you must be using the Ionic CLI that supports Ionic 2. You must also be using a Mac if you wish to add and build for the iOS platform.
We’re going to be using a mobile web browser for the authentication flow. This means we’ll need to have the Apache Cordova InAppBrowser plugin installed. From your Terminal or Command Prompt with the project as your current directory, execute the following:
ionic plugin add cordova-plugin-inappbrowser
Before we start looking at code, we need to create a Facebook application. This can be done for free from the Facebook Developer Dashboard. During this creation process you want to make sure the Valid Oauth redirect URIs is set to http://localhost/callback
. This setting can be found in the Facebook Dashboard’s Settings -> Advanced tab.
Take note of the App ID of your Facebook application. This is also known as a Client ID and it will be used within the Ionic 2 application.
With that out of the way, let’s code!
Open your project’s app/pages/home/home.html file and change it to look like the following:
<ion-header>
<ion-navbar>
<ion-title>Oauth Project</ion-title>
</ion-navbar>
</ion-header>
<ion-content padding>
<button (click)="login()">Facebook Login</button>
</ion-content>
The above snippet is our UI. It contains only one button which will start the authentication flow. This is done through a login()
function that we’re going to create now.
Open your project’s app/pages/home/home.ts file and change it to look like the following:
import { Component } from '@angular/core';
import { NavController, Platform } from 'ionic-angular';
declare var window: any;
@Component({
templateUrl: 'build/pages/home/home.html'
})
export class HomePage {
public constructor(public navCtrl: NavController, private platform: Platform) {
}
public login() {
}
public facebookLogin(): Promise<any> {
}
}
There are two functions here. Since the authentication flow is an asynchronous process I figured it would be easiest to split it from our button call. In other words, login()
will call the facebookLogin()
function.
However, before going there, notice the line near the top that reads:
declare var window: any;
We are using an Apache Cordova plugin that has no TypeScript type definitions. If we don’t declare this important object as any
, we’ll get errors during the build phase. Now we can look at the functions.
Starting with the login()
function, add the following:
public login() {
this.platform.ready().then(() => {
this.facebookLogin().then(success => {
alert(success.access_token);
}, (error) => {
alert(error);
});
});
}
In the above function we first make sure the app is ready. This is a requirement before trying to use Apache Cordova plugins. We know that facebookLogin()
is asynchronous so we wait for a success or error event to happen and show a message appropriately.
This is where the complicated stuff comes in. Take a look at the following facebookLogin()
function, then we’ll break it down:
public facebookLogin(): Promise<any> {
return new Promise(function(resolve, reject) {
var browserRef = window.cordova.InAppBrowser.open("https://www.facebook.com/v2.0/dialog/oauth?client_id=" + "CLIENT_ID_HERE" + "&redirect_uri=http://localhost/callback&response_type=token&scope=email", "_blank", "location=no,clearsessioncache=yes,clearcache=yes");
browserRef.addEventListener("loadstart", (event) => {
if ((event.url).indexOf("http://localhost/callback") === 0) {
browserRef.removeEventListener("exit", (event) => {});
browserRef.close();
var responseParameters = ((event.url).split("#")[1]).split("&");
var parsedResponse = {};
for (var i = 0; i < responseParameters.length; i++) {
parsedResponse[responseParameters[i].split("=")[0]] = responseParameters[i].split("=")[1];
}
if (parsedResponse["access_token"] !== undefined && parsedResponse["access_token"] !== null) {
resolve(parsedResponse);
} else {
reject("Problem authenticating with Facebook");
}
}
});
browserRef.addEventListener("exit", function(event) {
reject("The Facebook sign in flow was canceled");
});
});
}
First off, notice that we’re wrapping the whole thing in a Promise
. When we’re finished and we know login was a success we’ll call the resolve
and if there is an error or bail out for any reason we’ll call the reject
.
Now notice the following line:
var browserRef = window.cordova.InAppBrowser.open("https://www.facebook.com/v2.0/dialog/oauth?client_id=" + "CLIENT_ID_HERE" + "&redirect_uri=http://localhost/callback&response_type=token&scope=email", "_blank", "location=no,clearsessioncache=yes,clearcache=yes");
We’re launching the InAppBrowser plugin and keeping reference of it so that way we can inspect it whenever we want. The URL launched is the required endpoint per the Facebook documentation. If you’re using a different provider, you’d change it as necessary.
Since we have the browser reference we can look at the current page every time it loads. This is done through the loadstart
event like so:
browserRef.addEventListener("loadstart", (event) => {});
If the current page starts with http://localhost/callback
like set as our redirect URI in the Facebook Dashboard, it means we’ve finished signing in and our access token is attached. We just need to parse the token out now.
The access token exists in the URL so the remainder of our code is just parsing it out and returning it successfully as an object to the user.
Above are some screenshots of what the Facebook Oauth flow might look like in the app we just made.
We just saw how to initiate a Facebook Oauth authentication flow in an Ionic 2 Android and iOS mobile application. It is a step up from our previous Ionic Framework 1 example. We saw how to use the Apache Cordova InAppBrowser plugin and monitor its events to process Facebook login which is an implicit grant flow. In all honesty, you can just use the ng2-cordova-oauth plugin I made to accomplish this stuff, but I’ll have another article on that subject.