Remote data persistence using cookies (C#demo)

The use of cookies on login

Extend a web-enabled app's login with remote data persistence using cookies

In a previous post, we explained how to add remote data persistence to your apps by saving cookies in the browser. In this opportunity, we will take advantage of this feature to develop a small but useful demo that shows how to provide an extended sign-on for web users.

Thinfinity VirtualUI web-enabled apps were born as desktop apps and most include their own login mechanism. In this opportunity, we will show you how to extend your own existing application’s sign-on process, getting the browser to identify the application’s user. In this way, users would only need to manually log in when accessing the application for the first time, after logging out or when the login ID has expired.

Let’s do it

The present demo assumes this scenario:

  • The application is accessed both from the web through a VirtualUI Server and from the Windows desktop.
  • Users access the web-enabled application without authenticating against VirtualUI.
  • The user identification (user authentication) is performed in the application by using a login form and any local validation (accessing a database, a file, an external service, etc.; in our demo users are stored in a collection).

In the following C# example (find the code here):

  • On the first user access, we will show the application’s login form to get the end-user credentials, saving an identification token in the browser when the user authentication was successful.
  • Subsequently, if the token exists and is not expired, we will use it to identify the current user, bypassing the application’s login form.
  • Additionally, we will add a logout option to remotely delete the token in order to force a login for the next connection.
  • When the application is run from the Windows desktop directly, this authentication scheme is disabled and the original login process is used.

The demo application is composed of two forms and two auxiliary classes to resolve the end-user authentication:

  • The main application form.
  • The login form.
  • The UserValidator class, which provides the user validation.
  • The secondary User class, which keeps each user in a collection.

The Thinfinity VirtualUI library is added to web-enable the application.

The class diagram shows these elements, their public attributes, and methods:

Remote data persistence using cookies

Are You Using the Application from the Web?

When you start a web-enabled application, VirtualUI checks whether you are accessing it locally from the Windows desktop or from the Web. To know when the user is accessing from the web, check the VirtualUI.Active attribute value.
MainForm creates an instance of the VirtualUI class and attempts to connect to a VirtualUI Server; when it succeeds, the VirtualUI class instance is set to Active. As this is valid only when you run the application from the browser if the “VirtualUI. Active” attribute is true, the application tries to read a cookie from the browser.

Cookies are small pieces of text sent from a website (in this case our application, using VirtualUI methods) and stored in the user’s web browser. Once stored, cookies can be read or deleted, and if we want to, they can have an expiration date.
We will use a cookie to store a user identification value, but for security reasons, this value cannot be the username or the password. We will create a token for each successful login. This token is a unique ID, a long text value that will be saved along with the user credentials on the application side (e.g. in a database) and stored in the browser.

The application tries to recover the token to perform a user validation using the UserValidator class. If the token is valid, UserValidator will return the identified username, and then we will bypass the login process.

using System;
using System.Windows.Forms;
using Cybele.Thinfinity;
namespace LoginDemo
{
    public partial class MainForm : Form
    {
        const string COOKIE_NAME = "MYAPP_accesskey";
        UserValidator _uservalidator = null;
        VirtualUI _virtualUI = null;
        LoginForm loginform = null;
        string _username = "";
        public MainForm()
        {
            InitializeComponent();
            _uservalidator = new UserValidator();
            _virtualUI = new VirtualUI();
            _virtualUI.Start();
        }
        private void MainForm_Load(object sender, EventArgs e)
        {
            // If you are accessing from the Windows desktop
            // or the browser authentication id doesn't exist
            // or the browser authentication id is invalid
            if (!_virtualUI.Active || !ValidateUser(_virtualUI.BrowserInfo.GetCookie(COOKIE_NAME)))
            {
                // shows the login form
                loginform = new LoginForm();
                loginform.authenticationCallback = new AuthenticationHandler(ValidateUser);
                loginform.ShowDialog(this);
                // if the login dialog returns "" then the user cannot be identified
                if (_username.Equals(""))
                {
                    this.Close();
                }
                else
                {
                    // enabled only when accessed from the web
                    logOutToolStripMenuItem.Enabled = _virtualUI.Active;
                }
            }
        }
...
...
...

 

Saving and Deleting the Token

Storing the token in the user’s web browser is easy. The MainForm.UpdateUserToken method performs the token storage depending on the value parameter. If the value is empty, that means we want to delete an existing token. But if the value contains an existing username, it calls the UserValidator to obtain a new user token and defines the expiration date.
The cookie expiration date is set by using the expires=date format, where this date is expressed in Greenwich Mean Time (GMT) format. If the expiration date is not set or if the format is wrong, the cookie expires when the web session ends. Otherwise, the cookie is persisted in the browser cache until the expiration date. To set the expiration date in GMT format (“DAY, DD-MMM-YYYY HH:MM:SS GMT”), add the “R” parameter in the date creation:

    token = _uservalidator.CreateUserToken(value);
    expirationDate = DateTime.UtcNow.AddDays(7).ToString("R");

If the expiration date is previous to the current time, the cookie will be deleted. To delete the token from the browser, we will set the expiration date to a past date:

    expirationDate = DateTime.UtcNow.AddDays(-1).ToString("R");

Finally, we perform the token storage by using the VirtualUI.BrowserInfo.SetCookie method:

    _virtualUI.BrowserInfo.SetCookie(COOKIE_NAME, token, expirationDate);

This is the complete MainForm.UpdateUserToken code:

// in MainForm class:
        public void UpdateUserToken(string username)
        {
            string token = "";
            string expirationDate;
            if (!username.Equals(""))
            { // creates a cookie that expires after a week
                token = _uservalidator.CreateUserToken(username);
                expirationDate = DateTime.UtcNow.AddDays(7).ToString("R");
            }
            else
            { // forces the browser to delete the cookie
                expirationDate = DateTime.UtcNow.AddDays(-1).ToString("R"); // expired
            }
            _virtualUI.BrowserInfo.SetCookie(COOKIE_NAME, token, expirationDate);
        }

And here you can see how to create the token:

// in UserValidator class:
public string CreateUserToken(string user) {
    string tkn = "";
    ...
    ...
    tkn = System.Guid.NewGuid().ToString();
    ...
    ...
    return tkn;
}

 

Two ways to exit

When opening the File application menu, you will find two options: “Log out” and “Exit Program”.
Why? Because only the “Log out” option will delete the token from the browser. When you choose “Exit program”, the browser will remember the user until the cookie expires. The code explains it better than words:

private void exitToolStripMenuItem_Click(object sender, EventArgs e)
{
    Application.Exit();
}
private void logOutToolStripMenuItem_Click(object sender, EventArgs e)
{
    RemoveUserToken();
    Application.Exit();
}

 

Voilà!

By adding a few lines of code, we adapted our web-enabled application login process to work with the browser in an integrated way, while keeping the previous desktop login functionality. We hope this demo can be useful for you.
There are other ways to resolve the end-user authentication with Thinfinity VirtualUI; it allows developers to integrate OAuth/2, RADIUS, Windows Logon and Custom Authentication, helping them to build single sign-on (SSO) mechanisms.
In an upcoming post, we will show you how to implement a remote login by using SSO and external authentication methods.

Leave a comment

Privacy Preferences
This website uses cookies to improve your experience while you navigate through the website. Out of these, the cookies that are categorized as necessary are stored on your browser as they are essential for the working of basic functionalities of the website. We also use third-party cookies that help us analyze and understand how you use this website. These cookies will be stored in your browser only with your consent. You also have the option to opt-out of these cookies. But opting out of some of these cookies may affect your browsing experience.