Authenticating the sales force application

You have probably noticed by now that you did not build an authentication mechanism for the sales force application. Users need to be authenticated before they access their hand-held mobile devices for of the following reasons:

  • Changes are made to the master database at the server during synchronization. If the synchronization source was unauthorized, this may lead to data compromise or theft.
  • Unauthorized persons (for example, in the case of a stolen device) can access the data on the mobile device.

To implement authentication, you must first create the login screen. Create the following form and lay out the controls appropriately on the form.

Authenticating the sales force application

The login screen works in the following way:

  1. Upon the first-time use of this application, it will show a message requesting the user to key in a username and password. This becomes the master account.
  2. On subsequent runs, the user will be able to log in with this master account.
  3. The password for this master account will be stored in the database as a one-way encrypted string (a hash).

Performing one-way encryption using SHA256

One-way encryption, as opposed to two-way encryption, produces a value that cannot be decrypted (in the other direction) to produce the original value. It is hence useful for password verification. This is done in the following steps:

  1. The master account is created—a one-way encrypted value for the password is produced and stored in the database.
  2. Every time the user wishes to verify the authenticity of his password, the password will be encrypted using the same one-way encryption process, and will produce a hash value. This value is compared to the value in the database. If they match, access is granted. This way, you never need to know what the original password was in the first place.

To produce a one-way encrypted value or a hash value from a string of bytes, you can use SHA256, which is a commonly known hashing algorithm.

Note

SHA, short for Secure Hashing Algorithm is a set of algorithms developed by the National Security Agency (NSA) to produce a hash output (or "fingerprint") from an input message of any size. SHA256 is a variant of SHA that outputs a 256-bit sized hash.

There are other algorithms too. A few of them are listed as follows, together with their differences.

Algorithm name

Details

CRC32

Low security, fast speed

SHA1

Moderate security, medium speed

SHA256

High security, low speed

SHA384

High security, low speed

SHA512

Very high security, low speed

MD5

Moderate security, medium speed.

Take note that MD5 is already obsolete, and should no longer be used.

As we will focus on SHA256, let's see how you can write a function to encrypt a string in SHA256. Before you can use SHA256, you must first import the following namespaces:

using System.Security.Cryptography;
using System.Text;
public string SHA256Encrypt(string EncString)
{
string SHAString = null;
byte[] EncStringBytes = null;
UTF8Encoding Encoder = new UTF8Encoding();
EncStringBytes = Encoder.GetBytes(EncString);
//Create the SHA256 hash
SHA1CryptoServiceProvider SHAHasher = new SHA1CryptoServiceProvider();
EncStringBytes = SHAHasher.ComputeHash(EncStringBytes);
SHAString = BitConverter.ToString(EncStringBytes);
SHAString = SHAString.Replace("-", "");
return SHAString;
}

Create an empty form, place a button on it, and in the click event of this button write the following code:

MessageBox.Show(SHA256Encrypt("HELLO TEST"));

When you launch this form and click the button, you will see that the message has been encrypted using SHA256. Take note that whatever the length of the original message, it will always produce a hash of the same length. The great thing about SHA256 encryption is that small changes in the original text will translate to large changes in the hash value. This makes it especially sensitive to any data change.

Performing one-way encryption using SHA256

Writing the code for authentication

You will need to store the one-way encrypted password for the master account so that it can be used for future password verification. Although the password is in encrypted form, it is not a good idea to leave it around in a file on the mobile device.

The reason for this is that someone could potentially acquire this hash value, and then write a separate program to run a brute-force comparison by running words in a dictionary through the same SHA256 encryption and then comparing it with the hash value.

It is a good idea to store this password in the database. Your database has the added encryption functionality provided by both Oracle Lite and SQL Server C—this will make it a bit more difficult for unauthorized persons to retrieve the hash values.

Let's first create a new table in the database. You can do this via the Oracle mSQL tool or the QueryAnalyzer 3.5 tool.

CREATE TABLE UserLogons
(
Username NVARCHAR(20),
Password NVARCHAR(50)
)

We will just use this table to store our master account details. It will be expected to store only one single record at any point in time. You will now need to add a few more functions (for the login process) to the IDataLibPlugin interface.

public interface IDataLibPlugin
{
.
.
.
//This function will attempt to login the user by comparing
//his or her password against the hashed value in the
//database
bool Login(string Username, string Password);
//This method will check if this is the first login attempt
//after the application installation
bool IsFirstTimeLogin();
//This method will create the master login account and save
//its details to the UserLogons table
bool CreateLogin(string Username, string Password);
}

The next step would be to implement these functions, in both the Oracle Lite and SQL Server CE plugins. Let's take a look at the code for the SQL Server CE plugin (I'll leave you to do the same for the Oracle Lite plugin):

public bool Login(string Username, string Password)
{
SqlCeCommand _command;
int _recordCount;
_command = _globalConnection.CreateCommand();
//Do a compare against the hashed password stored in the
//database.
_command.CommandText = "SELECT COUNT(*) AS RecordCount FROM
UserLogons WHERE Username=@Username and
Password=@Password";
_command.Parameters.Add("@Username", Username);
_command.Parameters.Add("@Password", Password);
try
{
_recordCount = (int) (_command.ExecuteScalar());
}
catch (Exception ex)
{
_recordCount = 0;
throw (ex);
}
_command.Dispose();
_command = null;
if (_recordCount == 0)
{
return false;
}
else
{
return true;
}
}
public bool IsFirstTimeLogin()
{
SqlCeCommand _command;
int _recordCount;
_command = _globalConnection.CreateCommand();
//Checks if there is already a record in UserLogons table.
_command.CommandText = "SELECT COUNT(*) AS RecordCount FROM
UserLogons";
try
{
_recordCount = (int) (_command.ExecuteScalar());
}
catch (Exception ex)
{
_recordCount = 0;
throw (ex);
}
_command.Dispose();
_command = null;
if (_recordCount == 0)
{
return true;
}
else
{
return false;
}
}
public bool CreateLogin(string Username, string Password)
{
bool returnValue;
SqlCeCommand _command;
int _recordCount;
_command = _globalConnection.CreateCommand();
//The password is encrypted outside and passed in to this
//function
_command.CommandText = "INSERT INTO UserLogons (Username, Password) VALUES (@Username, @Password)";
_command.Parameters.Add("@Username", Username);
_command.Parameters.Add("@Password", Password);
try
{
_recordCount = _command.ExecuteNonQuery();
if (_recordCount > 0)
{
returnValue = true;
}
else
{
returnValue = false;
}
}
catch (Exception ex)
{
returnValue = false;
throw (ex);
}
_command.Dispose();
_command = null;
return returnValue;
}

Now write the code for the Login form. The highlighted code shows the code for the main logic of the login form.

public partial class Login
{
public Login()
{
InitializeComponent();
}
private bool _firstTimeLogin = false;
public void mnuExit_Click(System.Object sender,
System.EventArgs e)
{
System.Windows.Forms.Application.Exit();
}
public void mnuLogin_Click(System.Object sender, System.EventArgs e)
{
if (txtUsername.Text.Length == 0 || txtPassword.Text.Length == 0)
{
MessageBox.Show ("Please ensure you have specified
both the login username and password");
return;
}
//Encrypt the password
string _encryptedPassword;
_encryptedPassword = SHA256Encrypt(txtPassword.Text);
if (_firstTimeLogin == true)
{
GlobalArea.Application.CreateLogin(txtUsername.Text,
_encryptedPassword);
this.DialogResult = System.Windows.Forms.DialogResult.Cancel;
this.Close();
NavigationService.ShowDialog("MainMenu", null);
}
else
{
if (GlobalArea.Application.Login(txtUsername.Text,
_encryptedPassword) == false)
{
txtUsername.Text = "";
txtPassword.Text = "";
MessageBox.Show("The username and password
combination is not correct");
}
else
{
this.DialogResult =
System.Windows.Forms.DialogResult.Cancel;
this.Close();
NavigationService.ShowDialog("MainMenu", null);
}
}
}
public string SHA256Encrypt(string EncString)
{
string SHAString = null;
byte[] EncStringBytes = null;
UTF8Encoding Encoder = new UTF8Encoding();
EncStringBytes = Encoder.GetBytes(EncString);
SHA1CryptoServiceProvider SHAHasher = new
SHA1CryptoServiceProvider();
EncStringBytes = SHAHasher.ComputeHash(EncStringBytes);
SHAString = BitConverter.ToString(EncStringBytes);
SHAString = SHAString.Replace("-", "");
return SHAString;
}
public void Login_Load(object sender, System.EventArgs e)
{
//Only display the first-time login message if it is a
//first time login
if (GlobalArea.Application.IsFirstTimeLogin() == true)
{
_firstTimeLogin = true;
}
else
{
_firstTimeLogin = false;
}
lblFirstTimeMsg.Visible = _firstTimeLogin;
}
}

Loading the login form

Instead of going straight to the menu, you must now load the login form as the first form of your application. You can easily do that by first adding a new navigation target in the SalesForceApp.NavigationService class (highlighted as follows).

public static DialogResult ShowDialog(string DialogName, object Arg1)
{
DialogResult _dialogResult = 0;
switch (DialogName)
{
case "SetupDatasources":
PluginsSetup _PluginsSetup = new PluginsSetup();
_dialogResult = _PluginsSetup.ShowDialog();
_PluginsSetup.Close();
_PluginsSetup.Dispose();
_PluginsSetup = null;
break;
case "Login":
Login _login = new Login();
_dialogResult = _login.ShowDialog();
_login.Close();
_login.Dispose();
_login = null;
break;
case "MainMenu":
MainMenu _MainMenu = new MainMenu();
_dialogResult = _MainMenu.ShowDialog();
_MainMenu.Close();
_MainMenu.Dispose();
_MainMenu = null;
break;
.
.
.
}
}

As the last step, you will now need to modify the Main() method in the SalesForceApp.Application class. This will enable the application to launch the Login form first whenever you start the application.

public class Application
{
public static void Main()
{
InitializeApp();
NavigationService.ShowDialog("Login", null);
DeInitializeApp();
}
.
.
.
}

That's all there is to it! Now you can try your Login form by running the SalesForceApp project. The first time, it will prompt you for your password. You can see the record for the master account generated in the UserLogons table if you use the Query Analyzer 3.5 tool to run a query off the SQL Server CE database. On all subsequent runs, you will be required to key in that same username and password to log on.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.238.20