One-Time Password

Authenticate users and transactions with OTP and 2FA.


Use One-Time Passwords (OTP) in Two-Factor Authentication (2FA) to ensure a user is who they claim to be when they login or perform transactions.

Categories: Enterprise Communications 

Accessing accounts and performing transactions requires strong user authentication. In the context of customers, it is strong customer authentication (SCA) that is required and often mandated. One-Time Passwords (OTP), along with Two-Factor Authentication (2FA), provide a means to verify that a person is who they claim to be.

Ways to use One-Time Password

The Melrose Labs One-Time Password service provides the means to process One-Time Passwords using one of two ways. OTPs are generated by the service, sent to users and verified by the service; or are generated by an application on the user's device (e.g. Google Authenticator) and verified by the service.

Sending OTPs to Users

Sending One-Time Passwords to users can be done with a REST call to our OTP API, and delivered via SMS text message, voice call or email.

When using the Melrose Labs One-Time Password service, we don't let you know the actual One-Time Password that has been sent to your user, therefore preventing potential leakage of this critical information at the source.

TOTP Service: OTP and Google Authenticator

Time-base One-Time Passwords: Users can quickly be enrolled with the One-Time Password service and use the Google Authenticator mobile app on their mobile to generate OTPs. The user provides the OTP that was generated on their mobile and the service then verifies this.

Use of this method may be preferable in some scenarios.

Integrate with the One-Time Password service

Integrate OTP into your application using our OTP API. For simple integration, use one OTP API call to send an OTP to a user and another API call to verify what the user provided.

Sending OTP codes and verifying code from user

To send an OTP, you specify the message content and the recipient. You can also specify the complexity of the OTP (e.g. length, digits-only, letters-only or letters and digits) and its expiry. Delivery of the OTP will take place in a few seconds when using SMS text, email or voice call.

SIM-Swap Detection: For OTP delivery to UK mobiles via SMS or voice call, a check can be performed to confirm that the user account is not the victim of SIM-swapping.

Find out more

TOTP Service: Verify code from user when using Google Authenticator

Enroll user with service: Make REST API call to add user to service. Provide user with enrolment link for them to scan QR code with Google Authenticator.

When user then performs login or transaction, ask them for TOTP code from Google Authenticator. Make a REST API call to the OTP service and provide the TOTP code from the user and the user's OTP service user ID. The service will then verify if the provided code is valid for that user at that time.

REST API

Create Domain

Create an authentication domain for users.

Request:

curl --location --request POST https://api.melroselabs.com/identity/otp/domain/ \
	--header 'x-api-key: [API_KEY]' 

Response:

{"domain": "cabcc674-a328-432d-b925-0d5c3e79a183"}

Request:

var request = require('request');
var options = {
  'method': 'POST',
  'url': 'https://api.melroselabs.com/identity/otp/domain/',
  'headers': {
    'x-api-key': '[API_KEY]'
  }
};
request(options, function (error, response) { 
  if (error) throw new Error(error);
  console.log(response.body); // response is of type application/json
});

Response:

{"domain": "cabcc674-a328-432d-b925-0d5c3e79a183"}

Request:

import requests
import json

url = "https://api.melroselabs.com/identity/otp/domain/"

headers = {
  'x-api-key': '[API_KEY]'
}

response = requests.request("POST", url, headers=headers)

# response is of type application/json
print(response.text.encode('utf8'))

Response:

{"domain": "cabcc674-a328-432d-b925-0d5c3e79a183"}

Request:

<?php 
$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => "https://api.melroselabs.com/identity/otp/domain/",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_HTTPHEADER => array(
    "x-api-key: [API_KEY]"  )
));

$response = curl_exec($curl);

curl_close($curl);

echo $response; // response is of type application/json
?>

Response:

{"domain": "cabcc674-a328-432d-b925-0d5c3e79a183"}
Create user

Create a user within an authentication domain.

return_secret set to true will cause the generated secret to be returned. This should then be given to the user to add into Google Authenticator and enrolment will be assumed to have been completed. When set to false, or omitted, the secret will not be returned and instead an enrolment URL will be returned. The enrolment URL allows users to add the secret themselves to Google Authenticator.

set_secret is used to specify the secret to be used, rather than the service generate a secret.

We recommend the use of anonymised user IDs (user_id) with the service, rather than email addresses or similar that third parties can easily identify individuals with. Examples use email address to clearly illustrate purpose of field.

Request:

curl --location --request POST https://api.melroselabs.com/identity/otp/user/ \
	--header 'x-api-key: [API_KEY]' --header 'Content-Type: application/json' \
	--data-raw '{"domain": "cabcc674-a328-432d-b925-0d5c3e79a183", "user_id": "john.grant@melroselabs.com", "return_secret": true}'

Response:

{"domain": "cabcc674-a328-432d-b925-0d5c3e79a183", "user_id": "john.grant@melroselabs.com", "secret": "QIATV7YPGLQKDDIC", "type": "totp", "interval": 30}

Request:

var request = require('request');
var options = {
  'method': 'POST',
  'url': 'https://api.melroselabs.com/identity/otp/user/',
  'headers': {
    'x-api-key': '[API_KEY]',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({"domain": "cabcc674-a328-432d-b925-0d5c3e79a183", "user_id": "john.grant@melroselabs.com", "return_secret": true})
};
request(options, function (error, response) { 
  if (error) throw new Error(error);
  console.log(response.body); // response is of type application/json
});

Response:

{"domain": "cabcc674-a328-432d-b925-0d5c3e79a183", "user_id": "john.grant@melroselabs.com", "secret": "QIATV7YPGLQKDDIC", "type": "totp", "interval": 30}

Request:

import requests
import json

url = "https://api.melroselabs.com/identity/otp/user/"
payload = {
	{"domain": "cabcc674-a328-432d-b925-0d5c3e79a183", "user_id": "john.grant@melroselabs.com", "return_secret": true}
}
headers = {
  'x-api-key': '[API_KEY]',
  'Content-Type': 'application/json'
}

response = requests.request("POST", url, headers=headers, data = json.dumps(payload))

# response is of type application/json
print(response.text.encode('utf8'))

Response:

{"domain": "cabcc674-a328-432d-b925-0d5c3e79a183", "user_id": "john.grant@melroselabs.com", "secret": "QIATV7YPGLQKDDIC", "type": "totp", "interval": 30}

Request:

<?php 
$data = {"domain": "cabcc674-a328-432d-b925-0d5c3e79a183", "user_id": "john.grant@melroselabs.com", "return_secret": true}

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => "https://api.melroselabs.com/identity/otp/user/",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => $data,
  CURLOPT_HTTPHEADER => array(
    "x-api-key: [API_KEY]",
    "Content-Type: application/json"
  )
));

$response = curl_exec($curl);

curl_close($curl);

echo $response; // response is of type application/json
?>

Response:

{"domain": "cabcc674-a328-432d-b925-0d5c3e79a183", "user_id": "john.grant@melroselabs.com", "secret": "QIATV7YPGLQKDDIC", "type": "totp", "interval": 30}
Identity Check

Check time-based code provided by user is correct.

Request:

curl --location --request POST https://api.melroselabs.com/identity/otp/totp/ \
	--header 'x-api-key: [API_KEY]' --header 'Content-Type: application/json' \
	--data-raw '{"user_id": "john.grant@melroselabs.com", "code": "704471", "domain": "f5af5a70-e34c-40ad-8e6b-9e2cc883364f"}'

Response:

{"verified": true}

Request:

var request = require('request');
var options = {
  'method': 'POST',
  'url': 'https://api.melroselabs.com/identity/otp/totp/',
  'headers': {
    'x-api-key': '[API_KEY]',
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({"user_id": "john.grant@melroselabs.com", "code": "704471", "domain": "f5af5a70-e34c-40ad-8e6b-9e2cc883364f"})
};
request(options, function (error, response) { 
  if (error) throw new Error(error);
  console.log(response.body); // response is of type application/json
});

Response:

{"verified": true}

Request:

import requests
import json

url = "https://api.melroselabs.com/identity/otp/totp/"
payload = {
	{"user_id": "john.grant@melroselabs.com", "code": "704471", "domain": "f5af5a70-e34c-40ad-8e6b-9e2cc883364f"}
}
headers = {
  'x-api-key': '[API_KEY]',
  'Content-Type': 'application/json'
}

response = requests.request("POST", url, headers=headers, data = json.dumps(payload))

# response is of type application/json
print(response.text.encode('utf8'))

Response:

{"verified": true}

Request:

<?php 
$data = {"user_id": "john.grant@melroselabs.com", "code": "704471", "domain": "f5af5a70-e34c-40ad-8e6b-9e2cc883364f"}

$curl = curl_init();

curl_setopt_array($curl, array(
  CURLOPT_URL => "https://api.melroselabs.com/identity/otp/totp/",
  CURLOPT_RETURNTRANSFER => true,
  CURLOPT_CUSTOMREQUEST => "POST",
  CURLOPT_POSTFIELDS => $data,
  CURLOPT_HTTPHEADER => array(
    "x-api-key: [API_KEY]",
    "Content-Type: application/json"
  )
));

$response = curl_exec($curl);

curl_close($curl);

echo $response; // response is of type application/json
?>

Response:

{"verified": true}

Service snapshot

  • Part of strong customer authentication
  • Simple OTP service API
  • OTP delivery to device, or device generated OTP (TOTP)
  • OTP delivered via SMS, voice or email
  • Enhanced OTP with SIM-swapping fraud check

Find out more...

Please provide your name.
Please provide a valid company name.
Please type your message.
Please provide a valid email address.