Integration Guide – Onemoney Web Redirection Mechanism
Introduction
The Web redirection is a mechanism for FIUs to redirect their users from FIU Web or mobile application to Onemoney AA web application for purpose of user registration, account discovery and linking and consent management and redirection of user back to the FIU web or mobile application. It is a mechanism for seamless and frictionless user experience for end to end consumer journey.
In this mechanism the Onemoney Web application is invoked by FIU application as a HTTP GET request along with some encrypted parameters in the request URL to redirect the consumer from a FIU application page to Onemoney web application. Similarly, once the consumer finishes his activity of approving or rejecting his consent in Onemoney the FIU application is invoked as a HTTP GET request along with some encrypted parameters in the response URL to redirect the consumer from Onemoney web application to a particular page of FIU application.
Process Flow
- FIU gets the Onemoney AA Webview URL form Central Registry
- FIU securely captures consumer’s AA Id or VUA in its application if the consumer is already registered with Onemoney AA or his mobile number if the consumer is a new user and does not have a profile with Onemoney AA
- FIU server generates a consent request (as per ReBIT API specifications) by passing customer VUA in the consent request if the customer is already registered with Onemoney AA or constructs a VUA in mobilenumber@onemoney format if the customer is a new user and not yet registered with Onemoney AA. In response the FIU server receives a consent handle from Onemoney AA server.
- FIU mobile or web application sends a redirection request to Onemoney web application by constructing a request URL which includes some encrypted parameters, FIU entityId and request date/time.
- Onemoney AA server on receiving the redirection request URL decrypts the encrypted URL and performs validation.
- After validation of redirection request Onemoney web application will display the Onemoney login screen or user registration screen depending on whether the customer is existing user or new user.
- If the customer is existing user of Onemoney then customer will authenticate himself with Onemoney. After successful authentication user will be displayed the consent details. Customer will either approve/reject the consent. Similarly, if the customer is a new user of Onemoney then customer will register himself with Onemoney with his mobile number. Onemoney will authenticate the customer by sending OTP to his mobile number. Once customer is registered he will link his financial accounts with Onemoney. After account linking he will be displayed the consent details which he will either approve/reject.
- Based on customer’s approval/rejection of consent Onemoney server will send notification to FIU server alongwith a unique ConsentId provided the consent is approved.
- Onemoney AA will then re-direct the customer to FIU application by constructing a response URL which includes some encrypted parameters, AA Id and response date/time.
- FIU application on receiving the response URL will decrypt the URL and validate it. After validation FIU will display customer the page of the FIU application where it had asked Onemoney AA to be redirected back.
FIU server will then proceed to check the status of consent. If its approved it will fetch the consent artefact from Onemoney AA server and then proceed to place the data request.
Web Redirection Request Parameters
(FIU Calling AA)
A sample request looks like the following:
Onemoney Web application URL
Sandbox – https://aa-sandbox.onemoney.in/
UAT – https://aa-uat.onemoney.in/
Production – https://aa.onemoney.in/
HTTP Method : GET
The URL parameters are as follows (all mandatory):
Parameter Name | Parameter Type | Parameter Description |
---|---|---|
ecreq | Base 64 encoded string | Encrypted parameters (see below) |
reqdate | String | reqdate field format will be ddmmyyyyhh24misss in UTC. Expiry of this field will be 180 secs and beyond this request will be invalid |
fi | String | Unique FIU identifier or FIU entityId. This will be encrypted using Base64/XOR along with reqdate field |
ecreq encrypted parameters
Below are the parameters that will be encrypted using AES256 encryption algorithm
Parameter Name | Parameter Type | Parameter Description |
---|---|---|
txnid | String | UUID txnid. Uniquely identifies a particular redirection event. This same value will be returned by AA to FIU in the ecres txnid field. |
sessionid | String | Value that represents a ‘state’ (or session) on the FIU end. This value is opaque to AA and will be returned as is to the FIU by AA in ecres sessionid field. |
userid | String | The AA user Id or handle or VUA generated by AA after a user is registered with AA (Refer to AA Handle below) |
redirect | String | FIU URL that AA needs to call back after user has provided consent in the AA domain |
srcref | String | Consent handle Id, as returned by AA server to the Consent request API invoked by FIU to AA prior to this redirection call |
AA Handle
For new AA user
The userid should be in mobilenumber@AA format. If AA is Onemoney it should be mobilenumber@onemoney
For existing AA user
The userid should be AA handle generated by AA during user registration. E.g. 9999999999@onemoney
Web Redirection Response Parameters
(AA Calling FIU)
In the response from the AA back to FIU, below URL parameters would be sent by AA
HTTP Method : GET
The URL parameters are as follows (all mandatory):
Parameter name | Parameter type | Parameter description |
ecres | Base64 encoded String | Encrypted parameters (see below) |
resdate | String | format will be ddmmyyyyhh24misss UTC |
fi | String | Unique AA identifier or AA entityId. This will be encrypted using Base64/XOR along with resdate field |
ecres encrypted parameters
Below are the parameters that will be encrypted using AES256 encryption algorithm
Parameter name | Parameter type | Parameter description |
txnid | String | UUID txnid received in ecreq field in the request |
sessionid | String | Value of sessionid received in the ‘ecreq’ field in the request. |
userid | String | The AA user id or AA handle or VUA |
status | String | The status ‘S’ for success and ‘F’ for failure |
errorcode | String | Refer the errorcodes table below |
srcref | String | The consent handle id received in the ecreq ‘srcref’ field |
Error codes: The following errorcodes are returned by the AA to FIU when the user is redirected back to the FIU application.
Error code | Message | Mandatory | When is this returned |
0 | Success | Y | When the user has accepted the consent |
1 | Consent is rejected | Y | When the user rejects the consent |
2 | Consent not available | Y | Consent request not found with the AA. It could be due to the consent handle not available with the AA to which the customer is redirected |
3 | Invalid request | Y | The redirection request has invalid data |
Encryption Mechanism
The mechanism to encrypt the ecreq and acres parameters in the redirection request and response are given below
1. Data-in-transit security by encrypting the communication channel: This is a must-have anyway and TLS 1.2 and above will be used (https), for communication between the FIU app and the AA web app.
2. Additional Data-in-transit security through encryption of data:
All encryption must be done using AES 256. For the AES 256 encryption below will be used
IV – This can be 0
SALT – This will be the reqdate or resdate
Fi – This will be the unique FIU ID or AA ID ( i.e. the FIU entityId or AA entityId )
SECRETKEY – This will be the secret passphrase shared by the FIU to AA
Reference link: https://mkyong.com/java/java-aes-encryption-and-decryption/
Note: The SECRETKEY will be shared offline between FIU and AA
Sample Code for XOR and encryption of the ecreq and ecres fields.
import javax.crypto.Cipher;
import javax.crypto.SecretKey;
import javax.crypto.SecretKeyFactory;
import javax.crypto.spec.IvParameterSpec;
import javax.crypto.spec.PBEKeySpec;
import javax.crypto.spec.SecretKeySpec;
import java.security.SecureRandom;
import java.security.spec.KeySpec;
import static java.nio.charset.StandardCharsets.UTF_8;
import static java.util.Base64.*;
import static javax.crypto.Cipher.DECRYPT_MODE;
import static javax.crypto.Cipher.ENCRYPT_MODE;
public class WebRedirection {
private static final String AES_ALGO = "AES";
private static final String KEY_ALGO = "PBKDF2WithHmacSHA256";
private static final String AES_CBC_PKCS5 = "AES/CBC/PKCS5Padding";
private static final String secretKey = "ac12ghd75kf75r";
private static final String fi = "FIUID";
public static String encrypt(String strToEncrypt, String salt) {
final byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
IvParameterSpec ivspec = new IvParameterSpec(iv);
try {
SecretKeyFactory factory = SecretKeyFactory.getInstance(KEY_ALGO);
KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), salt.getBytes(), 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKeySpec secretKey = new SecretKeySpec(tmp.getEncoded(), AES_ALGO);
Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5);
cipher.init(ENCRYPT_MODE, secretKey, ivspec);
return getUrlEncoder().encodeToString(cipher.doFinal(strToEncrypt.getBytes(UTF_8)));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static String decrypt(String strToDecrypt, String salt) {
byte[] iv = {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0};
IvParameterSpec ivspec = new IvParameterSpec(iv);
try {
SecretKeyFactory factory = SecretKeyFactory.getInstance(KEY_ALGO);
KeySpec spec = new PBEKeySpec(secretKey.toCharArray(), salt.getBytes(), 65536, 256);
SecretKey tmp = factory.generateSecret(spec);
SecretKeySpec secretKey = new SecretKeySpec(tmp.getEncoded(), AES_ALGO);
Cipher cipher = Cipher.getInstance(AES_CBC_PKCS5);
cipher.init(DECRYPT_MODE, secretKey, ivspec);
return new String(cipher.doFinal(getUrlDecoder().decode(strToDecrypt)));
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
public static void printUsage() {
System.out.println("Usage: java EncryptUtil <salt> <payload>");
System.out.println(" where, 'reqdate' is to be used as salt & payload is as per the webview URL redirection spec doc.");
System.out.println(" e.g. java EncryptUtil 031120201803460 \"txnid=T1234&sessionid=S1234&srcref=Srcref1234&userid=acme@perfios-aa&redirect=https://example.com\"");
System.out.println("");
}
public static void main(String[] args) {
String salt = null;
String payload = null;
if (args.length < 2) {
printUsage();
return;
}
salt = args[0];
payload = args[1];
if (salt == null || salt.length() == 0) {
System.out.println("Error: Salt must not be empty.");
printUsage();
return;
} else {
System.out.println("Using salt: " + salt);
}
if (payload == null || payload.length() == 0) {
System.out.println("Error: Payload must not be empty.");
printUsage();
return;
}
System.out.println("Using payload: " + payload);
String encData = encrypt(payload, salt);
if (encData != null) {
System.out.println("Encrypted & encoded data: " + encData);
System.out.println("Decrypted data (to verify): " + decrypt(encData, salt));
String xoredFI = encryptValueToXor(fi, salt);
System.out.println("Xored FI: " + xoredFI);
System.out.println("Xored FI (reversed): " + decryptXoredValue(xoredFI, salt));
}
}
public static byte[] getRandomNonce(int numBytes) {
byte[] nonce = new byte[numBytes];
new SecureRandom().nextBytes(nonce);
return nonce;
}
/**
* Generate xored output of a using key.
*
* @param a
* @param key
* @return
*/
static byte[] xor(byte[] a, byte[] key) {
byte[] out = new byte[a.length];
for (int i = 0; i < a.length; i++) {
out[i] = (byte) (a[i] ^ key[i%key.length]);
}
return out;
}
static String decryptXoredValue(String xoredValue, String key) {
return new String(xor(Base64.decode(xoredValue.getBytes(), Base64.NO_WRAP), key.getBytes()));
}
static String encryptValueToXor(String value, String key) {
return new String(Base64.encode(xor(value.getBytes(), key.getBytes()), Base64.NO_WRAP));
}
}