Important: Signed metadata with public keys (RS256) is a paid feature and isn’t on by default. Contact Pendo Support to request access.
With a typical Pendo installation, your application passes metadata to Pendo as a JSON object over SSL or TLS. Some industries require additional assurance that this metadata hasn’t been tampered with in transit. Signed metadata adds a JSON Web Token (JWT), an open standard (RFC 7519), that verifies metadata originated from your application and wasn’t modified before it reached Pendo.
The legacy Send signed metadata with JWT option uses a shared secret and HMAC SHA‑256 (HS256). You generate a shared token in Pendo, sign JWTs with that shared secret, and Pendo verifies them with the same secret.
This article describes a different option: signed metadata with public keys. In this setup, you sign JWTs with your own RSA keys using the RS256 algorithm and publish the matching public keys at a JWKS (JSON Web Key Set) URI so Pendo can verify that the data came from your application and hasn’t been modified before it reaches Pendo. In the rest of this article, we call this signed metadata with public keys.
JWT doesn’t encrypt your metadata. It signs it. The signature confirms the message hasn’t changed, but the contents are still readable by other parties. Standard SSL or TLS encryption handles confidentiality separately.
This feature adds complexity and can cause data loss if implemented incorrectly. It’s unnecessary for most installations. If you’re already using signed metadata with a shared secret (HMAC SHA‑256), see Send signed metadata with JWT. Signed metadata with public keys is intended for customers who need to manage their own signing keys and publish public keys through a JWKS endpoint.
This article covers the process for installing Pendo using signed metadata with public keys.
Before you begin
You must have the following to install using signed metadata with public keys:
- RS256-signed metadata access for your subscription. This feature is available with all paid plans but is turned off by default. Contact Pendo Support to request access. The Advanced Security settings on your application's Install Settings page don't appear until access is turned on.
- Admin access to your Pendo subscription.
- An engineering resource to modify your Pendo installation code, generate JSON Web Tokens, and send them.
- A publicly accessible JWKS URI that serves your public signing keys in JSON format. Pendo must be able to reach this endpoint to verify JWT signatures.
- An RSA key pair, or multiple pairs for rotation. The private key signs JWTs on your server. The corresponding public key is published in your JWKS document.
We recommend installing Pendo without signed metadata first to validate your setup before you turn on JWT.
- For a direct web implementation, see the Developer's guide to implementing Pendo using the install script.
- For a mobile implementation, see the Developer's guide to installing the Pendo Mobile SDK.
Step 1. Activate signed metadata with public keys and configure your JWKS URI
Before you can save a JWKS URI in Pendo, your engineering team must publish your public signing keys at a JWKS endpoint. Your JWKS URI must be an HTTPS endpoint that returns a valid JWK Set document containing the public keys Pendo uses to verify JWT signatures. Each key in the set should include a key ID (kid) that uniquely identifies it.
Your JWKS URI must meet the following requirements. If it doesn't, you can't save it in Pendo:
- Use the HTTPS scheme.
- Resolve to a public address. Link-local and private IP ranges aren't allowed.
- Return an HTTP 200 response. Pendo doesn't follow redirects.
- Contain no query parameters or fragments.
Warning: Keep your private keys on your server only. Never embed private keys in client-side application code.
Turn on RS256-signed metadata
For your application to accept RS256-signed metadata:
- Go to Settings > Subscription settings from the top-right corner of Pendo.
- Open the Applications tab, then select the relevant application.
- Open the Install Settings tab.
- Find and turn on the Use RS256-signed metadata setting. For web apps, this is found under Customize your snippet. For mobile apps, this is found under Customize your SDK.
- After you turn on this setting, we reveal the JSON Web Key Set (JWKS) URI field. Continue to the next step: Configure and save your JWKS URI.
Note: The Advanced Security settings don't appear until our support team has activated RS256-signed metadata for your subscription. For more information, see Prerequisites.
Configure and save your JWKS URI
Unlike signed metadata with a shared secret, RS256-signed metadata doesn't use signing keys generated in Pendo. You register the JWKS endpoint where you publish your public keys:
- From the same Install Settings page, enter the URL of your JWKS endpoint in the JSON Web Key Set (JWKS) URI field.
- Select Test URI. Pendo validates that the URI is reachable and returns a valid JWK Set.
- After the test succeeds, select Save URI.
- You must complete both the test and save steps. Testing alone doesn't activate RS256-signed metadata for your application. If you attempt to send signed metadata without a saved JWKS URI, data from those sessions is dropped.
- You can edit the JWKS URI later using the edit icon next to the saved URI. You must test the URI again before you save changes.
- After you save the JWKS URI, another option appears: Only allow signed metadata. Don't turn on Only allow signed metadata until you verify that you're sending events with signed metadata, as outlined in Step 3 below.
- If your URI is validated, continue to Step 2. Start sending RS256-signed metadata below. If not, see JWKS URI validation errors.
Note: You can't turn off Use RS256-signed metadata or edit the JWKS URI while Only allow signed metadata is turned on. You must turn it off to make changes.
JWKS URI validation errors
If the URI isn't validated, Pendo displays one of the following messages:
| Error | Likely cause |
|---|---|
| The JWKS URI is invalid. | The URI format is malformed or doesn't meet the requirements listed earlier. |
| Failed to access the specified URI | Pendo can't reach the endpoint because of a network, DNS, or firewall issue. |
| Unable to fetch a JWK Set from the specified URI. | The endpoint responded but didn't return a valid JWK Set document. |
| The JWKS URI cannot be empty. | No URI was entered. |
Make sure your JWKS endpoint is publicly reachable from Pendo's servers and returns a valid JSON Web Key Set.
Step 2. Start sending RS256-signed metadata
Sending RS256-signed metadata to Pendo requires a technical or engineering resource to create JWTs that hold your metadata and to send them to Pendo. If you haven't already, we recommend that you first install Pendo without metadata before continuing.
- For a direct web implementation, see the Developer's guide to implementing Pendo using the install script.
- For a mobile implementation, see the Developer's guide to installing the Pendo Mobile SDK.
You shouldn't create or sign JWTs directly in your application code. To keep your private key safe, create the signed JWT on your server and pass it to your application before calling the initialize (for web) or startSession (for mobile) method.
Generate RS256-signed JWTs
There are many libraries you can use to generate and sign JWTs. When you generate signed JWTs to start sessions with Pendo, there are a few considerations:
- The JWT must be signed with the RS256 algorithm (RSA with SHA-256). If the JWT isn't signed with this algorithm, Pendo can't verify the signature, and the events aren't processed.
- The JWT must be signed with the private key that corresponds to one of the public keys published in your JWKS URI.
- The JWT header must include a key ID (
kid) that matches a public key in your JWKS document. Pendo uses this value to select the correct public key for signature verification. - The JWT payload must contain both the
visitorandaccountelements, each with anidproperty and value. - Visitor and Account IDs must be passed as strings for JWT installs. To generate an anonymous visitor, use an empty string as the value of the
idproperty of the visitor element. The Account ID property may be set to an empty string as well. Additionalvisitorandaccountproperties are optional. - A
nonceproperty must be included in the claims. The nonce is a string randomly generated by the client and must be at the top level in the JSON as a sibling property tovisitororaccount, not contained within one of those sections. The value isn't explicitly validated, but a value is required. Including a random nonce helps ensure that tokens always appear different even if they contain the same claims. - Any additional configuration you'd like can be included inside the JWT metadata.
- Historical metadata values must be included in every JWT.
See the following pseudocode for generating an RS256-signed JWT to start a visitor session with Pendo:
const payload = {
visitor: {
id: 'VISITOR-UNIQUE-ID' // Required if user is logged in; must be a string. Pass an empty string for an anonymous visitor.
// email: // Recommended if using Pendo Listen, or NPS Email
// full_name: // Recommended if using Pendo Listen
// role: // Optional
// You can add any additional visitor level key-values here,
// as long as it's not one of the above reserved names.
},
account: {
id: 'ACCOUNT-UNIQUE-ID' // Required if using Pendo Listen; must be a string. Pass an empty string if not applicable.
// name: // Optional
// is_paying: // Recommended if using Pendo Listen
// monthly_value:// Recommended if using Pendo Listen
// planLevel: // Optional
// planPrice: // Optional
// creationDate: // Optional
// You can add any additional account level key-values here,
// as long as it's not one of the above reserved names.
},
nonce: 'randomly generated value' // It should be different every time it is used
};
const jwt = JWT.sign(
payload,
PRIVATE_RSA_KEY, // Your RSA private key. Never expose this in client code.
{
algorithm: 'RS256',
keyid: 'YOUR-KEY-ID' // Must match a kid in your JWKS document
}
);Warning: There should be no private key value in the code of your application. The JWTs you create shouldn't be created on the client. They should be sent to the application from your server, where the JWT is already signed.
Signed metadata with anonymous visitors
Anonymous visitors are automatically assigned a random string as a Visitor ID when pendo.initialize() is called without metadata assigned to the Visitor ID. This method of generating anonymous Visitor IDs is the same for a conventional or signed metadata Pendo implementation.
With signed metadata, anonymous visitors still use JWT when they pass event data to Pendo.
Example of the payload used to initialize anonymous visitors with JWT:
let payload = {
nonce: "abcdefg78910xyz",
visitor: { // notice there is no "id" field
otherVisitorField: "hi"
},
account: {
otherAccountField: "hello world"
}
}
const jwt = JWT.sign(payload, PRIVATE_RSA_KEY, { algorithm: 'RS256', keyid: 'YOUR-KEY-ID' });
pendo.initialize({
jwt: jwt
})Update your application installation code
To send signed metadata, your application must fetch your JWT from your server and pass it to Pendo when starting a session.
Web implementation
For a web implementation, pass the JWT in the Pendo install script for your application as part of the initialize method:
pendo.initialize({
jwt: 'JWT-SIGNED-TOKEN' // obtained from your server
});Mobile implementation
For a mobile implementation, pass the JWT as part of the startSession method.
Example of an Android mobile device sending the JWT to Pendo (Java):
Pendo.setup(this, pendoAppKey, null, null);
String jwt = "JWT-SIGNED-TOKEN"; // obtained from your server
Pendo.jwt.startSession(jwt);Example of an iOS mobile device sending the JWT to Pendo (Swift):
PendoManager.shared().setup(pendoAppKey, nil);
let jwt = "JWT-SIGNED-TOKEN"; // obtained from your server
PendoManager.shared().jwt.startSession(jwt);Step 3. Verify that you're sending signed metadata
The following steps require you to know which visitor you're testing with. Typically, this involves signing in as a particular visitor to your application.
- Go to Settings > Subscription settings > Applications.
- Find and open your application.
- Open the Raw Events tab.
- Check for new data flowing into Pendo from the visitor that you're testing with.
Step 4. Enforce signed metadata only
When your install script is updated and transmitting signed metadata with public keys, you can enforce it so that data from sessions without secure metadata is dropped going forward. Up until this step, only Use RS256-signed metadata is turned on with a saved JWKS URI, which means that Pendo accepts metadata with or without a valid JWT depending on your configuration.
When you turn on Only allow signed metadata, Pendo only processes events that have a verified signed JWT. To turn on this setting:
- Go to Settings > Subscription settings from the top-right corner of Pendo.
- Open the Applications tab, then select the relevant application.
- Open the Install Settings tab.
-
Turn on Only allow signed metadata.
- Review the confirmation checklist, enter I understand, then confirm. This drops all events without signed metadata, as intended. After the signed JWT is generated and obtained by the client or mobile device, the JWT is sent to Pendo's servers. Pendo fetches your public keys from the configured JWKS URI and verifies the JWT signature using the
kidin the JWT header. Pendo doesn't process any events that are sent with an invalid JWT. Dropped data can't be recovered.
Important: You could experience data loss if your public application is using Pendo without secure metadata, or if mobile visitors haven't had time to update to an application version using JWTs, and you attempt to enforce signed metadata using the instructions in this section.
Replay protection
Signed metadata using JWT doesn’t use the jti claim (a unique identifier assigned to each JWT), which is often used to prevent replaying the same token. Instead, Pendo drops any duplicate events it receives, which helps prevent the same event from being processed more than once. You can also rotate your signing keys regularly to reduce the impact if a token is ever exposed.
Rotate your signing keys
A signed metadata JWT remains valid as long as the signature is valid and the corresponding public key is present in your JWKS document. Rotating keys on a regular basis is the best way to prevent long-lived JWTs from being exploited if compromised.
To rotate a signing key:
- Generate a new RSA key pair.
- Add the new public key, with a new
kid, to your JWKS endpoint. - Wait at least 10 days, then update your server to sign JWTs with the new private key. Set the
kidfield in the JWT header to match the new key's ID. Waiting gives Pendo's key caches time to refresh before the new key is used. - After all active sessions are using the new key, remove the old public key from your JWKS document.
Warning: If you remove a public key from your JWKS document before your application is updated to sign JWTs with the corresponding new private key, data isn't processed until the JWT sent to Pendo is signed with a key that Pendo can verify.
Unlike signed metadata with a shared secret, RS256 key rotation is managed entirely on your side through your JWKS endpoint. Pendo doesn't generate or revoke signing keys for RS256-signed metadata.
Turn off signed metadata with public keys
If you need to turn off signed metadata with public keys (using RS256) for your application, you can do so from the Install Settings page.
Warning: Turning off signed metadata removes your saved JWKS URI and causes data loss for any sessions currently sending signed JWTs. Dropped data can't be recovered. Before you turn it off, make sure your application is ready to send unsigned metadata.
- Go to Settings > Subscription settings from the top-right corner of Pendo.
- Go to the Applications tab.
- Find and open the relevant app.
- Open the Install Settings tab.
- Turn off Use RS256-signed metadata.
- Review the confirmation checklist, enter I understand, then confirm.
Your saved JWKS URI is removed immediately. Events sent with a signed JWT are no longer processed after this setting is turned off.
Note: You can't turn off Use RS256-signed metadata while Only allow signed metadata is turned on. Turn off Only allow signed metadata first.
Troubleshooting
| Symptom | What to check |
|---|---|
| No data appears in Raw Events after you turn on RS256 | Confirm the JWKS URI is saved, not just tested. Confirm JWTs are signed with RS256 and the JWT header kid matches a key in your JWKS document. |
| Data stopped after you enforced signed metadata | Confirm all application versions send valid JWTs. Check for clients still sending unsigned metadata. |
| JWKS URI test fails | Verify the endpoint is publicly reachable, uses HTTPS, returns valid JSON, returns an HTTP 200 response with no redirects, and has no query parameters or fragments. |
| Events dropped after key rotation | Confirm the new public key is in your JWKS document and new JWTs include the matching kid in the header. |
Related articles
- Send signed metadata with JWT (legacy HMAC SHA-256 shared-secret signing)
- Developer's guide to implementing Pendo using the install script
- Developer's guide to installing the Pendo Mobile SDK