Security
Since order history is private information, all requests must be authenticated. In the traditional method where you are using a UI server, you can simply pass your clientKey in the header of the request.
If you are using Storefront or other front-end implementation, then you will need to generate a securedPayload
to authenticate the user.
A private (authenticated with client key) and public endpoint exists for all retrieval APIs.
If you are passing the data through a UI server and authenticating with a clientKey
, reference the Private Retrieval Endpoints.
If you are letting the front-end directly request data from cloud, then read the next section on Generating a Secured Payload, and reference the Public Retrieval Endpoints.
{
"userId": "626f6240676d61696c2e636f6d",
"loyaltyId": "34313633353739353130",
"expiration": 1504720404379
}
You must include at least one of userId
or loyaltyId
, and an expiration timestamp. The securedPayload
will no longer work after the set expiration time.
Here are the steps for generating the securedPayload
from the plain text message. We can provide a library that implements the process.
initialValueRaw = PRNG(128-bit)initialValue = Base64Encode(initialValueRaw)
keyEncryption = PBKDF2WithHmacSHA1(--clientKey--, "--customerId--1Encryption", 5000 iterations)keyMAC = PBKDF2WithHmacSHA1(–clientKey–, “–customerId–1MessageAuthenticationCode”, 5000 iterations)
cipherTextRaw = AES-CBC-PKCS7Padding(keyEncryption, initialValueRaw, plainTextMessage)
cipherText = Base64Encode(cipherTextRaw)
messageAuthenticationCodeRaw = HmacSHA256(keyMAC, cipherTextRaw + initialValueRaw)messageAuthenticationCode = Base64Encode(messageAuthenticationCodeRaw)
A new initial value must be generated for each new securedPayload
generated. The encryption key and MAC key need to be different as well, so different filler text is added to each.
Failure to do so WILL make the usage of this token insecure.
You will then need to send the securedPayload
in the following format to the front-end, which it can then use to retrieve data as needed.
{
"securedPayload": {
"messageAuthenticationCode": "fJ7lXBJgJdF9K1m+RPVLZlc9ORYDbI=",
"initialValue": "vDn1PwcE6KLyHtSWf0ASrQ==",
"cipherText": "j2H7BnJTbA+T+yhDbC1P+/zhPvRAT5NLjwOQhTltonEnhoxthaPRwxfD30r\nugtQ5latIr+j4bLawHpsDbC1P+/zhPvR7DHFd/9GcZeCCZyeMygOzSN2ht+nbgSb3qLqM8O4Hm4wTFNR4IGgf08ifG5norc15Zmmunks7\n2tjfUHkg6hZpYnOpLdo="
}
}
curl -X POST \
--header 'Authorization: --clientKey--' \
--H 'Content-Type: application/json' \
--data '{…}'
"https://--customerId--.groupbycloud.com/orders/v1/securityToken"
{
"userId": "626f6240676d61696c2e636f6d",
"loyaltyId": "34313633353739353130",
"expirationDeltaMillis": 10000,
}
The expirationDeltaMillis
is optional, the default is 8 hours.
{
"result": {
"cipherText": "lFSe/4ryvXEI2afJ2oPVCr7SGbu+5k5U4LShbh86JFdnrgcIWmW8FRpeuu3WDEItWP3LexH4CwyhTEzyHNxpyEihXUbpzlZPIGjighxjXUbOMqvQRzPGTxbu68V4ySNthdE/U0Tt9RAubxHsCUz9WNhhZdUdfoHvnxu7WHCkuJY=",
"initialValue": "tnRtL9kxDsIwMAtxQKiMKQ==",
"messageAuthenticationCode": "fWRfU86osO5Tsl24m6OFCDn7voFho+aQOr6sCdhkKzU="
},
"status": {
"code": 200,
"internalCode": 0,
"message": "OK",
"additionalInfo": null,
"serverTimestamp": 1523903745000
}
}
curl -X POST \
--header 'Authorization: --clientKey--' \
--H 'Content-Type: application/json' \
--data '{…}'
"https://--customerId--.groupbycloud.com/orders/v1/securityToken/decrypt"
{
"cipherText": "lFSe/4ryvXEI2afJ2oPVCr7SGbu+5k5U4LShbh86JFdnrgcIWmW8FRpeuu3WDEItWP3LexH4CwyhTEzyHNxpyEihXUbpzlZPIGjighxjXUbOMqvQRzPGTxbu68V4ySNthdE/U0Tt9RAubxHsCUz9WNhhZdUdfoHvnxu7WHCkuJY=",
"initialValue": "tnRtL9kxDsIwMAtxQKiMKQ==",
"messageAuthenticationCode": "fWRfU86osO5Tsl24m6OFCDn7voFho+aQOr6sCdhkKzU="
}
{
"result": {
"loyaltyId": "eecd88f5a7c530be7923ccaac711767847a6da7f3a6ea0d4dae9db4552bdb4ad",
"userId": "1e5847500d76893b7eeec35436b6dd4f22ce25736d3451ec550c3314c4b3ac3c",
"expiration": 1524671390302
},
"status": {
"code": 200,
"internalCode": 0,
"message": "OK",
"additionalInfo": null,
"serverTimestamp": 1524674814030
}
}
When generating the token itself, you need to use an absolute expiration time.The test endpoint uses expirationDeltaMillis
to make testing easier.