Skip to main content

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.
info

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:

System ➜ Root Key Element ➜ Setup Root Key Store

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:

System ➜ Diagnostics Security ➜ Export State

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:

partition-name.jconfig
<?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.

partition-name.jconfig
<?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​

ElementRequiredDescription
<user_name>YesName of the partition. Omitted when a Partition Security Officer creates the JWT.
<jwt>YesOne element per JWT. Add one <jwt> element per role.
<jwt setup_password="true|false">NoDefault: false, writes the encrypted permanent secret into the JWT.
<jwt role="w|x|r">NoUser 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="">YesHostname/URL/IP and JCE port of the HSM that the TSB connects to.
<proxy password="">CloudHSM onlyProxy 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>NoStart 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">NoDelay before the JWT becomes valid. Default: 0, type days.
<validity type="seconds|days">YesLifetime of the JWT. Default type: days.
<service_name>YesWritten to the aud claim of the JWT. Must match hsm.accessToken.serviceName.
<encryption_password>YesEncrypts the partition credentials contained in the JWT. Must match hsm.accessToken.encryptionPassword.
<allowed_request_signing_certificate_fingerprints>NoSHA-1 fingerprint of a certificate allowed to sign requests. Can be repeated. Sample: d53216de4921a726eae533801842d1bef07c134c
<allowed_timestamp_signing_certificate_fingerprints>NoSHA-1 fingerprint of an allowed timestamp signing certificate. Can be repeated. Sample: d53216de4921a726eae533801842d1bef07c134c
<application_keys enabled="true|false">NoAPI 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:

Roles ➜ User ➜ Credentials ➜ New TSB JWTs

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.

  1. Copy issuing.cert to the config-files directory, which is mounted to /etc/app/config in the container.

  2. In application-local-access-token.yml, configure the hsm.accessToken section:

    hsm:
    ...
    accessToken:

    # Expected audience (aud) of the JWT; must match <service_name> in the *.jconfig file
    serviceName: my_tsb_service

    # Decrypts the partition credentials in the JWT; must match <encryption_password> in the *.jconfig file
    encryptionPassword: 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 HSM
    hsmIssuerCertificateChain:
    - type: file
    value: '/etc/app/config/issuing.cert'
  3. Activate the configuration in docker-compose.yml:

    environment:
    - spring.profiles.active=local-access-token
  4. 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.

tip

JWTs can be combined with mTLS and API keys. API keys for the individual roles can also be embedded in the JWT (<application_keys> in the *.jconfig file).

warning

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).

Get started withCloudHSM for free.
Other questions?Ask Sales.
Feedback
Need help?