Security & authentication

Learn more about how to secure your client-side applications as they integrate with Knock.
👉
Note: This integration guide references examples from our client-side JS SDK. You only need to add the authentication outlined in this guide if you're integrating Knock on the client side of your applications to use the Knock in-app feed or the Knock preferences model.

Access to Knock's API is protected using a secret API key for your backend application, and a public API key for your client application. By default, the public API key can read in-app feeds and manage user preferences for any of your users. While this is convenient for testing and development, this is not suitable for production environments.

Production environments should enable enhanced security mode, which requires clients to send both the public API key and a signed user token that identifies the user that is performing the request. Enhanced security mode trades convenience for security, and we recommend that you enable it When going to production.

API endpoints that can be called with a public API key

Public API keys can make the following calls from your client application:

  • Fetching a user's notification feed
  • Marking a feed message as read, seen, or archived
  • Getting or setting a user's preferences

When enhanced security mode is enabled, calls from your client application will need to include both the public API key as well as a signed user token.

Authentication (without enhanced security)

In a non-production Knock environment, you can use your public key to authenticate all users. You do not need to implement any other security mechanisms. Knock will not reject requests that do not include a signed user token.

🚨
Note: This approach is convenient for development and testing, but should not be used in a production environment with real user data.

Client SDK example

React notification feed example

Authentication (with enhanced security)

When enhanced security mode is enabled, Knock will reject requests from the client using your public API key that do not include a signed user token. This token must be generated by your backend application and is used to authenticate a user's requests to Knock using your public API key.

Using our JWT-based authentication approach means using a shared secret to sign a new JWT on your backend. This means you can generate the authentication token out-of-band without an additional network request.

1. Generate the signing key

You can find the signing key in the Knock dashboard under the "Developers > API keys" page. Save the private key shown to you here. Note: you won't be shown this key again, so you'll need to regenerate it if you lose access.

The Knock dashboard will present the generated private key in two formats:

  1. Base-64 encoded PEM format, which fits on a single line (convenient for setting environment variables)
  2. PEM encoded format, which may be required by certain libraries or platforms (visible under the "Advanced" disclosure)

By convention, we recommend storing the private key in the environment variable KNOCK_SIGNING_KEY. This is where the Knock SDK will look for the key by default.

2. Sign the JWT

Within your backend application, you'll need to sign the JWT and make it available to your front-end client. Usually, you'll do this by passing it down as a serialized property on the user or passing in a cookie.

Your JWT will need to be signed against your private signing key using an RS256 algorithm. At a minimum, the JWT to be signed must contain:

To sign your JWT as middleware in a NodeJS express like app:

You can see more details on the options for the signUserToken method in the docs.

3. Send the JWT to the client

In your client application, you can now use the JWT to authenticate with Knock:

Client SDK example

React notification feed example

Handling token expiration

Generally, it's advisable to set the token expiration to be equal to your session token expiration. That way you can regenerate both of the tokens together from within your application. There may, however, be cases where this is not possible, in which case it's best practice to opt for a relatively short-lived expiration time for your user tokens and refresh them from your backend before the expiration window.

For convenience, the Knock JavaScript client and React package expose an onUserTokenExpiring callback method which will be invoked before the user token expires. This provides an easy hook for your application to refresh the user token from your backend.

At any time your application can call the authenticate method again with an updated user token and the connection to the Knock real-time service will be restarted.

Avoiding authentication

You can avoid authentication altogether by proxying requests to Knock via your backend, although we don't recommend this approach as it will add more latency for your users.

Troubleshooting

Errors using your Knock signing key

If you are getting errors like secretOrPrivateKey must be an asymmetric key when using RS256, try using the base-64 encoded format of your signing key generated in the Knock Dashboard (under Developers > API keys > Application Signing Keys).