Security
To verify that data sent from your Front Connector is legitimate, validate the signature before accepting it into your system.
The requests made to your server will include 2 headers: X-Front-Signature
and X-Front-Request-Timestamp
. First, check that the timestamp says the request was made recently in order to prevent replay attacks. We recommend 5 minutes as the maximum time before rejecting a message.
- Retrieve the
X-Front-Request-Timestamp
header on the HTTP request and the body of the request. - Concatenate the timestamp and the JSON stringified body of the request to form a string. Use a colon as the delimiter between the two elements.
GET and DELETE requests return a string with the value "undefined" as the body
- Using HMAC SHA256, hash the above string, using your Channel Type Secret Key as the key.
This should match the X-Front-Signature
header. If it does not, you should not trust this message. See the following TypeScript example for how to validate a message and generate a token.
Sample application
The Auth file of our Basic application object handler sample application demonstrates verifying that a request is coming from Front.
/**
* Validate that the request is from Front
*
* Concatenate the request body + timestamp, delimited with a colon.
* Take SHA256 HMAC and validate it's equal to the X-Front-Signature
* In the Request Header
*
* In production, we recommend loading Channel Type secret from a configuration file.
*
* @param {Request} req: Incoming request from Front.
* @param {string} channelTypeSecret: Secret Key of your Channel Type. Was given to you when your Channel Type was created.
* @returns {boolean} Boolean denoting whether or not request is from Front.
*/
function isRequestFromFront(req: Request, channelTypeSecret: string): boolean {
const timestamp = req.headers['x-front-request-timestamp'];
const rawBody = JSON.stringify(req.body);
// GET and DELETE requests send a string with the value "undefined" as the body
const baseString = `${timestamp}:${rawBody}`;
const hmac = crypto.createHmac('sha256', channelTypeSecret)
.update(baseString)
.digest('base64');
return hmac === req.headers['x-front-signature'];
}
/**
* Creates a JSON web token
*
* jwt is your preferred JWT library found at https://jwt.io/
* In production, we recommend loading Channel Type ID and secret from a configuration file.
*
* @param {string} channelTypeId: ID of your Channel Type. Was given to you when your Channel Type was created.
* @param {string} channelTypeSecret: Secret Key of your Channel Type. Was given to you when your Channel Type was created.
* @param {number} channelId: Incoming request from Front.
* @returns {string} Signed JSON web token
*/
function buildToken(channelTypeId: string, channelTypeSecret: string, channelId: number) {
// Mark token to expire within 5 seconds for security (small usage window)
const exp = Math.floor(new Date().valueOf() / 1000) + 5;
// Can be any string, can be used by your system to identify tokens
const jsonWebTokenId = 'abc123';
const payload = {
iss: channelTypeId,
jti: jsonWebTokenId,
sub: channelId,
exp
};
return jwt.sign(payload, channelTypeSecret);
}
Updated about 1 month ago