Managing Key Sets
When an Approov account is created it is allocated a random secret key that is used by default for Approov token signing or encryption. This provides Approov tokens signed using the HS256 algorithm (or A256GCMKW if an encrypted JWE is selected). The HS256 verification uses the symmetric 512-bit account secret key, which needs to be made available to the backend API, to check the validity of the token.
Key sets allow additional keys to be added to an Approov account, which can then be used to sign or encrypt Approov tokens for specific API domains. This allows the use of different keys for different API domains if required. Moreover, key sets also allow access to a much richer set of signing algorithms. In particular, asymmetric signing algorithms (such as RS256) allow the validity of a token to be verified using only the public key. This avoids the security risks associated with needing to add a symmetric key to the API backend (such as with HS256), which could allow valid Approov tokens to be generated if it were to be compromised.
Key sets may also be used by the Custom JWTs feature too.
Adding a New Key
A new, randomly generated, keyset key can be added as follows. You can specify the name which you wish to give the key and the algorithm used for signing and encryption, as follows:
approov keyset -kid your-key -add RS256
In this case a new key named your-key is generated for use with the RS256 signing algorithm. A random RSA private key is generated by Approov and added to your account.
The following signing algorithm are available:
HS256,HS384,HS512: These HMAC signing methods use a symmetric key, with differing hashing algorithms. If you use these then you must be careful to secure the symmetric key used to verify them, since it can also be used to create fresh valid tokens.RS256,RS384,RS512: These useRSASSA-PKCS1-v1_5asymmetric cryptography, with differing hashing algorithms. The Approov tokens are signed with the private key which can be verified in the backend API using the associated public key.PS256,PS384,PS512: These useRSASSA-PSSasymmetric cryptography, with differing hashing algorithms. The Approov tokens are signed with the private key which can be verified in the backend API using the associated public key. The difference fromRSASSA-PKCS1-v1_5is that there is a random element to the signature, which may be advantageous to differentiate Approov tokens if many are being generated with the same expiry timestamp.ES256,ES384,ES512: These useECDSAasymmetric cryptography, with differing hashing algorithms.ES256uses curveP-256(secp256r1),ES384usesP-384(secp384r1), andES512usesP-521(secp521r1). The Approov tokens are signed with the private key which can be verified in the backend API using the associated public key.A256GCMKW: This is the only supported encryption algorithm to generate aJWErather than aJWS. This uses a symmetric key, so if you use this then you must be careful to secure the symmetric key since not only can it be used to decrypt and verify tokens, it can also be used to encrypt fresh valid tokens.
This article provides a good overview of the different options.
Once a new keyset key has been added, it can be referenced by the -keySetKID option for Keyset Key API Addition.
It is also possible to specify a key length override parameter when specifying an algorithm that uses RSA (RS256, RS384, RS512, PS256, PS384, PS512) or symmetric keys (HS256, HS384, HS512, A256GCMKW).
approov keyset -add RS256 -keyLength 4096
The default length for an RSA key is 2048 bits, but it may be overridden to 1024 or 4096 bits. The default length for a symmetric key is 256 bits, but may be overridden to 128 or 512 bits.
Note also that in this case no kid parameter was specified. If this is not provided then the key is named using a simple incrementing counter for the account.
The Backend API Quickstarts are written assuming the default signing algorithm of HS256 and that the account secret key is being used. You will need to make small alterations to these to support different algorithms and the different manner in which public keys are obtained for keyset keys.
It is only possible to have a maximum of 10 keyset keys at any one time.
Listing Keys
The current keys in the keyset can be listed as follows:
approov keyset -list
The algorithm associated with each key is provided, along with a list of any apis that the key is currently associated with for token signing.
1 key:
your-key alg:RS256 apis:your.domain
A given key may be associated with multiple different API domains.
Removing Keys
A keyset key can be removed as follows:
approov keyset -kid your-key -remove
Note that you need an admin role to remove a key from the keyset and you will need to provide confirmation. Furthermore, you can only remove a key if it is not in use on a particular API domain. If it is in use, you first need to Remove the API Domains or change them to use a different key before the key can be deleted. This needs to be done with care as it may have an immediate impact on your production apps.
Getting Public Key PEM
It is possible to obtain the PEM file for a specific key within the keyset. This is the encoded form of the public key specified by the -kid option, in PKIX ASN.1 DER format. The encoded public key is a SubjectPublicKeyInfo structure, as defined in RFC5280, section 4.1. Obtain the PEM as follows:
approov keyset -kid your-key -getPEM your-key.pem
The contents of the your-key.pem file will be something like the following:
-----BEGIN PUBLIC KEY-----
MIGfMA0GCSqGSIb3DQEBAQU...
-----END PUBLIC KEY-----
Various external tools and API gateways support this format to allow the checking of Approov tokens.
It is only possible to obtain a PEM for RSA and ECDSA key types, that use asymmetric cryptography. The command generates a PEM containing only the public key. This enables token verification but not token creation which means public disclosure of the PEM file does not enable a path to unauthenticated access to your API. It does however mean that external parties can determine the validity of Approov tokens which is undesirable. Depending on your security posture and if this does happen, you may still want to change the token secret for the associated APIs.
By default the PEM is obtained from the pass key set. The equivalent entry from the fail key set can be obtained by adding the -type fail option, as described in Pass and Fail Key Sets.
Getting Keyset JWKS
It is possible to obtain the JSON Web Key Set for all keys in the keyset as follows:
approov keyset -getJWKS keys.jwks
The contents of the keys.jwks will be something like the following:
{
"keys": [
{
"alg": "RS256",
"e": "AQAB",
"kid": "your-key",
"kty": "RSA",
"n": "4NhUHZSl5ws8...",
"use": "sig"
}
]
}
Note that you need an admin role to get the JWKS for the key set. This is because this will also obtain any symmetric keys in the key set, and these require rigorous security since they allow creation as well as verification of Approov tokens. For asymmetric RSA and ECDSA keys, only the public key is obtained.
By default the JWKS is obtained from the pass key set. The equivalent entries from the fail key set can be obtained by adding the -type fail option, as described in Pass and Fail Key Sets.
Remember that the keys encoded in a JWKS are in base64url rather than base64 encoding. The provided JWKS keys do not include the optional x5c and x5t claims.
Using JWKS URI Endpoint
It is possible to make the public keys in a keyset available as a JSON Web Key Set file on a URI. This public key material can then accessed and cached by your verifying server without the need to import a fixed set of public keys. This has the advantage that key rotations can be handled automatically. Note that only public keys, never symmetric keys, are provided on this endpoint.
By default the JWKS URI is not enabled. You can enable it as follows:
approov keyset -setJWKSURI on
Note that you need an admin role and will need to make a confirmation. This will output something like the following:
WARNING: updating the JWKS URI policy will have an immediate impact on your apps in production
ATTENTION: If you wish to continue then please type YES and return: YES
JWKS URI policy was updated successfully
JWKS URI: https://admin-something.approovr.io/keyset/your-account/jwks.json
You can provide this URI to configure your Approov token verification. There will be a short propagation delay of up to 30 seconds before keyset changes are reflected in the URI version. Note that only public keys are made available, so it is not possible to use this if you are using a symmetric key for signing tokens. Thus you cannot use this for the default HS256 signing algorithm.
You can always obtain the JWKS URI status and URI with:
approov keyset -getJWKSURI
Remember that the keys encoded in a JWKS are in base64url rather than base64 encoding. The provided JWKS keys do not include the optional x5c and x5t claims.
If you wish to rotate the keys being used for signing then you can do this by adding a new keyset key and setting the relevant API domains to use this new key. Keep the previous key in keyset (and therefore available by the JWKS URI) for some time until all Approov tokens using that key will have expired.
Importing Keys
It is possible to import a JSON Web Key into the keyset as follows. Imagine you have a file byok.jwk with the following content:
{
"alg": "RS256",
"use": "sig",
"d": "FumDxNCs...",
"dp": "mUxVEADBN...",
"dq": "Yv9xjIj5vOo...",
"e": "AQAB",
"kid": "byok",
"kty": "RSA",
"n": "05yGbvzgIobbtaeJ...",
"p": "9_NNlMTz_S5jcxORGz...",
"q": "2ns2LBc5-1f3m7iI...",
"qi": "TxLIVbqDsTvmhTgmR..."
}
Import it as follows:
approov keyset -import byok.jwk
A kid claim must be present and not be the same as any existing key in the key set. The alg and use claims must also be present and be consistent with algorithms supported by Approov, or else the import request will be rejected.
Note that you need an admin role to import a private key. For an asymmetric key, once the private key is imported it is not possible to export it again. Only the corresponding public key may be exported. Extreme care must be taken to secure the file holding the JWK since it contains the private key and can thus be used to create valid Approov tokens.
If you have multiple Approov accounts, then the importing feature allows you to Bring Your Own Key (BYOK) and share them between multiple accounts. This allows Approov tokens generated by different accounts to use the same Approov protected backend API using a common key. In this case the private key should be generated externally to Approov and then imported into the required accounts. Alternatively, you could make the backend API compatible with multiple different key IDs that it can lookup from the token header.
Pass and Fail Key Sets
Every key set operation described above acts on the account's pass key set. Whenever you add or import a key, Approov transparently mirrors the operation onto a corresponding fail key set: a matching entry is created that shares the same key identifier (kid) and the same signing or encryption algorithm, but uses entirely separate key material. The two key sets therefore always contain identical entries, differing only in the underlying keys.
When Approov issues a token for an attestation it signs or encrypts it using the key from the pass key set if the attestation passed, or the equivalent key from the fail key set if it failed. In both cases the result is a genuine Approov token, correctly signed or encrypted, and carrying an arc claim that records the reason for the outcome.
For many integrations you only need to care about passing attestations, which is the simplest approach: verify each token against the pass key set and reject the request if it is not valid. In this case the fail key set can be ignored entirely.
Some deployments, however, want to account for every request reaching the API, for example to feed attestation results into a SIEM or other analytics platform for live or later analysis. To do this the backend decodes and interprets the contents of every token, and in particular the arc claim, to understand why each request passed or failed. In this situation the fail key set becomes important, because checking a token against both key sets lets the backend distinguish three cases:
- the token verifies against the pass key set: it is a genuine passing token minted by Approov;
- the token verifies against the fail key set: it is a genuine failing token minted by Approov, and its
arcclaim can be trusted to explain the reason for the failure; - the token verifies against neither key set: it was not minted by Approov (for example it was forged by an attacker signing with a random secret), so none of its contents can be trusted.
A token that verifies against neither key set should be rejected immediately, and none of its contents relied upon. In particular the arc claim of such a token is fabricated and must not be used to reason about the cause of a failure, since only Approov generated tokens carry a trustworthy arc.
To support this, the key set retrieval commands accept a -type option to select which key set to obtain. The default, -type pass, retrieves the pass key set, and -type fail retrieves the fail key set. For example, to obtain the public key PEM of the fail key set entry for your-key:
approov keyset -kid your-key -getPEM your-key-fail.pem -type fail
Similarly, the complete fail key set can be obtained as a JWKS:
approov keyset -getJWKS fail-keys.jwks -type fail
The backend configuration obtained with approov secret -getBackendConfig also includes both the pass and fail key sets, along with the API domains they apply to, which can be convenient when configuring a backend that needs to verify against both.