Security
Learn how to securely call APIs on PAPE
Security Overview
For most of your integration with PAPE, your financial institution will be the one calling APIs on PAPE.
PAPE principally uses OAUTH2
for authenticcation and authorization of all API endpoints.
Other more sensitive endpoints will need additional security with the use of digital signatures. These digital signatures are generated from your financial institution’s public keys.
For all endpoints that require RSA digital signatures, note that the public key is always safe to share — other people need it to identify your account and verify that you authorized a transaction. It’s like an email address. The private key, however, is private information that proves you own — and gives you access to — your account. It’s like a password, and you should never share it with anyone.
You can generate a RSA 2048 Bits Keypair from RSA Key Generator, or you can generate it yourself with openssl.
Get Authorization Token
PAPE requires that every request to get privileged data is authenticated, and uses OAUTH2 as the Authentication layer for all API calls.
PAPE uses a combination of the OAUTH2 Authorization Grant Flow for frontend applications, and OAUTH2 Password Grant for backend applications.
To generate authentication tokens for your backend application, you have to make the following request with the credentials(username and password) that would have been shared with you when your financial institution was onboarded:
curl --request POST \
--url 'https://id.dev.projectwhite.io/auth/realms/projectwhite/protocol/openid-connect/token' \
--data-urlencode grant_type=password \
--data-urlencode username=user@example.com \
--data-urlencode password=pwd \
--data-urlencode 'client_id=projectwhite' \
--data-urlencode client_secret=
Response
If all goes well, you’ll receive an HTTP 200 response with a payload containing access_token, refresh_token, id_token, token_type, and expires_in values:
{
"access_token": "eyJz93a...k4laUWw",
"refresh_token": "GEbRxBN...edjnXbL",
"id_token": "eyJ0XAi...4faeEoQ",
"token_type": "Bearer",
"expires_in": 36000
}
Call API
To call our PAPE APIs, the application must pass the retrieved Access Token as a Bearer token in the Authorization header of your HTTP request.
curl --request GET \
--url 'https://apis-alpha.dev.projectwhite.io/payment-gateways' \
--header 'authorization: Bearer ACCESS_TOKEN' \
--header 'content-type: application/json'
Refresh tokens
You have already received a Refresh Token if you’ve been following this tutorial and completed the following:
Generated an access_token and a refresh_token from Authorization
Added logic to persist the acces_token and refresh_token.
You can use the Refresh Token to get a new Access Token. Usually, a user will need a new Access Token only after the previous one expires or when gaining access to a new resource for the first time. It’s bad practice to call the endpoint to get a new Access Token every time you call an API, and Auth0 maintains rate limits that will throttle the amount of requests to the endpoint that can be executed using the same token from the same IP.
To refresh your token, make a POST request to the /openid-connect/token endpoint in the Authentication API, using grant_type=refresh_token.
curl --request POST \
--url 'https://id.dev.projectwhite.io/auth/realms/projectwhite/protocol/openid-connect/token' \
--header 'content-type: application/x-www-form-urlencoded' \
--data-urlencode grant_type=refresh_token \
--data-urlencode 'client_id=projectwhite' \
--data-urlencode refresh_token=YOUR_REFRESH_TOKEN
Response
If all goes well, you’ll receive an HTTP 200 response with a payload containing a new access_token, its lifetime in seconds (expires_in), granted scope values, and token_type.
{
"access_token": "eyJ...MoQ",
"expires_in": 86400,
"scope": "openid offline_access",
"token_type": "Bearer"
}
Digital Signatures
Certain endpoints will require a digital signature attached as a X-PAPE-SIGNATURE-BASE64
header.
The digital signature algorithm to use will be RSAwithSHA256
. You should figure out how to sign payloads with the RSAwithSHA256 on your programming platform. For platforms that don’t directly support RSAwithSHA256, you should hash your payload first with Sha256
, and sign with PKCS1v15
.
The payload to sign will be:
payloadToSign = urlWithoutHost + rawBody
You should sign your payload with the private key you generated during the onboarding process. PAPE will use your supplied public key to verify the validity of your API calls.
Sample RSAwithSHA256 code in Python
#!/usr/bin/python
import sys
from Crypto.PublicKey import RSA
from Crypto.Signature import PKCS1_v1_5 as Signature_pkcs1_v1_5
from Crypto.Hash import SHA256
import base64
import configparser
import requests
import json
from urllib.parse import urlparse
parsedUrl = urlparse(sys.argv[2])
# our signing payload includes the path of the url, and query
uriWithoutHost = parsedUrl.path
payload = (uriWithoutHost+sys.argv[3]).encode('utf-8')
filename = "private-key.priv"
with open(filename) as f:
key = f.read()
privkey = RSA.importKey(key)
signer = Signature_pkcs1_v1_5.new(privkey)
digest = SHA256.new()
digest.update(payload)
signature = signer.sign(digest)
auth_signature = base64.b64encode(signature)
print("auth_signature: ", auth_signature)