nodejs


Table of Contents:

Prerequisites
Node SDK Installation
Run the node Demo App
Creating your own app


Prerequisites


Creating an app involves two basic steps:

  1. Register/create an app in the portal and obtain credentials (this is detailed in the 'Register / Create a New App' menu section)
  2. Configure your app using an SDK, making use of these credentials

It is recommended that you first create a demo/test app with a redirect uri of http://127.0.0.1:5000/login in the portal, to enable you to run the SDK demo app and test the SDK functionality.

In the portal, when you create a new app, you will be issued with the Client ID and Client Secret credentials that you need to specify when building your app with the SDK. Note that your Client Secret will only be issued to you once so it must be grabbed when first displayed:

client secret

Client ID can then be copied at any time from the app settings screen:

app settings page

Note that you can control the Login Methods available (QR Code requires customer usage of the mobile app. While Browser Login enables logging in within the desktop browser, without the mobile app)

When creating your app in the portal, you also must specify a redirect_uri endpoint which comes from the url where you are hosting your app:

add app

The SDK will automatically create the redirect uri by appending '/login' to your url. You, of course, are in charge of what the base url of your app is. So it could be http://testapp.com/login, http://12.34.567.89:8080/login or http://127.0.0.1:5000/login as above. Note, however, that the MFA server will not accept 'localhost' as a base url.


Node SDK Installation


  1. Dependencies which need to be installed are nodejs and npm (Node Package Manager):
    sudo apt-get install nodejs nodejs-dev npm
    It may also be necessary to install:
    sudo apt-get install nodejs-legacy
    The following are not strict dependencies but may help prevent any node error messages:
    npm install pug
    npm install minimatch
    npm install to-iso-string

  2. Grab the SDK:

    First of all, create a new folder for the SDK repo. Then cd to the new folder and download or clone the repo from:

    https://github.com/miracl/maas-sdk-nodejs

    Now get ready to do some folder re-arranging!

    To enable use of the sample app, you must move the samples sub-folder to the same level as the root folder. So, from within your top level folder (making sure you include the '.' at the end of this command):

    mv maas-sdk-nodejs/samples/ .

    You should now see that both folders appear in the top level folder:

    /maas-sdk-nodejs
    /samples

    Next step is:

    cd samples

    Now open the sample.json file and configure it with your client id, client secret and redirect_uri values, as set up in the Create a New App menu section:

For security, the client ID and secret for a genuine app should not be stored in clear text in a config file. This has only been done here for simple demo purposes. For a production scenario, the client ID and secret should be programmatically accessed via an encrypted API

  {
    "client_id": "CLIENT_ID",
    "secret": "SECRET",
    "redirect_uri": "REDIRECT_URI"
  }

Substitute CLIENT_ID, CLIENT_SECRET with your correct values.

Note the fact that app.js contains the line app.listen(5000) means that the sample app will be listening on http://127.0.0.1:5000 and that the redirect_uri value of http://127.0.0.1:5000/login will function correctly. If you wish to change this, just edit theapp.listen(5000), but remember it must match what has been entered in your app details screen in the portal.

Open the views/index.ejs file and, towards the end of the file, make sure the mpad script has the correct url in order to communicate with the authentication server (note that it begins with 'mcl.cdn.mpin.io'):

  <script src="https://mcl.cdn.mpin.io/mpad/mpad.js" data-authurl="<%=auth_url%>" data-element="btmpin"></script>

Now, to install the sample app dependencies, still within the samples folder:

npm install

Then to install the SDK, go to the 'maas-sdk-nodejs' folder:
cd ../maas-sdk-nodejs/
Followed by:
npm install

Now return to the top level folder and move the entire “maas-sdk-nodejs” to “samples/node_modules”:
cd ..
Followed by:
mv maas-sdk-nodejs/ samples/node_modules

So within your top-level folder, you should now only have one 'samples' sub-folder.

You are now, finally, ready to get to work!


Run the Node demo app


Running the pre-configured demo app will help you make sure that you have all your settings correct and so will be able to proceed with confidence toward developing your own application.

  1. From the root directory, you now need to go to the directory containing the demo app:

    cd samples

    Here you will find the following files:

    /views/index.ejs
    app.js
    package.json
    sample.json

    Now run:

    node app.js

    Your app should now be running on http://127.0.0.1:5000/ (or whichever port you have set!)

    image1

    From here you will be prompted to:

    1. Register
    2. Key in your identity
    3. Confirm your identity (by email activation)
    4. Create a 4-digit PIN
    5. Login

    Once logged in you will be greeted by the refresh/logout page:

    image2


Creating your own app


You can now begin creating your own apps within your top-level node projects folder. What follows is a detailed breakdown of the structure and code used in creating the sample app, which will give you a broad understanding of how to begin creating your own app. Note that the snippets of code which follow can be put to use, and you can also find the full files (complete with commented code) in the samples folder.

The following is a tree view of the folder / file layout of the sample app:

├── app.js
├── node_modules
│   ├── accepts
│   ├── array-flatten
│   ├── base64-url
│   ├── config-json
│   ├── inherits
│   ├── ipaddr.js
│   ├── maas-sdk-nodejs
│   ├── media-typer
├── package.json
├── sample.json
└── views
    └── index.ejs

Note that the list of modules is trimmed down for concise display. These modules were installed when the npm install command was run.

To begin creating your own app you can, within your top-level node projects folder, create a new folder called e.g. myapp and, into this, copy and paste the node_modules directory from the samples folder. You can then begin creating your own .js and .ejs files to create your own app.

In the sample app, the key files are:

  • The views/index.ejs file, to create a main web page with the login button
  • The sample.json credentials file
  • The app.js script which contains the code for dealing with the Miracl Client object and communicating with the platform

The instructions to follow will guide you on how to create your own app which gives complete management of the authorization flow.

1. Create the main web page and the login button

Note that the use of col-md divs here assumes use of the bootstrap framework, as does the use of the <% %> tags to receive flash messages in the standard bootstrap categories of 'success', 'info' and 'danger'.

In the views/index.ejs file, the first task is to check if a user has attempted login and listen out for success or danger messages coming from your main script. The default success or failure messages are then displayed:


<div class="row">
    <div class="col-md-12">
      <% if(success && success.length > 0){ %>
        <div class="alert alert-success">
            <%= success %>
        </div>
      <% }else if(danger && danger.length > 0){ %>
        <div class="alert alert-danger">
            <%= danger %>
        </div>
      <% } %>
    </div>
</div>

The next block then sets up the div for the login button if login has failed:


<% if(danger && danger.length > 0) {%>
    <div class="col-md-12">
          <div id="btmpin"></div>
    </div>

Or, if an is_authorized message is coming from the script, the User ID and Email are displayed as well as the refresh and logout buttons:


<%} else {%>
  <div class="row">
  <% if (is_authorized) {%>
    <div class="col-md-4">
      <b>E-mail: </b><%=email%><br/>
      <b>User ID: </b><%=user_id%><br/>
    </div>
    <div class="col-md-4"></div>
    <div class="col-md-4">
      <a href="/refresh" class="btn btn-primary action">Refresh user data</a>
      <a href="/logout" class="btn btn-primary action">Log out</a>
    </div>
  <% }else { %>
    <div class="col-md-12">
      <div id="btmpin"></div>
    </div>
  <% } %>
  </div>
<% } %>
</div>

If the is_authorized message is not coming from your script, as will be seen later, your script will have provided an authorization url. In this case a btmpin div is created to contain the login button (note that the wording for this is automatically populated by mpad.js hence there is no text entered in the btmpin div:

    <script src="https://mcl.cdn.mpin.io/mpad/mpad.js" data-authurl="<%=auth_url%>" data-element="btmpin"></script>

The button itself is created with the javascript, which makes use of the mpad.js library to send the authentication information to the server.

The parameters passed in this script are:

  • data-element: the login button ID (corresponds with <div id="btmpin">)
  • data-authurl: the authorization URL (this passes the client_id and redirect_uri to the authentication server). Each SDK has a 'Get Authorization Request URL' method for obtaining this.

2. Create a Credentials file

For security, the client ID and secret for a genuine app should not be stored in clear text in a config file. This has only been done here for simple demo purposes. For a production scenario, the client ID and secret should be programmatically accessed via an encrypted API

In the app folder, a file named e.g. sample.json can be used to store the credentials for your app:

{
  "clientID": "CLIENT_ID",
  "clientSecret": "CLIENT_SECRET",
  "redirectURL": "REDIRECT_URI"
}

Substitute the correct values for your app, as discussed in 'Prerequisites' above.

3. Create a main server script

In the sample app this is the app.js file. The requires are:

var express = require('express');
var session = require('express-session');
var flash = require('connect-flash');
var miraclClient = require('maas-sdk-nodejs');
var config = require('config-json');
var app = express();

Then the app is set to work with the .ejs view, and the express session is initialised:

app.set('view engine', 'ejs');

/**
 * Setting up Express session
 * 'session' object is saved in req object and available to all route methods
**/
app.use(session({
  secret: 'random_string',
  resave: false,
  saveUninitialized: true
}));

Then the connect-flash module is initialised and the flash authentication success/failure messages are made available:

app.use(flash());

app.use(function(req, res, next){
    res.locals.success = req.flash('success');
    res.locals.danger = req.flash('danger');
    next();
});

Then the credentials are retrieved from the json file and used to initialize the Miracl Client:

app.use(function(req, res, next) {
  // Retrieving credentials from 'sample.json'
  config.load('./sample.json');
  var configuration = config.get();

  // Initialization of miraclClient and storing it in req object so it is available to route methods
  req.miracl = new miraclClient(configuration, function(error, config) {
    if(!error){
      next();
    } else {
      res.send(error);
    }
  });
});

Then, at the main authorization handler "/" endpoint, a check is made to see if the user is already authorized by using the .isAuthorized() method:

app.get('/', function (req, res) {

  if(req.miracl.isAuthorized(req.session)) {
    req.miracl.getEmail(req.session, function(error, email) {
      req.miracl.getUserID(req.session, function(error, user_id) {
        if(error) {
          res.send(error);
        } else {
          res.render('index', { is_authorized: true,
                              user_id: user_id,
                              email: email }
          );
        }
      });
    });
    } else {
  res.render('index', { is_authorized: false,
                          auth_url: req.miracl.getAuthorizationRequestUrl(req.session) });
}
});

The first if section means that, on success, an access token will be returned, and the getEmail and getUserID methods can be use to obtain the user's email and ID, which are made available to the views/index.ejs template.

The else section means that, on failure, the .getAuthorizationRequestUrl() method is used to pass the is_authorized: false and auth_url message to the template.

Important Note on User Management

In terms of managing your users, it is important to note that, in the process of providing a secure login solution, the service has also registered your users with a confirmed user email and user ID. Once a user has been authenticated it is possible to make use of the above getEmail and getUserID methods to return string values.

This removes a considerable amount of pain from the process of managing users and databases!

For example, if you have a SQL user database and you want to make a check to see if a user is present, or needs added as a new user, then it is possible to make use of the above methods.

Another example would be if you want to present a web form to capture more information that is needed to provide a user with access to your product features. Here you can use the above methods to prepopulate the ID and email address field, and you do not need to initiate a 'verify by email' process, as this has already been done by the service.

After isAuthorized, at the "/login" redirect endpoint, the final validation can be carried out, with a success or danger message being passed to the template:

app.get('/login', function(req, res) {
  req.miracl.validateAuthorization(req.query, req.session, function (err, accessToken) {
    if(err){
      console.log(err.toString());
      req.flash('danger','Login failed!');
    } else {
      req.flash('success','Successfully logged in!');
    }

    res.redirect('/');
  });
});

On successful validation the access token is saved in the session variable, along with the obtained user info (email and ID).

Using the miracl.clearUserInfo() method, the refresh functionality is made available at the "/refresh" endpoint:

app.get('/refresh', function(req, res) {
  req.miracl.clearUserInfo(req.session);
  res.redirect('/');
});

Note that refresh clears userInfo from the session, but leaves the access token unchanged. This means that user info can be requested without performing a fresh authorization.

Using the miracl.clearUserInfo() method, the logout functionality is made available at the "/logout" endpoint:

app.get('/logout', function(req, res) {
  req.miracl.clearUserInfo(req.session, true);
  res.redirect('/');
});

Note that the true parameter means that the access token is also cleared, so a fresh authorization will be required.

Finally, the listening port is set (remember this should be set so that your redirect uri will function correctly), and your script is made available by module.exports:

app.listen(5000);
module.exports = app;

Top