Security & Compliance
Security
Card linking leverages RESTful APIs containing different levels of authentication and encryption to secure information being passed between Skipify and Issuers:
OAuth 2.0 Client Credential
API requests are secured by passing the access token fetched from the OAuth2.0 Client Credential flow between the backend services.
- The OAuth Client is the Skipify Server running the card linking flow
- The OAuth Authorization Server is run by the issuer to protect the APIs
- The client credentials are shared by the issuer to Skipify Administrators in a secure channel during the initial setup and rotated periodically at agreed upon intervals.
JSON Web Signature(JWS)
Used to sign data.
Note
To ensure data integrity, every request will also contain signed JWS headers for verification purposes.
- Skipify generates an RSA 2048 public/private key to sign the requests
- The public key is shared with the Issuer administrator in a secure channel during initial setup and rotated periodically at agreed upon intervals. (This may also be shared using a well-known URL)
- Each request is signed using the private key
- The Signature is added to the header of the request with the format defined in JWS RFC 7515 as
(BASE64URL(UTF8(JWS Protected Header)) || '.' || BASE64URL(JWS Payload) || '.' || BASE64URL(JWS Signature))
- Issuers can verify the integrity of the request payload using the Skipify public key
JSON Web Encryption (JWE)
PII fields are encrypted using JWE.
Request fields from Skipify are encrypted using the following attributes:
- PII fields will be encrypted using RFC-7516 JWE
- Skipify will use the RSA-OAEP-256 key encryption algorithm
- Skipify will use the A256GCM content encryption algorithm
Issuers will share RSA 2048 certificates with Skipify on well-known URLs
JWE encryption shall be completed by the Issuer on the PII fields of the Response as follows:
- PII fields shall be encrypted using RFC-7516 JWE
- Issuers shall use the RSA-OAEP-256 key encryption algorithm
- Issuers shall use the A256GCM content encryption algorithm
Skipify will share RSA 2048 certificates with the Issuer on well-known URLs
Mutual TLS
Mutual TLS (mTLS) is a security protocol that enhances the standard Transport Layer Security (TLS) by providing two-way authentication. In a standard TLS setup, only the server's identity is verified by the client. However, with mTLS, both the client and the server authenticate each other, ensuring that both parties involved in the communication are verified and trusted.
To implement mTLS, issuers should:
- Obtain Certificates: Acquire a valid certificate from a trusted Certificate Authority (CA) for the server.
- Exchange public certificates: Skipify will share the public certificate of the client and the issuer will share the public certificate of the server.
- Configure Servers and Clients: Set up your servers and clients to use mTLS.
ID Token (JWT)
The ID Token represents a successful user authentication during the card linking flow. The ID Token is signed using a Skipify RSA 2048 Private Key and contains the parameters used during the step-up process as shown below:
Claim | Description | Type | Validations | Example |
---|---|---|---|---|
iss | Issuer for the id token | string | always “skipify” | “skipify” |
sub | Issuer defined user ID | string | “123456” | |
skipify_account_id | Account ID managed by Skipify for the shopper | string | UUIDV4 | “1111-1111-1111-1111” |
aud | A valid audience id the token is intended | string | Issuer name without spaces | “issuer1” or ” issuer2” |
exp | Time in epoch till id token is valid | number | unix timestamp in seconds | 1657890876 |
iat | Time in epoch when id token was issued | number | unix timestamp in seconds | 1657890876 |
jti | Random id for id token uniqueness | “g4ys-8909-iuyws-961” | ||
auth_time | Time in epoch of the shopper authentication | number | unix timestamp in seconds | 1657890876 |
auth_iss | Represents entity which performed shopper authentication. | string | ENUM=[“issuer“, “skipify”] | “skipify” |
amr | Methods used by entity for shopper authentication. | string | ENUM=[“email_otp”, “sms_otp”] | email_otp |
amr_attempts | Number of attempts shopper tried for successful authentication | number | Range: 0-9 | 2 |
phone_number | Hashed phone value on which authentication has a been performed. Populated only if amr is sms_otp. (If issuer is completing the step-up will send this value on “Verify Customer API” response) | string | GenerateIdentityHash(phone) | “chbwchwcbd9q7q” |
Hashed email value on which authentication has a been performed. Populated only if amr is email_otp. (If issuer is completing the step-up will send this value on “Verify Customer API” response) | string | GenerateIdentityHash(email) | “cvhsqiudsioqscw“ |
Identity Hash
generateIdentityHash(String identity) {
currentHash = identity.toLowerCase();
// hash for 1000 times
for (int i = 0; i < 1000; ++i) {
currentHash = SHA256(currentHash);
}
return SHA256(SHA256(identity.toLowerCase()) + currentHash);
}
Compliance
Skipify’s platform is certified as PCI compliant (Level 1). Data that is shared by Issuers is stored and encrypted in the Skipify Vault. This includes:
- PII data
- Issuer payment credentials (PANs and tokens)
Skipify is SOC2 Type 1 certified ensuring that we maintain the highest standards for financial reporting.
Updated about 1 month ago