Configure HSM-Issued JWTs
In its default configuration, a TSB instance is bound to a single HSM partition:
the partition name and credentials are set in application-local.yml, and every request is executed on that partition (1:1).
With JSON Web Tokens (JWT), a single TSB instance serves multiple partitions (1:N).
The partition credentials are not configured in the TSB; they are contained in the JWT, encrypted.
Each JWT grants access to one partition, or to one sub-role of a partition.
The client sends its JWT in the Authorization header of each request,
and the TSB executes the request on the partition that the JWT belongs to:
curl -H "Authorization: Bearer <JWT>" https://<tsb-host>:8080/v1/keystore/statistics
The JWTs are issued and signed by the Primus HSM (firmware v3.2.11 or later). The TSB accepts only JWTs whose signature it can verify with the certificate of the issuing HSM. Clients with different JWTs share the TSB instance but can only access their own partition.
Prerequisites
This guide assumes that:
- You have installed the TSB on-premise.
- Your Master HSM runs firmware v3.2.11 or later.
- The Root Key Store of the Master HSM was set up with firmware v3.2.8 or later. Only then does it contain the Issuing Key that signs the JWTs.
- A partition exists for each client that receives a JWT.
- You have Security Officer access to the Master HSM and a USB drive or WebDAV.
A firmware update does not add the Issuing Key to an existing Root Key Store. If the Root Key Store was set up with a firmware version earlier than v3.2.8, update the firmware and set up the Root Key Store again as Security Officer:
- UI
- Console
System ➜ Root Key Element ➜ Setup Root Key Store
hsm_sec_setup_rks
This replaces the Device, Audit, and Issuing Keys. Existing Partition Attestation and Timestamp Keys keep their valid certificate chain. JWTs issued with a previous Issuing Key must be issued again. For details, see Section 6.1 "Initialize Root Key Store, Device Intermediate Key and Audit Key" of the Primus HSM User Guide.
Create the JWTs on the HSM
For details on the following steps, see Section 5.5.7 "Create JSON Web Tokens (JWT) for TSB" of the Primus HSM User Guide.
1. Export the Issuing Key Certificate
Export the device state of the Master HSM:
- UI
- Console
System ➜ Diagnostics Security ➜ Export State
hsm_sec_device_diag
The export contains issuing.cert, the PEM-encoded certificate chain of the Issuing Key, device, and Securosys root certificates.
The TSB uses this file to verify the signature of the JWTs.
2. Write the JWT Input File
Create one XML input file per partition, named <partitionName>.jconfig.
Minimal Configuration
The following file requests a JWT for the unrestricted role of a partition, valid for 30 days. Replace the fields with the values for your setup:
<?xml version="1.0" encoding="UTF-8"?>
<jwts>
<user_name>PARTITION_NAME</user_name>
<jwt>
<hostname port="2300">hsm-api.example.com</hostname>
<validity type="days">30</validity>
<service_name>my_tsb_service</service_name>
<encryption_password>secret_encryption_password</encryption_password>
</jwt>
</jwts>
With this configuration, the JWT is valid immediately and the TSB does not store the partition access in its database.
A Partition Security Officer (PSO) can also create JWTs;
in this case the input file contains only the XML header and a single <jwt> element.
JWTs can also be created during partition creation by adding <jwt> elements to the *.pconfig file.
Extended Configuration
Example with all optional parameters
The following sample shows all options that are available in the *.jconfig file.
<?xml version="1.0" encoding="UTF-8"?>
<jwts>
<user_name>PARTITION_NAME</user_name>
<jwt setup_password="true|false" role="w|x|r">
<hostname port="2300">ch01-api.cloudshsm.com</hostname>
<start_time>2026.09.30-16:14:00</start_time>
<delay type="seconds">10</delay>
<validity type="seconds">86400</validity>
<service_name>my_tsb_service</service_name>
<encryption_password>secret_encryption_password</encryption_password>
<proxy password="proxy_password">proxy_username</proxy>
<allowed_request_signing_certificate_fingerprints>sha1_fingerprint</allowed_request_signing_certificate_fingerprints>
<allowed_timestamp_signing_certificate_fingerprints>sha1_fingerprint</allowed_timestamp_signing_certificate_fingerprints>
<application_keys enabled="true">
<approver>secret_api_key</approver>
<approverKeyMgmt>secret_api_key</approverKeyMgmt>
<keyMgmt>secret_api_key</keyMgmt>
<keyOps>secret_api_key</keyOps>
<service>secret_api_key</service>
</application_keys>
</jwt>
</jwts>
To issue JWTs for several sub-roles of the same partition, add one <jwt> element per role.
Parameters
| Element | Required | Description |
|---|---|---|
<user_name> | Yes | Name of the partition. Omitted when a Partition Security Officer creates the JWT. |
<jwt> | Yes | One element per JWT. Add one <jwt> element per role. |
<jwt setup_password="true|false"> | No | Default: false, writes the encrypted permanent secret into the JWT. |
<jwt role="w|x|r"> | No | User sub-role of the JWT: Key Manager (w), Key User (x), or Key Auditor (r). Omit or leave empty (role="") for the unrestricted role. |
<hostname port=""> | Yes | Hostname/URL/IP and JCE port of the HSM that the TSB connects to. |
<proxy password=""> | CloudHSM only | Proxy user (element value) and proxy password of the partition. Required only for CloudHSM partitions that are 1) managed through Partition Administration (PSO) and 2) use a self-hosted TSB (instead of TSBaaS). Omit otherwise. |
<start_time> | No | Start of validity, YYYY.MM.DD-hh:mm:ss in UTC. Must not be later than the HSM system time. Default: HSM system time. |
<delay type="seconds|days"> | No | Delay before the JWT becomes valid. Default: 0, type days. |
<validity type="seconds|days"> | Yes | Lifetime of the JWT. Default type: days. |
<service_name> | Yes | Written to the aud claim of the JWT. Must match hsm.accessToken.serviceName. |
<encryption_password> | Yes | Encrypts the partition credentials contained in the JWT. Must match hsm.accessToken.encryptionPassword. |
<allowed_request_signing_certificate_fingerprints> | No | SHA-1 fingerprint of a certificate allowed to sign requests. Can be repeated. Sample: d53216de4921a726eae533801842d1bef07c134c |
<allowed_timestamp_signing_certificate_fingerprints> | No | SHA-1 fingerprint of an allowed timestamp signing certificate. Can be repeated. Sample: d53216de4921a726eae533801842d1bef07c134c |
<application_keys enabled="true|false"> | No | API keys embedded in the JWT: <approver>, <approverKeyMgmt>, <keyMgmt>, <keyOps>, <service>. Each element can be repeated. |
3. Create the JWTs
Copy the *.jconfig files to a USB drive (remove any other *.jconfig files), connect it to the HSM, and run:
- UI
- Console
Roles ➜ User ➜ Credentials ➜ New TSB JWTs
hsm_sec_create_jwt_file
The HSM writes one file per role to the USB drive
and removes the processed *.jconfig file.
Each file contains the JWT that clients send in the Authorization: Bearer header.
Configure the TSB
The TSB configuration package contains the template config-files/application-local-access-token.yml.
-
Copy
issuing.certto theconfig-filesdirectory, which is mounted to/etc/app/configin the container. -
In
application-local-access-token.yml, configure thehsm.accessTokensection:hsm:...accessToken:# Expected audience (aud) of the JWT; must match <service_name> in the *.jconfig fileserviceName: my_tsb_service# Decrypts the partition credentials in the JWT; must match <encryption_password> in the *.jconfig fileencryptionPassword: secret_encryption_password# Set to true if you used `<jwt setup_password="true">` in the *.jconfig file.# If true, the TSB will exchange the Setup Password for the Permanent Secret# and store the Permanent Secret encrypted in the database.onboardPartition: false# Issuing certificate chain exported from the Master HSM; add one entry per issuing HSMhsmIssuerCertificateChain:- type: filevalue: '/etc/app/config/issuing.cert' -
Activate the configuration in
docker-compose.yml:environment:- spring.profiles.active=local-access-token -
Restart the TSB:
docker compose restart
The TSB rejects a JWT if its signature cannot be verified against hsmIssuerCertificateChain,
if the audience does not match, or if it is expired or not yet valid.
Always use the application-local-access-token.yml template.
Do not use the other templates! They are incompatible with an HSM-issued JWT setup.
For example, your application.yml must not contain an HSM host, port, or username (as these are taken from the JWT).