Adding Ionic Facebook login to your app can help to quickly sign in users, and the setup required to make it work with Capacitor is actually not too hard!
After we have seen how to use Google sign in or the new Sign in with Apple, today we will focus on the third major social authentication provider.
To do so we will use the Capacitor Facebook login plugin, which also needs some previous setup inside the Facebook developer tools.
Once we are done, our users will be able to sign in with Facebook using the native dialog, and we will also make a dummy API call to the Facebook Graph API to retrieve some user data as the prove that we are logged in!
Getting started with our Ionic Facebook App
Before we dive into the Facebook part, let’s make sure you have an Ionic app ready. If you want to test things out, go ahead with the following commands:
ionic start devdacticFbLogin blank --type=angular --capacitor --package-id=com.devdactic.fblogin cd ./devdacticFbLogin npm i @capacitor-community/facebook-login ionic build npx cap add ios npx cap add android
The important part is to have a real package id and not just the dummy one that Ionic apps usually use, so instead of com.devdactic.fblogin use your own id in there.
If you already have an existing app, simply make sure you have set your own appId inside the capacitor.config.json like:
{ "appId": "com.devdactic.fblogin", "appName": "devdacticFbLogin", "bundledWebRuntime": false, "npmClient": "npm", "webDir": "www", "plugins": { "SplashScreen": { "launchShowDuration": 0 } }, "cordova": {} }
This ID will be used within the next step, so make sure everything is right up until here.
Because we will make an Http request we should also quickly change the src/app/app.module.ts and include the HttpClientModule
like this:
import { NgModule } from '@angular/core'; import { BrowserModule } from '@angular/platform-browser'; import { RouteReuseStrategy } from '@angular/router'; import { IonicModule, IonicRouteStrategy } from '@ionic/angular'; import { SplashScreen } from '@ionic-native/splash-screen/ngx'; import { StatusBar } from '@ionic-native/status-bar/ngx'; import { AppComponent } from './app.component'; import { AppRoutingModule } from './app-routing.module'; import { HttpClientModule } from '@angular/common/http'; @NgModule({ declarations: [AppComponent], entryComponents: [], imports: [BrowserModule, IonicModule.forRoot(), AppRoutingModule, HttpClientModule], providers: [ StatusBar, SplashScreen, { provide: RouteReuseStrategy, useClass: IonicRouteStrategy } ], bootstrap: [AppComponent] }) export class AppModule {}
That’s it for the first app setup, now on to the Facebook app itself.
Facebook App Preparation
To use Ionic Facebook login, you first of all now need to create a Facebook app over at the Facebook developers page.
Simply create an account if you don’t have one yet, and then from within your app dashboard click “Create App” to start a new dialog.
I’m actually not 100% about the other options available but I picked the third option “Build Connected Experiences” and everything worked just fine.
Give your app a name and create the app – you will soon be inside the overview page of your app.
From the left menu, select Settings and Basic and scroll down that page until you see the Add Platform button.
Just like we usually do within Firebase, we now create apps in here for iOS and Android.
The only thing you need to add for iOS is the Bundle ID, which is exactly the ID we have seen in the beginning when setting up our app (or inside the capacitor.config.json).
Once you got the iOS part, you can go ahead with the Android app for which you now also need the key hash of the keystore that you use to sign your app.
For development, your key is usually located at ~/.android/debug.keystore with the default password android. To get the hash you can simply run:
keytool -exportcert -alias androiddebugkey -keystore ~/.android/debug.keystore | openssl sha1 -binary | openssl base64
Copy that hash output into the Android section Key Hashes, and add the bundle ID inside the Google Play Package Name field.
Now we have added both platforms to our Facebook app and we can continue within our Ionic app.
iOS Facebook Changes
At this point you should have added the native iOS platform to your Ionic Capacitor app, and we need to apply a few changes to it.
First, we need to overwrite the CFBundleURLTypes
and add some more keys inside the ios/App/App/Info.plist, which you can either open with Xcode or your standard IDE:
<key>CFBundleURLTypes</key> <array> <dict> <key>CFBundleURLSchemes</key> <array> <string>fb687134308903752</string> </array> </dict> </array> <key>FacebookAppID</key> <string>YOUR_FACEBOOK_APP_ID</string> <key>FacebookDisplayName</key> <string>YOUR_FACEBOOK_APP_NAME</string> <key>LSApplicationQueriesSchemes</key> <array> <string>fbapi</string> <string>fbauth2</string> </array>
Simply overwrite the existing CFBundleURLTypes
with the whole snippet above so everything you need is inside the plist.
Note: Of course use your own FacebookAppID and FacebookDisplayName inside that snippet!
For the next step you need to open the ios/App/App/AppDelegate.swift and add the two imports for the Facebook SDK at the top, and then change the two functions that are inside the snippet below.
The rest of that file can stay the same, make sure you only replace the relevant functions:
import UIKit import Capacitor import FacebookCore import FBSDKCoreKit @UIApplicationMain class AppDelegate: UIResponder, UIApplicationDelegate { func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { FBSDKCoreKit.ApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions) // Override point for customization after application launch. return true } func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool { // Called when the app was launched with a url. Feel free to add additional processing here, // but if you want the App API to support tracking app url opens, make sure to keep this call if CAPBridge.handleOpenUrl(url, options) { return FBSDKCoreKit.ApplicationDelegate.shared.application(app, open: url, options: options) } else{ return false } } }
Now the iOS part is ready and the app knows how to handle the return value after the native Facebook login is finished.
Android Facebook Changes
For Android, we first need to add the Capacitor plugin like always inside theandroid/app/src/main/java/com/devdactic/fblogin/MainActivity.java:
package com.devdactic.fblogin; import android.os.Bundle; import com.getcapacitor.BridgeActivity; import com.getcapacitor.Plugin; import java.util.ArrayList; public class MainActivity extends BridgeActivity { @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Initializes the Bridge this.init(savedInstanceState, new ArrayList<Class<? extends Plugin>>() {{ // Additional plugins you've installed go here add(com.getcapacitor.community.facebooklogin.FacebookLogin.class); }}); } }
Simply add the one line inside the init block and you are fine.
For the next step you need to paste the block below under the manifest -> application tag (where you can also see another activity tag).
Open the android/app/src/main/AndroidManifest.xml and insert at that location:
<meta-data android:name="com.facebook.sdk.ApplicationId" android:value="@string/facebook_app_id"/> <activity android:name="com.facebook.FacebookActivity" android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation" android:label="@string/app_name" /> <activity android:name="com.facebook.CustomTabActivity" android:exported="true"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.BROWSABLE" /> <data android:scheme="@string/fb_login_protocol_scheme" /> </intent-filter> </activity>
Finally we need to add our Facebook app id for two values, so open the android/app/src/main/res/values/strings.xml and change it to this (or simply add the two relevant rows since the rest contains my app bundle id!):
<?xml version='1.0' encoding='utf-8'?> <resources> <string name="app_name">devdacticFbLogin</string> <string name="title_activity_main">devdacticFbLogin</string> <string name="package_name">com.devdactic.fblogin</string> <string name="custom_url_scheme">com.devdactic.fblogin</string> <string name="facebook_app_id">YOUR_FACEBOOK_APP_ID</string> <string name="fb_login_protocol_scheme">fbYOUR_FACEBOOK_APP_ID</string> </resources>
Make sure you add fb before the FB App ID for the fb_login_protocol_scheme, that’s no typo! So it should be something like “fb1234567”.
That’s it, both of our native platforms are now configured!
Web Facebook Changes
If you also want to test the process on the browser because you want to build an Ionic website or simply for testing, you need to load the Facebook JS SDK inside the
src/index.html:
<script> window.fbAsyncInit = function () { FB.init({ appId: 'YOUR_FACEBOOK_APP_ID', cookie: true, // enable cookies to allow the server to access the session xfbml: true, // parse social plugins on this page version: 'v5.0' // use graph api current version }); }; // Load the SDK asynchronously (function (d, s, id) { var js, fjs = d.getElementsByTagName(s)[0]; if (d.getElementById(id)) return; js = d.createElement(s); js.id = id; js.src = "https://connect.facebook.net/en_US/sdk.js"; fjs.parentNode.insertBefore(js, fjs); }(document, 'script', 'facebook-jssdk')); </script>
Put that snippet simply below the body
of your page and insert your Facebook App id in the relevant place again.
Ionic Facebook Login
Now we can finally trigger the dialog from our Ionic app, which is actually the easiest part.
The only challenge is that the plugin is a bit different for web and native app, so we use a little switch inside the setupFbLogin
to check on which platform we are running and either use the web version (which is already registered at the top) or use the according object from the Capacitor plugins object.
Once this is done, you can call all functions on the plugin to login a user with specific permissions, which will give you an accessToken
plus more information inside a native app. When you run the app inside the browser preview, the plugin will only return the token and no other user information, so in that case we can directly call the getCurrentToken
which will then give us all relevant information.
Finally with the token in place and the user id available, we can make a dummy call to the Graph API inside the loadUserData
to retrieve some general information about that user!
Now go ahead and change the home/home.page.ts to:
import { Component } from '@angular/core'; import { FacebookLoginPlugin } from '@capacitor-community/facebook-login'; import { Plugins, registerWebPlugin } from '@capacitor/core'; import { isPlatform } from '@ionic/angular'; import { HttpClient } from '@angular/common/http'; import { FacebookLogin } from '@capacitor-community/facebook-login'; registerWebPlugin(FacebookLogin); @Component({ selector: 'app-home', templateUrl: 'home.page.html', styleUrls: ['home.page.scss'], }) export class HomePage { fbLogin: FacebookLoginPlugin; user = null; token = null; constructor(private http: HttpClient) { this.setupFbLogin(); } async setupFbLogin() { if (isPlatform('desktop')) { this.fbLogin = FacebookLogin; } else { // Use the native implementation inside a real app! const { FacebookLogin } = Plugins; this.fbLogin = FacebookLogin; } } async login() { const FACEBOOK_PERMISSIONS = ['email', 'user_birthday']; const result = await this.fbLogin.login({ permissions: FACEBOOK_PERMISSIONS }); if (result.accessToken && result.accessToken.userId) { this.token = result.accessToken; this.loadUserData(); } else if (result.accessToken && !result.accessToken.userId) { // Web only gets the token but not the user ID // Directly call get token to retrieve it now this.getCurrentToken(); } else { // Login failed } } async getCurrentToken() { const result = await this.fbLogin.getCurrentAccessToken(); if (result.accessToken) { this.token = result.accessToken; this.loadUserData(); } else { // Not logged in. } } async loadUserData() { const url = `https://graph.facebook.com/${this.token.userId}?fields=id,name,picture.width(720),birthday,email&access_token=${this.token.token}`; this.http.get(url).subscribe(res => { this.user = res; }); } async logout() { await this.fbLogin.logout(); this.user = null; this.token = null; } }
If you want to test other API calls, simply give the cool Facebook Graph API Explorer a try!
The last step is to simply show a few buttons to test our app, so go ahead and replace everything inside the home/home.page.html with:
<ion-header> <ion-toolbar color="primary"> <ion-title> Devdactic Facebook </ion-title> </ion-toolbar> </ion-header> <ion-content> <ion-card *ngIf="user"> <img [src]="user.picture.data.url"> <ion-card-header> <ion-card-title> {{ user.name }} </ion-card-title> <ion-card-subtitle> {{ user.birthday }} </ion-card-subtitle> </ion-card-header> <ion-card-content> {{ user.email }} <ion-button (click)="logout()" expand="full">Logout</ion-button> </ion-card-content> </ion-card> <ion-button (click)="login()" expand="full">Login</ion-button> </ion-content>
That’s it! Now run your app in the preview mode or on a real device and enjoy your Ionic Facebook login.
Conclusion
Adding Facebook login to your Ionic app isn’t very complicated if you follow the exact steps necessary to configure your app correctly upfront.
If you encounter problems, make sure you got the bundle ID correct everywhere and also that you are using the right Android hash.
You can also find a video version of this tutorial below:
The post How to Add Ionic Facebook Login with Capacitor appeared first on Devdactic - Ionic Tutorials.