Posts

Showing posts with the label ibm cloud

Helping Disabled Passengers Travel with Confidence

This is a reproduction of a blog post originally made on the IBM Emerging Technology blog at https://www.ibm.com/blogs/emerging-technology/helping-disabled-passengers-travel-with-confidence/ (link now dead).  Original article published on 3rd April 2019, re-publication to this blog was on 11th June 2021.

Introduction

Disabled or disadvantaged passengers have every right to fear travelling with multiple high profile cases of unfair and appalling levels of service evident in the media, particularly for rail passengers. Our team have been tackling this problem recently in collaboration with the IBM Travel and Transport team and 50% funding through Innovate UK’s call for Accelerating Innovation in Rail (round 4). The project was the brain child of Sam Hopkins and won the internal IBM Hybrid Hackathon event in 2016.

The Problem

 The rail industry in the UK is a complex one and travelling on our railways can be a difficult experience for anybody. If you’re disabled then the experience can be difficult at best and demeaning or impossible at worst. Depending on the type and severity of their disability, disabled travellers need to plan for eventualities such as whether a station is fully accessible, whether and when staff are available to help, when and where they might be able to use a toilet, how and where to board and alight the train, the list is as long as the wide range of issues people may have. Today, assistance is on offer, but this is complex due to the nature of our fragmented system and passengers (or their carers) may need to contact multiple companies 24 hours in advance of travel when planning their journey. This process of organising their journey is extremely time consuming and can be as much of a frustration as the journey itself.

The Challenges 

The UK rail industry is highly fragmented with different parts of the operation split among different companies. For example, Network Rail oversee the infrastructure such as maintaining tracks and signalling; Rolling Stock Operating Companies (ROSCOs) own the trains; and Train Operating Companies (TOCs) operate the trains and run passenger services in different regions around the UK. In order for a disabled passenger to make a journey, the Train Operating Companies are legally obliged to provide support both off the train at the station and on board the train during the journey. However, a passenger may be travelling through a large number of regions and across services provides and hence need to understand which company will be responsible for their journey at any given stage. Understanding this takes quite a bit of research and can be difficult, it also requires that everything they require on their journey lines up across the network they’re travelling on and this is certainly not guaranteed on our network today.

Our Solution

We have created a mobile application for disabled passengers, supported by an enterprise grade back end architecture. During the project we established a principle that the disabled passenger should always be connected to a member of staff. This connection provides continuous support available whenever required by the passenger and is designed to help

alleviate the anxiety felt by this group of passengers when travelling. The connection comes in the form of a chat application similar to how passengers may already use common applications such as WhatsApp or Facebook Messenger. The passenger can type anything they want to the member of staff they’re connected to and get a human-level response to their query from staff local to their situation. During their journey, the passenger is handed over between staff members such that they’re always connected with a local staff member who can offer physical assistance if required.

A typical journey story starts with the user programming their journey in a similar way to how they might on existing rail applications. They search for their departure and destination stations and select a time and route they wish to travel. Some time later, they embark upon their journey. When they arrive at the station, they either press a button to start the process or the app uses geolocation to detect their arrival at the station. They are connected to a member of the station staff who can answer questions and provide physical assistance to board their first train. Once boarded, the station staff hand the passenger over to a member of staff on board the train. This hand-over process is transparent to the user and they will simply see a new greeting from the next member of staff in the chain once they have been connected. The process continues with the on train staff handing over to station staff at the destination station in order to provide assistance alighting the train. This process can repeat as many times as necessary until the final destination is reached.

Technical Implementation 

Our solution has a strong server-side implementation with an MVP level front end to exercise the APIs provided.

We base the solution entirely within the IBM Cloud, using a Cloudant instance for database hosting, App ID for authentication services, Message Sight for highly reliable messaging built on top of the MQTT protocol, and NodeJS for writing our APIs on top of the Express framework and where necessary calling out to other APIs such as the Transport API. Security and privacy have been key concerns in the design to ensure chat messages are securely delivered only to their intended recipient. The application itself is authenticated at each of its routes and all of the server-side APIs also use the same App ID authentication. Novel to this solution is the capability of third-party authentication from Message Sight to App ID, a first-of-a-kind implementation.

The front end application is currently written in VueJS. This has been designed with accessibility in mind given the intended audience. It is a simple interface conforming to web accessibility standards that is compatible with screen readers. This component was never intended to be the final solution and we see another interface being developed in the future that is likely to build upon the current one. For example, a fully native solution or perhaps one written to be more native-like using technologies such as Native Script.

Moving Forward 

The solution is complete and ready, subject to customisation, to be adopted by the UK train operating companies. However, we do see the need for an improved user interface to be developed before the solution is truly ready to be used in the wild.

Further to the current solution for the rail industry, we recognise the issues faced by disabled travellers don’t stop with the UK rail system. Similar issues are faced when using our road network, taxi services, ferries and of course our airports. The principle established within this project of alleviating anxiety through the connection to a supporting human member of staff is likely to remain. We hope this is extended into the other areas we’re considering with the next most obvious choice to tackle being the airport use case.

VueJS Example for IBM App ID

I was recently working on a project in VueJS that needed an authorisation layer added to it.  It turns out there aren't any existing examples of how to do this anywhere, unusually not even on Stack Overflow.  So I set about writing one and thought I would share it.  My work was based upon some other useful examples and information, particularly a blog post from the IBM Cloud blog.

Before I go any further, the code samples are available and documented on GitHub as follows:

  1. IBM App ID API Server
  2. App ID VueJS Client

The code is deliberately split into two such that:
  1. the API Server is used to demonstrate how to secure an API on the server side.  This is done with the WebAppStrategy of App ID which is simply an implementation of a strategy package for passportjs.  The code here isn't anything particularly new over existing examples you can find on the web but it's necessary in order to fully demonstrate the capabilities of the client code.
  2. the VueJS Client is used to demonstrate two things:
    1. how to secure a VueJS route for which I can currently find no example implementations on the web
    2. how to call an API that has been secured by App ID by passing credentials through from the client application to the API server
The API Server should be relatively trivial to get up and running as it's a standard NodeJS API implementation using Express.  If you refer to the WebAppStrategy and the blog post I mention above then you'll see the sample code I've come up with is broadly the same i.e. an amalgamation of the two.

The VueJS Client code can be simple to get up and running as well but it's probably more important to understand how it was created such that you can apply the same principles in your own application(s).  For this then, the explanation is a little longer...

Start by running the VueJS command line client (cli) to create a bare project and for the sample to make sense you will need to add VueX and Router components using the tool:
vue create vue-client
Then understand the 3 modifications you need to make in order to have a working set of authenticated routes.

1. A store for state. 
It doesn't really matter how you achieve this in VueJS, you can use any form of local state storage.  The example code I have come up with uses VueX and a modification to the store.js code you get from the client above.  The idea of this is such that the client application can cache whether the user has already authenticated themselves.  If they have not then the client must request authentication via the server.  If they have, then all the credentials required for making an authenticated call to a server-side API are already available in the browser.  Essentially, this is a speed-up mechanism that stops the client from requesting client credentials on each API call since the session store for the authentication actually lives on the server side when using App ID.

2. A new VueJS Component
This is the component whose route is to be protected via authentication.  In the case of the example code below the standard vue cli "About" component has been used and modified slightly to include an authenticated call to the server API.  The thing to note here is that the credentials from the client side must be sent over to the server with each API call.  Using the fetch API as per the below to implement your GET request means you have to add the credentials: 'include' parameter.

<template>
  <div class="about">
    <h1>This is a protected page</h1>
    <h2>hello: {{ hello }}</h2>
  </div>
</template>

<script>
export default {
  data: function () {
    return {
      hello: undefined
    }
  },
  computed: {
    user () {
      return this.$store.state.user
    }
  },
  methods: {
    getProtectedAPI () {
      fetch('http://localhost:3000/protected/get-some-info',{
            credentials: 'include',
          }).then(res => res.text())
          .then(body => {
            console.dir(body)
            this.hello = JSON.parse(body).hello
          })
    },
  },
  created() {
    this.getProtectedAPI()
  }
} 
</script>

3. A VueJS Navigation Guard
You need to write a function that will be added as a VueJS middleware upon each route change.  The middleware is inserted automatically by the VueJS route code when using the beforeEnter call on a route.  This is known in VueJS as a Navigation Guard.

function requireAuth(to, from, next) {
  // Testing authentication state of the user
  if (!store.state.user.logged) {
    // Not sure if user is logged in yet, testing their login
    const isLoggedUrl = "http://localhost:3000/auth/logged"
    fetch(isLoggedUrl, {credentials: 'include'}).then(res => res.json()).then(isLogged => {
      if (isLogged.logged) {
        // User is already logged in, storing
        store.commit("setUser", isLogged)
        next()
      } else {
        // User is not logged in, redirecting to App ID
        window.location.href=`http://localhost:3000/auth/login?redirect=${to.fullPath}`
      }
    }).catch(e => {
      // TODO: do something sensible here so the user sees their login has failed
      console.log("Testing user login failed - D'oh!")
    })
  } else {
    // User already logged in
    next()
  }
}

The requireAuth function does the following in plain English:

  1. Using the VueJS client side cache, test if the user is already logged in
  2. If they are not. then ask the server if the user is already logged in
    1. If they are not, then redirect them to the server login page
    2. If they are, then cache the information and load the next piece of middleware
  3. If they are, then simply load the next piece of middleware


Each route you want to protect with the above function must have a beforeEnter: requireAuth parameter specified on the route.  When this is done, VueJS will call the requireAuth function before the component specified by the route is loaded.

{
  path: '/protected',
  name: 'protected',
  beforeEnter: requireAuth,
  component: Protected
}

Note: there are methods by which you don't have do call window.location.href to redirect the user to the login page (which does seem like a bit of a nasty hack.  However, these methods require the modification of the webpack configuration and so were kept out of scope of this example for the purposes of being simple.