Strong Customer Authentication (SCA) is a new European regulatory requirement as part of the second Payment Services Directive (PSD2) for authenticating online payments and make them more secure.
There are some actions such as funding a transfer from your balance or viewing the statement that require SCA within the UK and EEA.
SCA builds additional authentication by asking two of the following three elements:
- Something the customer knows.
- Something the customer has.
- Something the customer is.
If you don’t integrate with it and make a request to an SCA protected endpoint, your request will be rejected.
Simple SCA implementation:
API Server side
- Daily random API Keys are generated for each register entity.
- Each register entity API KEY is RSA encrypted with the API server public key and saved in the central database and is associated with the unique ID of the registered entity.
- The new entity API Keys are saved also in an ApiKeyCache (memmory only) unencrypted.
- The entities public keys are also loaded in a CertificateCache so they are easily accesible.
Each day at a given reset time the new API key is delivered to each entity in a secure message, encrypted (RSA) using the public key of each entity. The message is delivered to an entity by using the old (previous day) API key such that the entity can process and extract the new API key using the old API key.
Client entity side
Client entity POST structure:
Mandatory Header fields:
sender = entity identifier (the unique id assigned to the entity when was registered or an official identification: BIC, fiscal number etc.)
msgId = message reference
certificate = used certificate serial number (cert.getSerialNumber().toString()) (Optional, indicates what client entity certificate is used, if none quoted the default one assigned by central system to the sender is used.)
certificate_issuer = used certificate issuer name (cert.getIssuerX500Principal().toString())
Authorization = signature of (sender API key+msgId+yyyyMMdd+HHmm)
API Server verification of client entity requests:
- Check if sender is an Authorized entity by verifying that corresponds to an active entity identifier.
- Validate Authorization token by checking it with a signature verification function(signature, content, certificate):
2.1 First candidate
- as signature the value from the received “Authorization” header variable
- as content API key of sender + msgId + yyyyMMdd+HHmm
- as certificate certificate use the certificate specified by certificate serial number and issuer or default participant trusted certificate.
2.2 Second candidate
- as signature the value from the received “Authorization” header variable
- as content API key of sender + msgId + yyyyMMdd+HHmm – 1 minute
- as certificate certificate use the certificate specified by certificate serial number and issuer or default participant trusted certificate.
2.3 Third candidate
- as signature the value from the received “Authorization” header variable
- as content API key of sender + msgId + yyyyMMdd+HHmm + 1 minute
- as certificate certificate use the certificate specified by certificate serial number and issuer or default participant trusted certificate.
If any of the candidates is verified then accept POST call as a valid call.
With above we ensure full SCA compliance:
- something the customer knows -> the API key of the day
- something the customer has -> the private key
- something the customer is -> the sender entity identifier
By using also the time indicator yyyyMMdd+HHmm we have a 2 minute replay attack window.
Reply attack can be done effectively only if a valid, intercepted GET header, is used for a POST.
This has to be done in this 2 min window that can be configurable to be shorter.
Reply attack by using a valid, intercepted POST header is not effective due to the duplicate message validation checks (msgId unique per business day).
API server to client entity communication
This is the case of a webhook call performed by the API server, to POST some asynchronous response to the client entity.
API server POST structure:
Mandatory Header fields:
sender = API server unique identification
msgId = message reference
certificate = used certificate serial number (cert.getSerialNumber().toString()) (optional, indicates what API server certificate is used, if none quoted the default one assigned by central system is used)
certificate_issuer = used certificate issuer name (cert.getIssuerX500Principal().toString())
Authorization = signature of (receiver APIKEY+msgId+yyyyMMdd+HHmm)
Client entity verification:
- Check if sender is an Authorized API server by verifying that corresponds to the API server unique identification.
- Validate Authorization token by checking it with a signature verification function(signature, content, certificate):
2.1 First candidate
- as signature the value from the received “Authorization” header variable
- as content APIKEY of participant + msgId + yyyyMMdd+HHmm
- as certificate certificate use the certificate specified by certificate serial number and issuer or default API server trusted certificate.
2.2 Second candidate
- as signature the value from the received “Authorization” header variable
- as content APIKEY of participant + msgId + yyyyMMdd+HHmm – 1 minute
- as certificate certificate use the certificate specified by certificate serial number and issuer or default API server trusted certificate.
2.3 Third candidate
- as signature the value from the received “Authorization” header variable
- as content APIKEY of participant + msgId + yyyyMMdd+HHmm + 1 minute
- as certificate certificate use the certificate specified by certificate serial number and issuer or default API server trusted certificate.
If any of the candidates is verified then accept POST call as a valid call.
With above we ensure full SCA compliance:
- something the customer knows -> the API_KEY of the day
- something the customer has -> the private key
- something the customer is -> the API server unique identification
By using also the time indicator yyyyMMdd+HHmm we have a 2 minute replay attack window.
Reply attack can be done effectively only if a valid, intercepted GET header, is used for a POST.
This has to be done in this 2 min window that can be configurable to be shorter.
Reply attack by using a valid, intercepted POST header is not effective due to the duplicate message validation checks (msgId unique per business day).
Final note:
Note that I do not mention here anything about the body of the calls. The whole above SCA implementation is based only on header fields. To ensure maximum security the body of the request should be ancrypted and signed using the same certificates used in the SCA operations. This way a security cross-check can be done between security elements in the header and the body of the request.