Persisting Cookies over SUSI.AI Subdomains

In this blog post, we are going to see, how the cookies are persisted for all the subdomains of SUSI.AI. By this implementation, the session for the user is maintained over all the SUSI.AI websites.

The cookies are persisted over these SUSI.AI websites –

All the web clients are developed using ReactJs framework and for the manipulation of cookies in React, a npm package – universal-cookie is used. Firstly, we will see how the cookies are set/created during login, followed by removal of cookies during logout.

Creating cookies

  • Firstly, we need to import the universal-cookie package into the component and create an instance of it.
import Cookies from 'universal-cookie';
const cookies = new Cookies();

Now, we can set a new cookie using this instance of cookies.

  • The following snippet sets the cookies after the login is done.

// AJAX call for login

let email = this.state.email.trim();
$.ajax({
  url: loginEndpoint,
  dataType: 'jsonp',
  jsonp: 'callback',
  crossDomain: true,
  success: function(response) {
  if (response.accepted) {
    cookies.set('serverUrl', BASE_URL, {
      path: '/',
      domain: '.susi.ai',
    });
    let accessToken = response.access_token;
    let state = this.state;
    let time = response.valid_seconds;
    this.handleOnSubmit(email, accessToken, time);
  }.bind(this),
  error: function(errorThrown) {
    .
    .
    .
  }.bind(this)    
});

handleOnSubmit = (email, loggedIn, showAdmin, time) => {
  let state = this.state;
  if (state.success) {
    cookies.set('loggedIn', loggedIn, {
      path: '/',
      maxAge: time,
      domain: '.susi.ai',
    });
    cookies.set('emailId', this.state.email, {
      path: '/',
      maxAge: time,
      domain: '.susi.ai',
    });
    this.props.history.push('/', { showLogin: false });
    window.location.reload();
  } else {
    this.setState({
      error: true,
      accessToken: '',
      success: false,
    });
  }
};

 

  • The cookies.set is a function provided by the package, that takes in three (3) parameters –
    • Cookie name
    • Cookie vallue
    • Options – an object containing the cookies properties
  • In the above example, say setting the loggedIn cookie, that contains the access token. We set the cookie name as loggedIn, the cookie value equal to the access token value received from the server response.
  • Apart from that, we have set 3 properties of the cookies, by passing an optional options parameter to the set function.
    • path – It indicates a URL path that must exist in the requested URL in order to send the Cookie header.
    • domainIt specifies allowed hosts to receive the cookie. If unspecified, it defaults to the host of the current document location, excluding subdomains.
    • maxAgeIt specifies a time duration after which the cookie gets expired.

Deleting cookies

  • It is mainly used, when a user wants to logout. It is used in the Logout component of the client’s codebase.
  • An approach to delete/remove a cookie is to set the expiry date of the cookie as Thu, 01 Jan 1970 00:00:01 GMT, which results in the removal of the cookie after a page refresh.
  • Following is the code snippet of how the cookies are removed to log-out a user of the website.

.
.
.
let deleteCookie = function(name, options = {}) {
  let cookieString = `${name}=;expires=Thu, 01 Jan 1970 00:00:01 GMT;`;
  if (options.domain) {
    cookieString = `${cookieString}domain=${options.domain};`;
  }
  if (options.path) {
    cookieString = `${cookieString}path=${options.path};`;
  }
  document.cookie = cookieString;
};
.
.
.
.
deleteCookie('loggedIn', { domain: '.susi.ai', path: '/' });
deleteCookie('serverUrl', { domain: '.susi.ai', path: '/' });
deleteCookie('emailId', { domain: '.susi.ai', path: '/' });
deleteCookie('showAdmin', { domain: '.susi.ai', path: '/' });
deleteCookie('username', { domain: '.susi.ai', path: '/' });

 

  • The deleteCookie function takes in 2 params –
    • Cookie name
    • options – an object containing the cookies properties
  • The options parameter needs to be passed while deleting the cookie, as it defines the scope for which the cookie has to be deleted.
  • The function creates a string and appends to it the expiry date, path, domain to the cookie name, if provided.
  • Finally, it sets the cookie by assigning the string to the document object.

Resources

Continue Reading

Recognise new SUSI users and Welcome them

SUSI web chat application is up and running now. It gives better answers for most of the questions that users ask. But for new users application does not display a welcome message or introduction about the application. It is a distraction for new users. So a new requirement arrived that is to show a welcome message for new users or give them a introduction about the application.

To give a introduction or to show a welcome message we need to identify new users. For that I used cookies.
I added a new dialog to show welcome message and introductory video. Then placed below code in the DialogSection.js file which contains codes about every dialog-box of the application.

 <Dialog
          contentStyle={{ width: '610px' }}
          title="Welcome to SUSI Web Chat"
          open={this.props.tour}
        >
          
            width="560"
            height="315"
            src="https://www.youtube.com/embed/9T3iMoAUKYA"
            gesture="media"
            allow="encrypted-media"
            >
          
          <Close style={closingStyle} onTouchTap={this.props.onRequestCloseTour()} />
        </Dialog>

We already have installed ‘universal-cookie’ npm module in our application so we can use this module to identify cookies.
I used this way to check whether user is new or not.

           <DialogSection
             {...this.props}
             openLogin={this.state.showLogin}
              .
              .
              .
              onRequestCloseTour={()=>this.handleCloseTour}
              tour={!cookies.get('visited')}

           	/>

Now it shows dialog-box for each and every user we don’t need to display the welcome message to old users so we need to store a cookie in users computer.
I stored a cookie in users computer when user clicks on the close button of the welcome dialog-box.
Below function makes new cookie in users computer.

  handleCloseTour = ()=>{
   this.setState({
     showLogin: false,
     showSignUp: false,
     showThemeChanger: false,
     openForgotPassword: false,
     tour:false
    });
    cookies.set('visited', true, { path: '/' });
 }

 

Below line sets a cookie and { path : ’/’ } makes cookie accessible on all pages.

References:

Continue Reading

Storing SUSI Settings for Anonymous Users

SUSI Web Chat is equipped with a number of settings by which it can be configured. For a user who is logged in and using the chat, he can change his settings and save them by sending it to the server. But for an anonymous user, this feature is not available while opening the chat every time, unless one stores the settings. Thus to overcome this problem we store the settings in the browser’s cookies which we do by following the steps.

The current User Settings available are :-

  1. Theme – One can change the theme to either ‘dark’ or ‘light’.
  2. To have the option to send a message on enter.
  3. Enable mic to give voice input.
  4. Enable speech output only for speech input.
  5. To have speech output always ON.
  6. To select the default language.
  7. To adjust the speech output rate.
  8. To adjust the speech output pitch.

The first step is to have a default state for all the settings which act as default settings for all users when opening the chat for the first time. We get these settings from the User preferences store available at the file UserPreferencesStore.js

let _defaults = {
                Theme: 'light',
                Server: 'http://api.susi.ai',
                StandardServer: 'http://api.susi.ai',
                EnterAsSend: true,
                MicInput: true,
                SpeechOutput: true,
               SpeechOutputAlways: false,
               SpeechRate: 1,
               SpeechPitch: 1,
           };

We assign these default settings as the default constructor state of our component so that we populate them beforehand.

2. On changing the values of the various settings we update the state through various function handlers which are as follows-

handleSelectChange – handles all the theme changes, handleEnterAsSendhandleMicInput – handles Mic Input as true, handleSpeechOutput – handles whether Speech Output should be enabled or not, handleSpeechOutputAlways – handles if user wants to listen to speech after every input, handleLanguage – handles the language settings related to speech, handleTextToSpeech – handles the Text to Speech Settings including Speech Rate, Pitch.        

  1. Once the values are changed we make use of the universal-cookie package and save the settings in the User’s browser. This is done in a function handleSubmit in the Settings.react.js file.

        

 import Cookies from 'universal-cookie';
     const cookies = new Cookies(); // Create cookie object.
     // set all values
     let vals = {
            theme: newTheme,
            server: newDefaultServer,
            enterAsSend: newEnterAsSend,
            micInput: newMicInput,
            speechOutput: newSpeechOutput,
            speechOutputAlways: newSpeechOutputAlways,
            rate: newSpeechRate,
            pitch: newSpeechPitch,
      }

    let settings = Object.assign({}, vals);
    settings.LocalStorage = true;
    // Store in cookies for anonymous user
    cookies.set('settings',settings);   
  1. Once the values are set in the browser we load the new settings every time the user opens the SUSI Web Chat by having the following checks in the file API.actions.js. We get the values from the cookies using the get function if the person is not logged in and initialise the new settings for that user.
if(cookies.get('loggedIn')===null||
    cookies.get('loggedIn')===undefined){
    // check if not logged in and get the value from the set cookie
    let settings = cookies.get('settings');
    if(settings!==undefined){
      // Check if the settings are set in the cookie
      SettingsActions.initialiseSettings(settings);
    }
  }
else{
// call the AJAX for getting Settings for loggedIn users
}

Resources

Continue Reading
Close Menu