Ruby


Table of Contents:

Prerequisites
Ruby SDK Installation
Run the ruby Demo App
Create 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 MIRACL Trust 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. These are found in 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.


Ruby SDK Installation


Dependencies

Make sure the following are installed on your system:

  • ruby
  • ruby gems
  • bundler
  • sinatra

1. Download or clone the SDK from:

https://github.com/miracl/maas-sdk-ruby.git

2. Go to the root maas-sdk-ruby folder and run bundle install

This means you can now include the Miracl API by placing require 'miracl_api' at the top of any file where you are going to use the SDK (as will be seen in the sinatra_sample.rb file later).

3. Alternative install method:

In root maas-sdk-ruby folder run gem build miracl_api.gemspec to build the gem

Then install the gem: gem install miracl_api-0.1.0.gem

After successful installation gem 'miracl_api' can be added to Gemfiles being used, and require 'miracl_api' can be placed at the top of any file where you are going to use the SDK.


Run the Ruby 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. Open the samples/sample.json file and configure it with your client id, client secret and redirect_uri values, as set up in the app details screen in the portal:

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 **sinatra_sample.rb** contains the line `set :port, 5000` means that the app will be listening on **http://127.0.0.1:5000** and that a redirect_uri value of **http://127.0.0.1:5000/login** will function correctly. If you wish to change this, just edit the `set :port, 5000` line, but remember it must match what has been entered in your app details screen in the portal.
  1. Open the views/application.erb 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>
  2. Open samples/Gemfile and uncomment line 6 and remove , :branch => "development" to leave gem 'miracl_api', :git => "https://github.com/miracl/maas-sdk-ruby.git"

    Then, making sure you are in the samples folder, run bundle install

  3. Start the server:

    ruby sinatra_sample.rb

    At the top of the .rb file you will see the code block:

    configure do
    set :port, 5000
    enable :sessions
    end

    which tells you that your sample app is open for testing at http://127.0.0.1:5000:

    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


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.

To start developing your own app, create a project folder within the maas-sdk-ruby root folder.The basic steps involved, as per the sample app, are:

  • Create a main web page with the login button (in the sample app this is views/application.erb)
  • Create a credentials file
  • Create a main server script to contain the code for dealing with the Miracl Client object and communicating with the platform

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/application.erb file, first listen for messages coming from your main script:

  <div class="row">
      <div class="col-md-12">
        <% flash.each do |key, message| %>
          <div class="alert alert-<%= key %>">
              <%= message %>
          </div>
        <% end %>
      </div>
  </div>  

Then run an if @retry to check for the retry message coming from your main script. The retry message means that an attempted login has failed (as will be seen later) and 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):

  <% if @retry %>
  <div class="col-md-12">
        <a href="#" class="btn btn-primary" onClick="mpin.login({authURL: '<%=@auth_url%>'})">Retry?</a>
    </div>

The next if @is_authorized check is to listen for the is_authorized message, in which case display the user email and id, plus the refresh and logout buttons which initiate a redirect to the "/refresh" and "/logout" endpoints:

  <% 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>
                <script src="https://mcl.cdn.mpin.io/mpad/mpad.js" data-authurl="<%=@auth_url%>" data-element="btmpin"></script>
              </div>
          <% end %>
        </div>
      <% end %>

The last else section of the above snippet then creates a btmpin div 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).

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 project folder, a file named e.g. sample.json can be used to store the credentials for your app:

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

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

3. Create a main server script

Now create a main .rb server script, with the following main elements:

  1. Requires

    require "bundler/setup"
    require 'sinatra'
    require 'sinatra/flash'
    require 'miracl_api'
    require 'json'

    Note that sinatra/flash enables use of flash messaging to communicate with the .erb page template.

  2. Set listening port

    configure do
    set :port, 5000
    enable :sessions
    end
  3. Read Credentials

    before do
    file = open("sample.json")
    json = file.read
    parsed = JSON.parse(json)
    credentials = parsed.inject({}){|memo,(k,v)| memo[k.to_sym] = v; memo}
    @miracl = MiraclApi::MiraclClient.new(credentials)
    end

    Note that the above reads the credentials from the json file and also initiates a new @miracl client with the imported credentials.

  4. Working with the Miracl Client object

    At the main handler "/" endpoint, a check is made to see if the user is already authorised by using the .is_authorized() method:

    get('/') do
    @retry = flash[:danger] ? true : false
    @is_authorized = @miracl.is_authorized(session)
    if @is_authorized
      @email = @miracl.get_email(session)
      @user_id = @miracl.get_user_id(session)
    else
      @auth_url = @miracl.get_authorization_request_url(session)
    end
    erb :application
    end

    If the user is authorized an access token is returned, and the .get_email() and .get_user_id() methods can be used to return the user data to the application.erb template.

    If the user is not authorized, the .get_authorization_request_url() method is used to pass auth_url to the application.erb template (this passes the client_id and redirect_uri to the authentication server), and @retry will also be sent.

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 .get_email() and .get_user_id() 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.

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

  get('/login') do
    # Validating the authorization
    # 'params' hash contains Sinatra parsed request query string. It should include :state and :code so access token
    #  along with user info can be obtained and stored in session
    if @miracl.validate_authorization(params, session)
      flash[:success] = "Successfully logged in!"
    else
      flash[:danger] = "Login failed!"
    end
    redirect '/'
  end

And the refresh and logout options can be presented:

  get('/refresh') do
    # Clears user info from session but leaves access token unchanged
    #  so user info can be obtained without performing fresh authorization
    @miracl.clear_user_info(session)
    redirect '/'
  end

  get('/logout') do
    # If 'including_auth=true' is passed as a second parameter to MiraclClient#clear_user_info,
    #  then not only user info is cleared from session but also access token
    #  so call of MiraclClient#is_authorized returns false
    @miracl.clear_user_info(session, including_auth=true)
    redirect '/'
  end

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.

Top