Monday, January 13, 2020

Xamarin.Forms - Build Auth App With Node.Js And MongoDb

Introduction

Nowadays we are spotting Node.Js everywhere in the software industry. The demand for Node.Js developers is increasing day by day. Node.Js is the most popular JavaScript framework and an open source server environment that allows you to run JavaScript on the server.
 
In this article, we will build a Xamarin.Forms authentication app with the help of Node JS with Mongo DB. We will develop our backend API in Node.JS with No SQL database and then consume this REST'ful API in our client app Xamarin.Forms. In this post, I will teach you how to build this app exactly with all frontend and backend-coding. So, let's get started.
 
Prerequisites
 
You are required to have basic knowledge of Node JS and intermediate level knowledge of Xamarin.Forms and a basic idea of NoSQL databases like Mongodb.
 
In the initial stage, you must have installed mongodb and Node on your local PC. I am skipping the installation process of Node and Mongodb.
 

Backend API (Server Side Application)

 
Step 1 - Create Database
 
In this step, we will create a new database in Mongodb for storing user information. Open your Mongodb folder and copy the path. Go to -> C: drive and open your program files and search MongoDB and open this folder inside this open server folder and then go to the bin folder.
 
C:\Program Files\MongoDB\Server\4.2\bin
 
Xamarin.Android - Working With Node.js And MongoDB
 
Open your command prompt as administrator and hit the follwing commands.
  • enter -> cd /d C:\Program Files\MongoDB\Server\4.2\bin
  • enter -> mongo
  • enter -> use DatabaseName //Write database name in place of DatabaseName whatever you want.
  • enter -> db.createCollection('user') //user is Collection Name (Like In SQL Table)
Xamarin.Android - Working With Node.js And MongoDB
 
Step 2 - Create Node Project
 
Create a new folder with your project name and copy the path of your project. Hit the npm init command for creating your node project.
 
Xamarin.Android - Working With Node.js And MongoDB
 
After creating your node project add the follwing npm packages to your node project.
  1. npm install mongodb //For mongodb connection
  2. npm install crypto //To encrypt user's password
  3. npm install express //To create RRSTFul API
  4. npm install body-parser //For parsing the user form
Open your project folder, add a new js file with name index.js and the following code.
  1. //Import Packages  
  2. var mongodb = require('mongodb');  
  3. var ObjectID = mongodb.ObjectID;  
  4. var crypto = require('crypto');  
  5. var express = require('express');  
  6. var bodyParser = require('body-parser');  
  7. //Password Utils  
  8. //Create Function to Random Salt  
  9. var generateRandomString = function(length) {  
  10.     return crypto.randomBytes(Math.ceil(length / 2)).toString('hex'/* Convert to hexa formate */ .slice(0, length);  
  11. };  
  12. var sha512 = function(password, salt) {  
  13.     var hash = crypto.createHmac('sha512', salt);  
  14.     hash.update(password);  
  15.     var value = hash.digest('hex');  
  16.     return {  
  17.         salt: salt,  
  18.         passwordHash: value  
  19.     }  
  20. };  
  21.   
  22. function saltHashPassword(userPassword) {  
  23.     var salt = generateRandomString(16);  
  24.     var passwordData = sha512(userPassword, salt);  
  25.     return passwordData;  
  26. }  
  27.   
  28. function checkHashPassword(userPassword, salt) {  
  29.     var passwordData = sha512(userPassword, salt);  
  30.     return passwordData;  
  31. }  
  32. //Create Express Service  
  33. var app = express();  
  34. app.use(bodyParser.json());  
  35. app.use(bodyParser.urlencoded({  
  36.     extended: true  
  37. }));  
  38. //Create MongoDB Client  
  39. var MongoClient = mongodb.MongoClient;  
  40. //Connection URL  
  41. var url = 'mongodb://localhost:27017' //27017 is default port  
  42. MongoClient.connect(url, {  
  43.     useNewUrlParser: true,  
  44.     useUnifiedTopology: true  
  45. }, function(err, client) {  
  46.     if (err) {  
  47.         console.log('Unable to connect to MongoDB server.Error', err);  
  48.     } else {  
  49.         //Start Web Server  
  50.         app.listen(3000, () => {  
  51.             console.log('Connected to MongoDb server, Webservice running on on port 3000');  
  52.         });  
  53.     }  
  54.     //Register  
  55.     app.post('/register', (request, response, next) => {  
  56.         var post_data = request.body;  
  57.         var plain_password = post_data.password;  
  58.         var hash_data = saltHashPassword(plain_password);  
  59.         var password = hash_data.passwordHash;  
  60.         var salt = hash_data.salt;  
  61.         var firstname = post_data.firstname;  
  62.         var lastname = post_data.lastname;  
  63.         var mobile = post_data.mobile;  
  64.         var email = post_data.email;  
  65.         var insertJson = {  
  66.             'firstname': firstname,  
  67.             'lastname': lastname,  
  68.             'email': email,  
  69.             'mobile': mobile,  
  70.             'password': password,  
  71.             'salt': salt  
  72.         };  
  73.         var db = client.db('ahsannodejs');  
  74.         //Check Already Exist Email  
  75.         db.collection('user').find({  
  76.             'email': email  
  77.         }).count(function(err, number) {  
  78.             if (number != 0) {  
  79.                 console.log('User Email already exist!');  
  80.                 response.json('User Email already exist!');  
  81.             } else {  
  82.                 //Insert data  
  83.                 db.collection('user').insertOne(insertJson, function(err, res) {  
  84.                     console.log('User Registration Successful..');  
  85.                     response.json('User Registration Successful..');  
  86.                 });  
  87.             }  
  88.         });  
  89.     });  
  90.     //Login  
  91.     app.post('/login', (request, response, next) => {  
  92.         var post_data = request.body;  
  93.         var email = post_data.email;  
  94.         var userPassword = post_data.password;  
  95.         var db = client.db('ahsannodejs');  
  96.         //Check Already Exist Email  
  97.         db.collection('user').find({  
  98.             'email': email  
  99.         }).count(function(err, number) {  
  100.             if (number == 0) {  
  101.                 console.log('User Email not exist!');  
  102.                 response.json('User Email not exist!');  
  103.             } else {  
  104.                 //Insert data  
  105.                 db.collection('user').findOne({  
  106.                     'email': email  
  107.                 }, function(err, user) {  
  108.                     var salt = user.salt;  
  109.                     var hashed_password = checkHashPassword(userPassword, salt).passwordHash; //Hash Password with Salt  
  110.                     var encrypted_password = user.password; //Get Password from user  
  111.                     if (hashed_password == encrypted_password) {  
  112.                         console.log('User Login Successful..');  
  113.                         response.json('User Login Successful..');  
  114.                     } else {  
  115.                         console.log('Login Failed Wrong Password..');  
  116.                         response.json('Login Failed Wrong Password..');  
  117.                     }  
  118.                 });  
  119.             }  
  120.         });  
  121.     });  
  122. });  
Step 3 - Build and Run
 
Copy your project path and run your command prompt as administrator and hit node index.js to Run your server.
 

Client Application

 
Step 1 - Create a Mobile App (Xamarin.Forms) Project
 
Open Visual Studio-> New Project-> Templates-> Mobile App-> Xamarin.Forms-> Blank app and give the project name AuthNodeJsMongoXamarin.
 
(ProjectName: AuthNodeJsMongoXamarin)
 
Step 2 - Add NuGet Package
 
After creating a blank project, first, add Refit NuGet package to this project by right-clicking on References and select manage NuGet packages.
 
Step 3 - Create Login Page
 
Next, open Solution Explorer-> Project Name-> MainPage.xaml. Open MainPage.xaml file and add the following code.
 
(FileName: MainPage.xaml)
  1. <?xml version="1.0" encoding="utf-8" ?>    
  2. <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"    
  3.              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"    
  4.              xmlns:d="http://xamarin.com/schemas/2014/forms/design"    
  5.              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"    
  6.              mc:Ignorable="d"    
  7.              x:Class="AuthNodeJsMongoXamarin.MainPage">    
  8.         
  9.     <StackLayout HorizontalOptions="Center" VerticalOptions="Start">    
  10.             <Image x:Name="imgBanner" Source="NodeJs.jpg" ></Image>    
  11.             <Label Margin="0,0,0,10" Text="Authentication with Mongo Using Node.Js" FontAttributes="Bold" FontSize="Large" TextColor="Gray" HorizontalTextAlignment="Center" ></Label>    
  12.         <StackLayout Padding="10,10,10,10">    
  13.             <Entry x:Name="txtEmail" Placeholder="Enter Email"></Entry>    
  14.             <Entry x:Name="txtPassword" Placeholder="Enter Password" IsPassword="True"></Entry>    
  15.             <Label FontSize="Caption" Text="If you don't have credentials to SignIn? Please click on Registeration button."/>    
  16.         </StackLayout>        
  17.     
  18.             <StackLayout  HorizontalOptions="CenterAndExpand" Orientation="Horizontal">    
  19.                 <Button BackgroundColor="Beige" x:Name="btnSignIn" WidthRequest="200" Text="SignIn" Clicked="btnSignIn_Clicked" />    
  20.                 <Button BackgroundColor="LightSeaGreen" x:Name="btnRegister" WidthRequest="200" Text="Registeration" Clicked="btnRegister_Clicked" />    
  21.             </StackLayout>    
  22.         <Label HorizontalTextAlignment="Center" Margin="0,0,0,10" x:Name="txtSignInResult" TextColor="Black" FontSize="Large"/>    
  23.     </StackLayout>    
  24.     
  25. </ContentPage>     
Step 3 - Create Registration Page
 
Add a new ContentPage by going to Solution Explorer-> Project Name. Right click to add a new item, select ContentPage, and give it the name RegisterPage.xaml
 
Open this layout file and add the following code.
  1. <?xml version="1.0" encoding="utf-8" ?>    
  2. <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"    
  3.              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"    
  4.              xmlns:d="http://xamarin.com/schemas/2014/forms/design"    
  5.              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"    
  6.              mc:Ignorable="d"    
  7.              x:Class="AuthNodeJsMongoXamarin.RegisterPage">    
  8.     <ContentPage.Content>    
  9.         <StackLayout HorizontalOptions="Center" VerticalOptions="Start">    
  10.             <Label Margin="0,0,0,10" Text="User Register" FontAttributes="Bold" FontSize="Large" TextColor="Gray" HorizontalTextAlignment="Center" ></Label>    
  11.             <StackLayout Padding="10,10,10,10">    
  12.                 <Entry x:Name="txtFirstName" Placeholder="Enter First Name"></Entry>    
  13.                 <Entry x:Name="txtLastName" Placeholder="Enter Last Name"></Entry>    
  14.                 <Entry x:Name="txtMobile" Placeholder="Enter Mobile"></Entry>    
  15.                 <Entry x:Name="txtEmail" Placeholder="Enter Email"></Entry>    
  16.                 <Entry x:Name="txtPassword" Placeholder="Enter Password" IsPassword="True"></Entry>    
  17.             </StackLayout>    
  18.             <StackLayout  HorizontalOptions="CenterAndExpand" Orientation="Horizontal">    
  19.                 <Button x:Name="btnRegisteration" BackgroundColor="LightSeaGreen" WidthRequest="200" Text="Register" Clicked="btnRegisteration_Clicked" />    
  20.                 <Button x:Name="btnCancel" BackgroundColor="PaleVioletRed" WidthRequest="200" Text="Cancel" Clicked="btnCancel_Clicked" />    
  21.             </StackLayout>    
  22.             <Label HorizontalTextAlignment="Center" Margin="0,0,0,10" x:Name="txtRegisterResult" TextColor="Black" FontSize="Large"/>    
  23.         </StackLayout>    
  24.     </ContentPage.Content>    
  25. </ContentPage>     
Step 4 - Create Dashboard Page
 
Similarly add a new layout by going to Solution Explorer-> Project Name. Right click to add a new item, select ContentPage, and give it the name DashboardPage.xaml. Open DashboardPage.xaml Page and add the following code.
  1. <?xml version="1.0" encoding="utf-8" ?>    
  2. <ContentPage xmlns="http://xamarin.com/schemas/2014/forms"    
  3.              xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"    
  4.              xmlns:d="http://xamarin.com/schemas/2014/forms/design"    
  5.              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"    
  6.              mc:Ignorable="d"    
  7.              x:Class="AuthNodeJsMongoXamarin.Views.DashboardPage">    
  8.     <ContentPage.Content>    
  9.         <StackLayout>    
  10.             <Label Text="Welcome to Dashboad!"    
  11.                 VerticalOptions="CenterAndExpand"     
  12.                 HorizontalOptions="CenterAndExpand" />    
  13.             <Button Text="Back To Home" Clicked="BackButton_Clicked" x:Name="BackButton"/>    
  14.         </StackLayout>    
  15.     </ContentPage.Content>    
  16. </ContentPage>     
Step 5 - Create User Model Class
 
Add a new class to your project with the name User.cs. Add the following properties to getter and setter with an appropriate namespace.
  1. public class User  
  2. {  
  3.     public string FirstName { getset; }  
  4.     public string LastName { getset; }  
  5.     public string Mobile { getset; }  
  6.     public string Email { getset; }  
  7.     public string Password { getset; }  
  8. }  
Step 6 - Register Class
 
Open Solution Explorer-> Project Name-> Open-> RegisterPage.xaml.cs and add the following code, using the appropriate namespaces.
 
(FileName: RegisterPage.xaml.cs)
  1. using AuthNodeJsMongoXamarin.API;  
  2. using AuthNodeJsMongoXamarin.Model;  
  3. using Refit;  
  4. using System;  
  5. using System.Collections.Generic;  
  6. using Xamarin.Forms;  
  7. using Xamarin.Forms.Xaml;  
  8.   
  9. namespace AuthNodeJsMongoXamarin  
  10. {  
  11.     [XamlCompilation(XamlCompilationOptions.Compile)]  
  12.     public partial class RegisterPage : ContentPage  
  13.     {  
  14.         public RegisterPage()  
  15.         {  
  16.             InitializeComponent();  
  17.         }  
  18.   
  19.         private async void btnCancel_Clicked(object sender, EventArgs e)  
  20.         {  
  21.             await Navigation.PushAsync(new MainPage());  
  22.         }  
  23.   
  24.         private async void btnRegisteration_Clicked(object sender, EventArgs e)  
  25.         {  
  26.             if (string.IsNullOrEmpty(txtFirstName.Text))  
  27.             {  
  28.                 txtRegisterResult.Text = "First Name can not be empty or null!";  
  29.             }  
  30.             else if (string.IsNullOrEmpty(txtLastName.Text))  
  31.             {  
  32.                 txtRegisterResult.Text = "Last Name can not be empty or null!";  
  33.             }  
  34.             else if (string.IsNullOrEmpty(txtMobile.Text))  
  35.             {  
  36.                 txtRegisterResult.Text = "Mobile can not be empty or null!";  
  37.             }  
  38.             else if (string.IsNullOrEmpty(txtEmail.Text))  
  39.             {  
  40.                 txtRegisterResult.Text = "Email can not be empty or null!";  
  41.             }  
  42.             else if (string.IsNullOrEmpty(txtPassword.Text))  
  43.             {  
  44.                 txtRegisterResult.Text = "Password can not be empty or null!";  
  45.             }  
  46.             else  
  47.             {  
  48.                 var authAPI = RestService.For<IAuthAPI>("http://10.0.2.2:3000");  
  49.                 User user = new User  
  50.                 {  
  51.                     Email = txtEmail.Text.ToString(),  
  52.                     FirstName = txtFirstName.Text.ToString(),  
  53.                     LastName = txtLastName.Text.ToString(),  
  54.                     Mobile = txtMobile.Text.ToString(),  
  55.                     Password = txtPassword.Text.ToString()  
  56.                 };  
  57.                 Dictionary<stringstring> data = new Dictionary<stringstring>();  
  58.                 data.Add("firstname", user.FirstName);  
  59.                 data.Add("lastname", user.LastName);  
  60.                 data.Add("email", user.Email);  
  61.                 data.Add("mobile", user.Mobile);  
  62.                 data.Add("password", user.Password);  
  63.                 var result = await authAPI.Register(data);  
  64.                 txtRegisterResult.Text = result.ToString();  
  65.                 if (result.Contains("Registeration Successful"))  
  66.                 {  
  67.                     await Navigation.PushAsync(new MainPage());  
  68.                 }  
  69.             }  
  70.         }  
  71.     }  
  72. }  
Step 7 - Dashboard Class
 
Open Solution Explorer-> Project Name-> Open-> DashboardPage.xaml.cs and add the following code, using the appropriate namespaces.
 
(FileName: DashboardPage.xaml.cs)
  1. using System;  
  2. using Xamarin.Forms;  
  3. using Xamarin.Forms.Xaml;  
  4.   
  5. namespace AuthNodeJsMongoXamarin.Views  
  6. {  
  7.     [XamlCompilation(XamlCompilationOptions.Compile)]  
  8.     public partial class DashboardPage : ContentPage  
  9.     {  
  10.         public DashboardPage()  
  11.         {  
  12.             InitializeComponent();  
  13.         }  
  14.   
  15.         private async void BackButton_Clicked(object sender, EventArgs e)  
  16.         {  
  17.             await Navigation.PushAsync(new MainPage());  
  18.         }  
  19.     }  
  20. }  
Step 8 - Add API Interface
 
Before you go further, you need to write your IAPI class with all the getter and setter methods. For this, go to Solution Explorer-> Project Name and right-click. Select Add -> New Item-> Class. Give it a name like IAPI.cs and write the following code.
 
(File Name: IAPI.cs)
  1. using Refit;  
  2. using System.Collections.Generic;  
  3. using System.Threading.Tasks;  
  4.   
  5. namespace AuthNodeJsMongoXamarin.API  
  6. {  
  7.     public interface IAuthAPI  
  8.     {  
  9.         [Post("/login")]  
  10.         Task<string> SignIn([Body(BodySerializationMethod.UrlEncoded)] Dictionary<stringstring> data);  
  11.   
  12.         [Post("/register")]  
  13.         Task<string> Register([Body(BodySerializationMethod.UrlEncoded)] Dictionary<stringstring> data);  
  14.     }  
  15. }  
Step 9 - MainPage Class
 
Open Solution Explorer-> Project Name-> Open-> MainPage.xaml.cs and add the following code, using the appropriate namespaces.
 
(FileName: MainPage.xaml.cs)
  1. using AuthNodeJsMongoXamarin.API;  
  2. using AuthNodeJsMongoXamarin.Model;  
  3. using AuthNodeJsMongoXamarin.Views;  
  4. using Refit;  
  5. using System;  
  6. using System.Collections.Generic;  
  7. using System.ComponentModel;  
  8. using Xamarin.Forms;  
  9.   
  10. namespace AuthNodeJsMongoXamarin  
  11. {  
  12.     [DesignTimeVisible(false)]  
  13.     public partial class MainPage : ContentPage  
  14.     {  
  15.         public MainPage()  
  16.         {  
  17.             InitializeComponent();  
  18.         }  
  19.   
  20.         private async void btnRegister_Clicked(object sender, EventArgs e)  
  21.         {  
  22.             await Navigation.PushAsync(new RegisterPage());  
  23.         }  
  24.   
  25.         private async void btnSignIn_Clicked(object sender, EventArgs e)  
  26.         {  
  27.             if (string.IsNullOrEmpty(txtEmail.Text))  
  28.             {  
  29.                 txtSignInResult.Text = "Email can not be empty or null!";  
  30.             }else if (string.IsNullOrEmpty(txtPassword.Text))  
  31.             {  
  32.                 txtSignInResult.Text = "Password can not be empty or null!";  
  33.             }  
  34.             else  
  35.             {  
  36.                 var authAPI = RestService.For<IAuthAPI>("http://10.0.2.2:3000");  
  37.                 User user = new User  
  38.                 {  
  39.                     Email = txtEmail.Text.ToString(),  
  40.                     Password = txtPassword.Text.ToString()  
  41.                 };  
  42.   
  43.                 Dictionary<stringstring> data = new Dictionary<stringstring>();  
  44.                 data.Add("email", user.Email);  
  45.                 data.Add("password", user.Password);  
  46.                 var result = await authAPI.SignIn(data);  
  47.   
  48.                 txtSignInResult.Text = result.ToString();  
  49.                 if (result.Contains("Login Successful"))  
  50.                 {  
  51.                     await Navigation.PushAsync(new DashboardPage());  
  52.                 }  
  53.             }  
  54.         }  
  55.     }  
  56. }  
Step 10 - MainPage Class
 
Open Solution Explorer-> Project Name-> Open-> App.xaml.cs and add the following code, using the appropriate namespaces.
 
(FileName: App.xaml.cs)
  1. using Xamarin.Forms;  
  2.   
  3. namespace AuthNodeJsMongoXamarin  
  4. {  
  5.     public partial class App : Application  
  6.     {  
  7.         public App()  
  8.         {  
  9.             InitializeComponent();  
  10.             MainPage = new NavigationPage(new MainPage());  
  11.         }  
  12.     }  
  13. }  
Step 11 - Permissions From Device
 
We need permission from the device because we can use the device’s INTERNET. Please add internet permission to your AndroidManifest.xml. Let's open Solution Explorer-> Properties-> AndroidManifest and let's add the code inside application tags.
  1. <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />  
  2. <uses-permission android:name="android.permission.INTERNET" />   
User Already Exists Testing
 
 
User Registration Testing
 
 
User Login Testing
 

Ahsan Siddique

Author & Editor

Experienced Microsoft Certified Azure Developer and Trainer with a demonstrated history of working in the computer software industry. Skilled in .NET, .NET Core, C#, Xamarin, Azure, Kubernetes, Docker Containers, Microservices, CI/CD, and Universal Windows Platform with Strong engineering professional.

1 Comments: