Rebar Web Service Access

Monkton, Inc.

Rebar itself allows for Web Services to be accessed via API Endpoints within the Rebar Hub. We have added the ability to call Web Services directly from apps itself, in a secured manner you can use to validate users and their credentials.

When a user logs into an app built with Rebar, they are issued a set of Rebar Bearer Tokens (RBT) that are stored within the app. Each request made by the app secured by Rebar via HTTPS is then signed with the RBT and passed as headers for the the server to authenticate the user and context. (These can be embedded in your web service calls with the RebarUtil.instance.signedRebarHeaders convenience method).

Going directly to the web service will avoid the overhead of an extra hop from the Rebar Hub, increasing performance of the app secured with Rebar.

Token Generation Checklist

  • Identify how you would like to generate tokens

    Your web service will need to be able to generate an initial token for the user of the web service. Your Token Generation Service must be able to call the Rebar Token Validation Service

  • Generate Tokens for Users

    Once your Token Generation Service has invoked the Rebar Token Validation Service and obtained a valid user, the service shall generate tokens and assign a TTL to the token

  • Securely store tokens in the app

    If writing a bespoke method to sign, store and retrieve the tokens using Rebar's secure RebarSettingController.default.setSecureSetting and RebarSettingController.default.getSecureSetting methods. If you are going to use Rebar's built in methods to use the settings, invoke the RebarUtil.default.setWebServiceApiKeys methods described below.

  • Sign the Requests

    When invoking your web service, the Rebar RBT signed headers must be present in the request, as well as the apps signed token headers. Use the RebarSettingController.default.getSecureSetting to retrieve your tokens if you are performing signing yourself or the RebarUtil.default.signedHeadersForWebServiceApi method to automatically manage signing

  • Refresh Tokens

    As your tokens expire, the web service shall be able to refresh the tokens with the Rebar Token Validation Service at any time. The Rebar RBT are sent with each request to your web service, the headers can be forwarded to the Rebar Token Validation Service and validation can be performed. As above, you will need to securely store the refreshed tokens.

Building your Token Service

By no means do you have to use the methodology below to generate tokens for your web service and app. You must leverage the Rebar Token Validation Service defined below and you must include the Rebar Headers forwarded to the Rebar Token Validation Service.

We have outlined the below as a means to assist in developing web service and authentication rapidly.

The requirements are basic:

  1. Your web service must issue some type of token to the app
  2. The app must pass those tokens to the web service
  3. The app must pass the Rebar Bearer Tokens (outlined below) to your web service as headers
  4. Your Web Service must call the Rebar Token Validation Service to validate the user is still valid within Rebar and has access to the app
  5. Your Web Service must be able to refresh tokens in the same manner as requirement #4 above

Additionally, in the app-config.json value you must add your Web Service domains. This will automate the signing of the request with the RBT.

"rebar.webservice.hosts": [
    "sample-dev-api.monkton.io"
]

Web Service Tokens

As stated above, this methodology below is provided as a means to rapidly build tokenization on the app side. By no means must you use this.

To call a web service directly from a Rebar App and avoid passing through the Rebar Hub, your web service will need to perform three basic functions:

  1. Issue Web Service Bearer Tokens (WSBT)
  2. The Web Service must be able to call the Rebar Token Validation Service to validate the users
  3. Refresh WSBT as they expire

Using Headers

You can certainly manage signed headers for your web service however you like, but we have built in some convenience methods to perform that work for you. The RebarUtil helper class has a few methods to streamline the process. These methods assume you have a sharable token and a secret token generated by your WSBT.

  • RebarUtil.default.setWebServiceApiKeys
  • RebarUtil.default.signedHeadersForWebServiceApi
  • RebarUtil.default.clearWebServiceApiKeys

Storing Headers

You can store your WSBT in the RebarUtil.default.setWebServiceApiKeys by invoking:

// Grab the keys we will store
let sharedKey = resultDictionary["authKeyRefId"] as! String
let secretKey = resultDictionary["secretKey"] as! String

// Store these values
RebarUtil.default.setWebServiceApiKeys(service: "sample-app", publicKey: sharedKey, secretKey: secretKey)

In this example, the result from the WSBT has a header value authKeyRefId and secretKey, we then store them using the RebarUtil.default.setWebServiceApiKeys method. From here, we can then use those WSBT tokens to sign headers.

Leveraging Headers

Whenever a request is made by Rebar to one of the Web Service endpoints, it has signed headers placed into the request to be sent to the server using the RBT. For those requests where you make a call directly to a web service and you need to use the WSBT, you will need to use the RebarUtil.default.signedHeadersForWebServiceApi header signer to make the request.

// Grab the signed headers we will send to the server
var signedHeaders = RebarUtil.default.signedHeadersForWebServiceApi(service: "sample-app")

This will generate a dictionary of key/value pairs to store in your headers:

  • RebarApp-RequestIdentifier: random identifier for the request
  • RebarApp-RequestTime: ISO formatted date time of the request
  • RebarApp-AppIdentifier: the bundle id of the app
  • RebarApp-SharedKey: the publicKey token to identify the requesting user
  • RebarApp-ToSign: the value that was signed by the secret key
  • RebarApp-Signature: the computed signature (Base 64 encoded)

The RebarApp-ToSign is computed by concatenating the RebarApp-RequestIdentifier with RebarApp-RequestTime as follows:

let valueToHash: String! = "\(requestId!)|\(requestTime!)";

The RebarApp-RequestIdentifier is used to prevent replay attacks on the server. The id should be cached with a time to live.

The RebarApp-RequestTime is used to prevent time based attacks on the server, the request should be made and processed within a time window you define.

Making Server Request

When you are ready to make your request to the server, you will want to invoke the RebarUtil.default.signedHeadersForWebServiceApi method. This generates the series of headers you can add to your HTTPS request to the server:

// Grab the signed headers we will send to the server
var signedHeaders = RebarUtil.default.signedHeadersForWebServiceApi(service: "sample-app")

From there, your Web Service must validate the requesting tokens, refresh them, or invalidate the request back to the device.

App Config Keys and Settings

Within the app-config.json file, we must define the `` key, which is a string array of host names that the app will connect to. This is done so the RBT can be automatically attached to the request

"rebar.webservice.hosts": [
    "sample-dev-api.monkton.io"
]

In this case, when we make a request to sample-dev-api.monkton.io, the RBT headers are automatically sent to the endpoint.

Web Service Architecture

The Web Service will need to implement a token generation service to issue your Web Service Bearer Tokens (WSBT) for the app to consume and store.

For instance, when crafting a Web Service, you may create the endpoint /api/v1/app/token that accepts requests from the app. Your token generation endpoint should

  1. Invoke the Rebar Token Validation Service and pass the Rebar Headers along
  2. Validate that it gets a successful user object back
  3. Issue tokens for the user
  4. Pass the tokens back to the app

Rebar Token Validation Service

The Rebar Token Validation Service is meant to validate that the RBT headers are valid. If they are valid, they will return back a JSON object that contains the following fields:

  • accountRefId: within Rebar, the random and unique identifier for the user
  • accountEmail: within Rebar, the users email
  • accountAdUpn: within Rebar, the users UPN
  • accountName: within Rebar, the users name

With a successful HTTP status code of 200, you will receive back a JSON object such as:

{
	"accountRefId": "account_2RFVEG046pztVjcOOTwSHxHKgUJn8Y-zu_2y-3i_Ujtr",
	"accountEmail": "g.washington@army.mil",
	"accountAdUpn": "g.washington@army.mil",
	"accountName": "George Washington"
}

Upon this successful result, you now know that your user has a valid account and has access to the app they are using!

The Rebar Token Validation Service

The Rebar Token Validation Service (RTVS) is located off the Rebar API, at the path https://api.yourdomain.com/v1/token/validate. Invocation of this requires a series of fields to perform a zero trust validation:

  • HMAC signed headers
  • RBT signed headers

HMAC signed headers

Obtain your Web API Token's from the Rebar Hub Admin portal. You will get a Public Token and Secret Token value.

Caution - cycling these tokens will invalidate other tokens.

To make a request to the RTVS, you will need to perform a HMAC signature operation and pass the headers to the server:

// Grab the headers—you should use a secure store to store these values
string publicKey = Environment.GetEnvironmentVariable("REBAR_AUTH_PUBLIC");
string signingKey = Environment.GetEnvironmentVariable("REBAR_AUTH_SECRET");

// Generate the dictionary with the keys
Dictionary<string, string> headers = new Dictionary<string, string>();
headers.Add(@"rebar-ref-id", publicKey);
headers.Add(@"rebar-time", DateTime.UtcNow.ToString(@"s"));
headers.Add(@"rebar-identifier", @"abc");

// Generate what we will sign
string toSign = Convert.ToBase64String(Encoding.UTF8.GetBytes(headers[@"rebar-identifier"] + headers[@"rebar-time"]));

// Sign the data...
string hashed = platformCrypto.HMAC256(toSign, signingKey);

// Embed the signature
headers.Add(@"rebar-signature", hashed);
  • rebar-ref-id: The Web API public token from the Rebar Admin
  • rebar-identifier: random identifier for the request
  • rebar-time: ISO formatted date time of the request
  • rebar-signature: the computed signature (Base 64 encoded)

When the https://api.yourdomain.com/v1/token/validate method receives the request, it will validate that the signature sent is correct.

Testing HMAC Signed Headers

Before you integrate, you can also invoke the https://api.yourdomain.com/v1/token/validate/test with an HTTP GET using the signed HMAC headers. This will return a JSON object with the values:

{ "status": true }

Forwarding Rebar RBT headers

In order to validate a users, you will need to do a HTTP GET to the https://api.yourdomain.com/v1/token/validate with the following headers. Each of these headers will be present coming from the Rebar App to your Web Service.

// Grab the headers (from HMAC signed headers)
var headers = HMACSignedHeadersForRebarHub();

// Copy over the Rebar headers so we can validate the users request
headers.Add("auth-request-identifier", identifier);
headers.Add("auth-request-time", time);
headers.Add("auth-request-signature", signature);
headers.Add("auth-request-user", user);

// Generate the tokens we will validate with...
var result = AppHttpPoster.Get("https://api.yourdomain.com/v1/token/validate", headers);

With a successful HTTP status code of 200 you will receive the JSON object that contains the user fields.

{
	"accountRefId": "account_2RFVEG046pztVjcOOTwSHxHKgUJn8Y-zu_2y-3i_Ujtr",
	"accountEmail": "g.washington@army.mil",
	"accountAdUpn": "g.washington@army.mil",
	"accountName": "George Washington"
}

Leveraging the Account Object

Your web service can assume, that when the user object returns, the user is valid within the Rebar Hub. If the service returns a value other than 200 and is missing the account object, the user is either not in Rebar, they have lost access to the app, or their account has been disabled or removed. In such instances, you would prevent the user from issuing new tokens or interacting with your Web Service.

Refreshing Tokens

We suggest that your Web Service Bearer Tokens (WSBT) have a TTL assigned to them. This range can be anything from single use, 12 hours, 5 days, 10 days, or even more. Your TTL should be defined by the risk to your system and it is defined in numOfSeconds.

When the app invokes your Web Service, you should perform validation of your WSBT. If your WSBT has timed out, you can, from that same validation method, re-invoke the Rebar Token Validation Service and refresh the tokens.

The refreshed tokens must be sent back to the app (we suggest as headers) and stored using the RebarUtil.default.setWebServiceApiKeys method. In the case below, our web service will return the public key as refresh-authkeyrefid and the secret key as the refresh-secretKey header. On the next invocation of the Web Service, the RebarUtil.default.signedHeadersForWebServiceApi method will use the updated tokens.

// Grab the keys we will store
let sharedKey = resultDictionary["refresh-authkeyrefid"] as! String
let secretKey = resultDictionary["refresh-secretKey"] as! String

// Store these values
RebarUtil.default.setWebServiceApiKeys(service: "sample-app", publicKey: sharedKey, secretKey: secretKey)