OTP Login Integration in SAP UI5 using Google Firebase

Introduction

Welcome to the ultimate guide for integrating OTP (One-Time Password) login functionality in SAP UI5 using the power of Google Firebase! If you’re looking to enhance the security and user experience of your SAP UI5 application, implementing OTP login is a fantastic choice.

In this comprehensive tutorial, we will walk you through the step-by-step process of seamlessly integrating OTP login functionality into your SAP UI5 application using Google Firebase. By leveraging Firebase’s robust authentication services, you can provide users with a secure and convenient login experience.

In the world of modern web applications, OTP login has become increasingly popular due to its effectiveness in preventing unauthorized access. With OTP login, users receive a unique, time-sensitive code via SMS or email, which they enter to authenticate themselves. This adds an extra layer of security to your application.

Throughout this tutorial, we will cover everything you need to know to successfully integrate OTP login in your SAP UI5 application. Starting from setting up a Firebase project and configuring the necessary Firebase services, to implementing OTP generation and verification logic within your application, we’ve got you covered.

You will learn how to leverage Firebase Authentication and the Firebase SDK to generate and send OTP codes to users. We will guide you through the process of capturing and validating OTPs, ensuring a smooth and secure login process. Additionally, we’ll explore best practices for handling error scenarios and improving the overall user experience.

By the end of this tutorial, you’ll have a fully functional OTP login system integrated seamlessly into your SAP UI5 application, powered by the secure and reliable infrastructure of Google Firebase.

So, if you’re ready to take your SAP UI5 application’s security to the next level, join us in this exciting journey of OTP login integration. Let’s get started on creating a secure, user-friendly, and highly-protected login system for your SAP UI5 application using Google Firebase.

OTP Login Integration in SAP UI5 using Google Firebase

Sure! Here are the steps to do OTP login integration in SAP UI5 using Google Firebase:

1. Set up a Firebase project: Create a new Firebase project or use an existing one. Go to the Firebase console (https://console.firebase.google.com/) and create a new project. Enable the Firebase Authentication service for your project.

Enable Authentication in Google Firebase

Enable the test OPT Mobile Number in Google Firebase:

Test OPT Mobile Number in Google Firebase

2. Install the Firebase SDK: In your SAP UI5 project, open the terminal or command prompt and navigate to the project directory. Run the following command to install the Firebase JavaScript SDK:

npm install firebase

3. Initialize Firebase: Create a new JavaScript file in your SAP UI5 project, such as “firebase.js”. Import the Firebase SDK and initialize Firebase with your project’s configuration. Obtain the Firebase configuration object from the Firebase console by navigating to Project Settings > General > Your apps > Firebase SDK snippet. Copy the code snippet for the web app configuration and paste it into your “firebase.js” file.

4. Generate and send OTP: Implement a user interface in your SAP UI5 app where users can enter their phone number or email address. When the user requests an OTP, use the Firebase Authentication SDK to generate and send the OTP to the provided phone number or email address.

5. Verify OTP: Create another user interface where users can enter the OTP they received. Use the Firebase Authentication SDK to verify the entered OTP against the generated OTP. If the verification is successful, proceed with the login process.

6. Handle authentication events: Implement Firebase authentication state listeners to detect when a user is logged in or logged out. Update your SAP UI5 app’s UI and behavior accordingly based on the user’s authentication status.

7. Test and refine: Test the OTP login integration thoroughly to ensure a smooth user experience. Verify that OTPs are generated and delivered correctly and that the verification process is working as expected. Handle error scenarios gracefully and provide appropriate feedback to the user.

By following these steps, you’ll be able to integrate OTP login functionality into your SAP UI5 application using Google Firebase. Remember to consult the Firebase documentation and the SAP UI5 guidelines for more detailed instructions and best practices. Happy coding!

UI5 Code to Integrate OTP Login using Google Firebase

index.html

<!DOCTYPE html>
<html>
    <head>
        <meta charset="utf-8">
        <!--<meta name="viewport" content="width=device-width, initial-scale=1.0">-->
        <title>HealthBridge Doctor</title>
          <link rel="icon" type="image/x-icon" href="https://healthbridge-intl.com/wp-content/uploads/2021/09/cropped-Colour-Logo-Only-1-32x32.png">
        <script id="sap-ui-bootstrap"
            src="https://openui5.hana.ondemand.com/1.96.7/resources/sap-ui-core.js"
            data-sap-ui-theme="sap_fiori_3"
            data-sap-ui-resourceroots='{"Healthbridge-Doctor.Healthbridge-Doctor": "./"}'
            data-sap-ui-compatVersion="edge"
            data-sap-ui-oninit="module:sap/ui/core/ComponentSupport"
            data-sap-ui-async="true"
            data-sap-ui-frameOptions="trusted">
        </script>
<!--Check if device is mobile: Create a media condition that targets viewports at least 768px wide-->
<script>
const mediaQuery = window.matchMedia('(max-width: 768px)')
// Check if the media query is true
if (mediaQuery.matches) {
  // Then trigger an alert
  alert('This device is not supported, contact Admin!')
  window.location = 'https://healthbridge-intl.com/';
}
</script>
        <!-- Insert these scripts at the bottom of the HTML, but before you use any Firebase services -->
<script type="text/javascript" src="https://unpkg.com/virgil-crypto@^4.0.0/dist/browser.umd.js"></script>
   <!-- Firebase App (the core Firebase SDK) is always required and must be listed first -->
  <script src="https://www.gstatic.com/firebasejs/7.14.5/firebase-app.js"></script>

  <!-- If you enabled Analytics in your project, add the Firebase SDK for Analytics -->
  <script src="https://www.gstatic.com/firebasejs/7.14.5/firebase-analytics.js"></script>

  <!-- Add Firebase products that you want to use -->
  <script src="https://www.gstatic.com/firebasejs/7.23.0/firebase-auth.js"></script>
  <script src="https://www.gstatic.com/firebasejs/7.14.5/firebase-firestore.js"></script>
  <script src="https://www.gstatic.com/firebasejs/7.14.5/firebase-database.js"></script>
  <script src="https://www.gstatic.com/firebasejs/7.23.0/firebase-storage.js"></script>
  <script src="https://www.gstatic.com/firebasejs/7.8.0/firebase-functions.js"></script>
  
  <!-- Agora Scripts -->
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
<script src="https://download.agora.io/sdk/release/AgoraRTC_N.js"></script>
    </head>
    <body class="sapUiBody">
        <div data-sap-ui-component data-name="Healthbridge-Doctor.Healthbridge-Doctor" data-id="container" data-settings='{"id" : "Healthbridge-Doctor"}'></div>
    </body>
</html>

 

Model.js

sap.ui.define([
    "sap/ui/model/json/JSONModel",
    "sap/ui/Device"
], function (JSONModel, Device) {
    "use strict";

    return {

        createDeviceModel: function () {
            var oModel = new JSONModel(Device);
            oModel.setDefaultBindingMode("OneWay");
            return oModel;
        },

        //app Congiguration model
        createAppConfigModel: function () {
            var appData = {
                "otpSent": false
            };
            var oModel = new JSONModel(appData);
            return oModel;
        }

    };
});

 

Firebase.js

sap.ui.define([
    "sap/ui/model/json/JSONModel",
], function (JSONModel) {
    "use strict";
    return {
        // Firebase-config retrieved from the Firebase-console
        initializeFirebase: function () {
            // Replace with your config here
            const firebaseConfig = {
                apiKey: "AIzaSyBGCi3pHJZqMmpJEeNjnoII8Ic_BL2v8vU",
                authDomain: "myprojectideas-c2512.firebaseapp.com",
                projectId: "myprojectideas-c2512",
                storageBucket: "myprojectideas-c2512.appspot.com",
                messagingSenderId: "121838639924",
                appId: "1:121838639924:web:39794cab14d51551172361"
            };
            // Initialize Firebase with the Firebase-config
            firebase.initializeApp(firebaseConfig);

            // Create a Firestore reference
            const firestore = firebase.firestore();

            // Create a Authentication reference
            const fireAuth = firebase.auth();

            // Get Firebase Instance
            const oFirestore = firebase.firestore;

            // Create a Fire Storage reference
            const fireStorage = firebase.storage();

            // Create a Fire Functions reference
            const fireFunctions = firebase.app().functions('asia-east2');

            // Firebase services object
            const oFirebase = {
                firestore: firestore,
                fireAuth: fireAuth,
                oFirestore: oFirestore,
                fireStorage: fireStorage,
                fireFunctions: fireFunctions
            };

            // Create a Firebase model out of the oFirebase service object which contains all required Firebase services
            var fbModel = new JSONModel(oFirebase);

            // Return the Firebase Model
            return fbModel;
        }
    };
});

 

Component.js

sap.ui.define([
    "sap/ui/core/UIComponent",
    "sap/ui/Device",
    "firebaseApp/firebaseApp/model/models",
    "firebaseApp/firebaseApp/js/Firebase"
], function (UIComponent, Device, models, Firebase) {
    "use strict";

    return UIComponent.extend("firebaseApp.firebaseApp.Component", {

        metadata: {
            manifest: "json"
        },

        /**
         * The component is initialized by UI5 automatically during the startup of the app and calls the init method once.
         * @public
         * @override
         */
        init: function () {
            // call the base component's init function
            UIComponent.prototype.init.apply(this, arguments);

            // enable routing
            this.getRouter().initialize();

            // set the device model
            this.setModel(models.createDeviceModel(), "device");

            // set the app Config model
            this.setModel(models.createAppConfigModel(), "AppConfig");

            //set Firebase Model
            this.setModel(Firebase.initializeFirebase(), "fbModel");
        }
    });
});

 

Login.view.xml

<mvc:View controllerName="firebaseApp.firebaseApp.controller.Login" xmlns:mvc="sap.ui.core.mvc" displayBlock="true" xmlns="sap.m"
    xmlns:html="http://www.w3.org/1999/xhtml" xmlns:core="sap.ui.core">
    <Shell id="shell">
        <App id="app">
            <pages>
                <Page id="page" title="OTP Login Integration in SAP UI5 using Google Firebase">
                    <content>
                        <VBox height="100%" alignItems="Center">
                            <HBox height="100%" alignItems="Center">
                                <Image height="70px" class="sapUiLargeMarginEnd"
                                    src="https://www.loc-online.co.uk/berkshire-loc/wp-content/uploads/sites/23/2020/06/Screenshot-2020-05-28-at-16.35.37-266x300.png"/>
                                <IconTabBar id="idIconTabBarNoIcons" expanded="{device>/isNoPhone}" selectedKey="mail" class="sapUiResponsiveContentPadding">
                                    <items>
                                        <IconTabFilter text="Mobile Login" key="mobile">
                                            <VBox id="idInitialDetails">
                                                <Label design="Bold" text="Enter Registered Mobile number" required="true"/>
                                                <HBox>
                                                    <ComboBox id="idcc" selectedKey="65" width="90px" class="sapUiTinyMarginEnd">
                                                        <core:Item key="65" text="+65"/>
                                                        <core:Item key="60" text="+60"/>
                                                        <core:Item key="62" text="+62"/>
                                                        <core:Item key="91" text="+91"/>
                                                    </ComboBox>
                                                    <Input width="200px" id="idMob" equired="true" type="Number" placeholder="0000000" submit="ongetOTP"/>
                                                </HBox>
                                                <HBox visible="{= ${AppConfig>/otpSent} === true ? false : true}">
                                                    <Button width="145px" class="sapUiTinyMarginEnd" text="Get OTP" press="ongetOTP"/>
                                                    <Button width="145px" text="Reset" press="onReset"/>
                                                </HBox>
                                                <Label visible="{AppConfig>/otpSent}" design="Bold" text="OTP" required="true"/>
                                                <Input visible="{AppConfig>/otpSent}" width="300px" id="idOTP" required="true" submit="onASignin"/>
                                                <HBox visible="{AppConfig>/otpSent}">
                                                    <Button width="145px" class="sapUiTinyMarginEnd" text="Sign In" press="onASignin"/>
                                                    <Button width="145px" text="Resend OTP" press="ongetOTP"/>
                                                </HBox>
                                            </VBox>
                                        </IconTabFilter>
                                    </items>
                                </IconTabBar>
                                <!--Code for Recaptcha-->
                                <core:HTML content='&lt;div id=&quot;sign-in-button&quot;&gt;&lt;/div&gt;'></core:HTML>
                            </HBox>
                        </VBox>
                    </content>
                </Page>
            </pages>
        </App>
    </Shell>
</mvc:View>

 

Login.controller.js

sap.ui.define([
    "sap/ui/core/mvc/Controller",
    "sap/m/MessageBox"
], function (Controller, MessageBox) {
    "use strict";

    return Controller.extend("firebaseApp.firebaseApp.controller.Login", {
        onInit: function () {

        },

        onAfterRendering: async function () {
            sap.ui.core.BusyIndicator.show();
            await this.onGetRecaptcha();
            sap.ui.core.BusyIndicator.hide();
        },

        onGetRecaptcha: function (oEvent) {
            var that = this;
            sap.ui.core.BusyIndicator.show();
            // Create a Fireauth Auth reference
            var oModel = this.getView().getModel("fbModel").getData();
            var fireAuth = oModel.fireAuth;
            fireAuth.useDeviceLanguage();
            var firestoreData = oModel.firestore;
            window.recaptchaVerifier = new firebase.auth.RecaptchaVerifier('sign-in-button', {
                'size': 'invisible',
                'callback': (response) => {
                    // reCAPTCHA solved, allow signInWithPhoneNumber.
                    sap.ui.core.BusyIndicator.hide();
                }
            });
        },

        ongetOTP: function () {
            sap.ui.core.BusyIndicator.show();
            var appVerifier = window.recaptchaVerifier;
            var that = this;
            var cc = this.byId("idcc")._getSelectedItemText();
            var mob = this.byId("idMob").getValue();
            mob = cc + mob;
            this.phone = mob;
            // Create a Fireauth Auth reference
            var oModel = this.getView().getModel("fbModel").getData();
            var fireAuth = oModel.fireAuth;
            fireAuth.useDeviceLanguage();
            var firestoreData = oModel.firestore;
            firebase.auth().signInWithPhoneNumber(mob, appVerifier)
                .then((confirmationResult) => {
                    sap.ui.core.BusyIndicator.hide();
                    // SMS sent. Prompt user to type the code from the message, then sign the
                    // user in with confirmationResult.confirm(code).
                    window.confirmationResult = confirmationResult;
                    that.getOwnerComponent().getModel("AppConfig").setProperty("/otpSent", true);
                }).catch((error) => {
                    sap.ui.core.BusyIndicator.hide();
                    // Error; SMS not sent
                    var errorMessage = error.message;
                    that.getOwnerComponent().getModel("AppConfig").setProperty("/otpSent", false);
                    MessageBox.error(errorMessage);
                });
        },

        onASignin: async function (oEvent) {
            sap.ui.core.BusyIndicator.show();
            var that = this;
            var otp = this.byId("idOTP").getValue();
            var errorMessage = "";
            // Create a Fireauth Auth reference
            var oModel = that.getView().getModel("fbModel").getData();
            localStorage.setItem("oModelFireAuth", JSON.stringify(oModel.fireAuth));
            var fireAuth = oModel.fireAuth;
            var firestoreData = oModel.firestore;
            var fireFunctions = oModel.fireFunctions;
            //get Token for the call
            window.confirmationResult.confirm(otp).then(async(result) => {
                await fireAuth.currentUser.getIdToken( /* forceRefresh */ true).then(async function (idToken) {
                    MessageBox.success("You are logged in via OTP!");
                    sap.ui.core.BusyIndicator.hide();
                }).catch(function (error) {
                    sap.ui.core.BusyIndicator.hide();
                    that.onReset();
                    MessageBox.error("User is not registered, kindly contact Admin.");
                    fireAuth.signOut().then(function (success) {
                        // MessageBox.error("You are logged out, refresh and try again!");
                    }).catch(function (error) {
                        MessageBox.error(error.error.Error);
                    });
                });
            }).catch((error) => {
                // User couldn't sign in (bad verification code?)
                sap.ui.core.BusyIndicator.hide();
                errorMessage = error.message;
                MessageBox.error(errorMessage);
                fireAuth.signOut().then(function (success) {
                    // jQuery.sap.storage.put(that.userID, null);
                }).catch(function (error) {});
            });
        },

        onReset: function (oEvent) {
            this.byId("idOTP").setValue("");
            this.byId("idMob").setValue("");
            this.getOwnerComponent().getModel("AppConfig").setProperty("/otpSent", false);
        }
    });
});

 

Output

OTP Login Output UI5

Author

  • Barry Allen

    A Full Stack Developer with 10+ years of experience in different domain including SAP, Blockchain, AI and Web Development.


Comments

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.