Installation using signed metadata with JWT

Last updated:

Important: This functionality must be enabled by a Pendo representative. Contact Pendo Support to request access.

With a typical Pendo installation, the client passes metadata directly to the Pendo agent as a JSON object. All data exchanged between the agent in your application and Pendo is encrypted and transferred using Security Sockets Layer (SSL) protocol.

Some industries require additional reassurance that metadata isn't tampered with in-flight. Signed metadata is used to add a JSON web token (JWT) to your metadata and validate that it wasn't altered and didn't originate from a source other than your agent. This is optional and not necessary for most installations. It adds additional complexity and might result in data loss if implemented incorrectly.

When using signed metadata in conjunction with the Pendo install script, metadata passed to the Pendo agent must be contained in a signed token used to verify the integrity of the claims contained within it. This doesn't hide the claims from other parties. This is addressed with standard data encryption, but the signature is used to verify the message wasn’t changed along the way.

This isn't encryption. Think of it as a hotel key. You register at the front desk and they give you a plastic electronic key (or token) with which you can access your room, the pool, and the garage. But you can't open other people's rooms or go into the manager's office. You can only access your rooms using your key and nobody can else can access your rooms without your key. Like a hotel key, when your stay has ended, you're left with a useless piece of plastic. The token doesn't do anything after it's expired.


  • Active signed metadata access.
  • Subscription admin access.
  • Engineer who can modify your Pendo install script.

JWT installation requires all requests to be signed using your JWT shared secret, otherwise, data is dropped. You can find the shared secret on the Install Settings page, which is only accessible by Pendo Admin users. JWT doesn't have to be set up in the initial install and can be set up later if needed.

Configure your application to accept signed metadata

Signed metadata must be active for your subscription for Advanced Security settings to be visible. Contact your Pendo representative if Advanced Security isn't available.

Use signed metadata must be enabled for your application to accept data with JWT. If this setting isn't enabled and you attempt to send signed metadata, it will be dropped.

  1. Navigate to Settings > Subscription Settings.

  2. Open the Applications tab.

  3. Find and open the relevant app from your Applications list.

  4. Open the Install Settings tab.
  5. Select Enable under Customize your snippet to accept signed metadata.

  6. Update your install script to transmit signed metadata. Don't complete the following steps until you are sending signed metadata. 
    • If Use signed metadata is enabled, we accept metadata with or without JWT.  
    • If Only allow signed metadata is enabled, we only process events that have a verified signed JWT.
    • If Use signed metadata is disabled, we don't accept events with JWT. 
  7. When your install script is updated and transmitting signed metadata, enable Only allow signed metadata.

  8. Confirm that you want to only allow signed metadata. This drops all events without signed metadata, as intended. Dropped data can't be recovered.


Generate key

This key is used to sign your metadata. You can create up to five active keys per application. When set up is complete, your application only accepts data that's transmitted with one of your five active keys.

  1. Navigate to the Active Keys table in Install Settings and select Generate Key.

  2. Enter a description to help you identify your keys later. Select Create to add a new key.

  3. The key is now available in the Active Keys table. Keys are hidden by default. Select Show to see the key.


Update Pendo install script

Pendo signed metadata requires the use of JSON Web Tokens (JWT). JWT is an open, industry standard method (RFC 7519) for representing claims securely between two parties. There are many libraries out there that can be used to generate and sign JWTs.

There are a couple requirements to keep in mind when generating the JWT.

  • A "nonce" property 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 to visitor or account, not contained within one of those sections. The value is not 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.
  • The HMAC SHA-256 algorithm should be used when signing the JWT. If the JWT isn't signed with this algorithm, Pendo will not be able to verify the signature and the events will not be processed.

To send signed metadata, the client application must create a JWT to contain the metadata and use the generated key to sign it. Once the signed JWT is generated, the JWT and the key ID are sent to the Pendo agent instead of sending the metadata as a raw JSON body. You can send the JWT and key ID by including them in the Pendo install script for your application as part of the pendo.initialize call. The JSON object passed to initialize must have both jwt and signingKeyName properties.

Any additional configuration you would like can be included alongside the jwt and signingKeyName properties.

Example with JWT

jwt = JWT.sign({

        id:             'VISITOR-UNIQUE-ID' // Required if user is logged in, must be a string
        // email:       // Recommended if using Pendo Feedback, or NPS Email
        // full_name:   // Recommended if using Pendo Feedback
        // 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 Feedback, must be a string
        // name:         // Optional
        // is_paying:    // Recommended if using Pendo Feedback
        // monthly_value:// Recommended if using Pendo Feedback
        // 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
'JWT-SECRET-KEY' // Generate this key below

The agent includes the JWT with key ID when sending events for processing. Pendo verifies that the JWT hasn't been tampered with and doesn't process any events that are sent with an invalid JWT.

Visitor and Account IDs must be passed as strings for JWT installs.

Exchange and revoke the JWT secret key

To revoke a previously used JWT secret key, generate a new key in the Install Settings page. Once the new key is properly inserted, the previous key should be revoked.

Warning: If an active key is revoked before the install script is updated with the new key, data won't be processed until the JWT sent to Pendo is signed with the new key.

To revoke a key, select the Revoke Key icon when hovering over the key, then accept the confirmation to revoke the key permanently. This can't be undone.


You can find a log of all Revoked Keys underneath the Active Keys section. Screen_Shot_2020-04-06_at_3.02.58_PM.png

Additional configurations

Can I use signed metadata and track 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 installation. Anonymous visitors should 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, 'SECRET KEY');
jwt: jwt,
signingKeyName: 'SIGNING KEY NAME'

Identifying anonymous visitors
If you identify visitors with their unique visitor ID after initializing with an anonymous ID, call pendo.UpdateOptions(...) and update metadata as needed. This function works the same as a conventional Pendo installation.

Clear user metadata on log out

It's a best practice to clear the stored user metadata at the end of the session. This is encouraged if multiple users use the same computer and is highly recommended if multiple anonymous visitors use the same computer. If the stored metadata isn’t cleared, another user who should be identified as a new anonymous user may be incidentally identified using the stored metadata and their behavior will be attributed to the previously identified visitor.

This can be resolved by calling pendo.clearSession() in your app when the user logs out or before the next user is identified, for example on a login screen. This is particularly important on a login screen that loads when an expired cookie is detected to catch user sessions that ended when the browser was closed and did not log out or time out as expected.

Does signed metadata help prevent replay attacks?

Pendo drops any duplicate events it receives, preventing malicious users from replaying the same event over and over. Signed metadata using JWT doesn't support the “jti” claim, commonly known as a way to prevent replay attacks. A signed metadata JWT will remain valid as long as the signature is valid. Revoking and exchanging tokens on a regular basis is the best way to prevent long lived JWT tokens from being exploited if compromised. 


Was this article helpful?
4 out of 7 found this helpful