Getting started in Sandbox

API Guides

Overview

When you build an application to be used on Narmi's platform, you're building a web app which will be served inside an iframe container from your own domain inside of digital banking. Since Narmi only serves apps to logged in users, this means that you are guaranteed to have a logged in user available for authentication. You may control the size, scrolling, and other properties of the iframe by using the iframe resizer API.

All apps must be served over TLS (a https:// url). This ensures the security of requests.

Understanding App Launch

When your app is loaded on Narmi's platform, a HTTP POST request is made to your specified app URL. This POST request will contain some parameters in the body, including the signed_request parameter which you should decode for user information, and a signature to verify the security and authenticity of this data.

The signed_request is base64 encoded and signed with an SHA256 HMAC of your App Secret (sometimes this is called a JSON Web Token). You can parse this parameter like this:

  1. Split the signed request into three parts delineated by a '.' character (eg. 34k324nsfsfm.238fsdfsd.oijdoifjsidf899).
  2. Calculate the expected signature of the request, and compare it to the third part - the encoded signature.
  3. If the expected signature and signature match, decode the second part - the payload - from base64 and then decode the resultant JSON object.

This JSON object has several keys:

Name Type Description Example
exp number expiration, a Unix epoch timestamp 1291840400
iat number issued at, a Unix epoch timestamp 1516239022
aud string client id of the application “7ugpYTwyIoFkhz6bLnzQJGYUEaJGtcnrv8pfOJCb”
sub string subject, the Narmi user id “0b0b893f-9885-4789-b26d-6e879f0fc693”
user.institution_user_identifier string uniquely identifies the current user on the core “555555”
user.institution_business_identifier string uniquely identifies the current user's business on the core (if any). Is not the EIN “555556”
user.narmi_business_identifier string UUID, uniquely identifies the business to Narmi "823686a9-6412-4a3e-b1bc-79371702f7fb"

If exp is greater than the current time, then the request should be considered invalid.

These steps are possible in any modern programming languages. Here are some examples:

PHP:

function parse_signed_request($signed_request) {
 list($header, $payload, $encoded_sig) = explode('.', $signed_request, 3);
 $secret = "appsecret";

 // Use your app secret here
 $sig = base64_url_decode($encoded_sig);

 // confirm the signature  $expected_sig = hash_hmac('sha256', $header.".".$payload, $secret, $raw = true);
 if ($sig !== $expected_sig) {
   error_log('Bad Signed JSON signature!');
   return null;
 }

 // decode the data  $data = json_decode(base64_url_decode($payload), true);
 return $data;
}

function base64_url_decode($input) {
 return base64_decode(strtr($input, '-_', '+/'))
;}

Then to use it:

parse_signed_request($_REQUEST['signed_request'])

For example:

parse_signed_request("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjEyOTE4NDA0MDAsInN1YiI6IjBiMGI4OTNmLTk4ODUtNDc4OS1iMjZkLTZlODc5ZjBmYzY5MyIsInVzZXIiOnsiaW5zdGl0dXRpb25fdXNlcl9pZGVudGlmaWVyIjoiOTk2MjcifSwiaWF0IjoxNTE2MjM5MDIyfQ.SUxrDJW6Q7Uylefh6aEbodxRpeeJ8bHTIT1Hs-RrYMQ")

Will produce a JSON payload of:

{
 "exp": 1291840400,
 "sub": "0b0b893f-9885-4789-b26d-6e879f0fc693",
 "user": {
   "institution_user_identifier": "99627"
 },
 "iat": 1516239022
}

ASP.NET

This example uses the .NET class HMACSHA256.

static string ParseSignedRequest(string signedRequest){
   string[] split = signedRequest.Split('.');
   string header = split[0];
   string data = split[1];
   string dataRaw = FixBase64String(data);
   string signatureRaw = FixBase64String(split[2]);

   // the decoded signature
   byte[] signature = Convert.FromBase64String(signatureRaw);
   byte[] dataBuffer = Convert.FromBase64String(dataRaw);

   // JSON object    string dataJson = Encoding.UTF8.GetString(dataBuffer);
   byte[] appSecretBytes = Encoding.UTF8.GetBytes("appsecret"); // Use your app secret here
   HMAC hmac = new HMACSHA256(appSecretBytes);
   byte[] expectedHash = hmac.ComputeHash(Encoding.UTF8.GetBytes(header + "." + data));
   bool areEqual = expectedHash.SequenceEqual(signature);

   if (areEqual) {
       return dataJson;
   } else {
       return "";
   }
}

static string FixBase64String(string str){
   string result = str;
   while (result.Length % 4 != 0)
   {
       result = result.PadRight(result.Length + 1, '=');
   }
   result = result.Replace("-", "+").Replace("_", "/");
   return result;
}

For example:

using System;
using System.Text;
using System.Linq;
using System.Security.Cryptography;

public class Program{
 public static void Main()
 {    Console.WriteLine(ParseSignedRequest("eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJleHAiOjEyOTE4NDA0MDAsInN1YiI6IjBiMGI4OTNmLTk4ODUtNDc4OS1iMjZkLTZlODc5ZjBmYzY5MyIsInVzZXIiOnsiaW5zdGl0dXRpb25fdXNlcl9pZGVudGlmaWVyIjoiOTk2MjcifSwiaWF0IjoxNTE2MjM5MDIyfQ.SUxrDJW6Q7Uylefh6aEbodxRpeeJ8bHTIT1Hs-RrYMQ"));
 }
 //...
}

Will produce a string that can be JSON parsed:

{"exp": 1291840400,"sub": "0b0b893f-9885-4789-b26d-6e879f0fc693","user": {"institution_user_identifier": "99627"},"iat": 1516239022}

Narmi Inc.
3 East 28th St. Floor 12
New York, NY 10016