Skip to main content

Custom authentication keys

By default, access tokens are JWTs signed/verified using an Ed25519 keypair derived from the Privy API secret. This derivation is done automatically if you use the createAccessToken() method in privy-node.

Using custom keysโ€‹

If you prefer, you can configure Privy to use your own JWT signing keys instead. In this case, Privy will generate well-formatted claims for you to sign and pass to your user.

To use your own keys for JWT signing:

  1. Securely generate a keypair independently from Privy.
  2. Register your public key in the Privy console.
  3. Implement a function that signs access token claims using your corresponding private key.
  4. Instantiate privy-node with the signing function as your customSigningFn.

Register your public key in the consoleโ€‹

To register your own public key for JWT signing, navigate to the Settings tab in the console and activate the toggle in the Custom Authentication Keys section.

To override the auto-generated JWT signing key, click "Register New Auth Keys" and enter the JWT public key in PEM format. This public key should correspond to the private key you will use to sign access tokens on your server.

Public keys must be entered in PEM format. Allowable JWT signature algorithms include:

  • RSA: RS256, RS384, RS512
  • EdDSA: EdDSA (Ed25519 keys)
  • Elliptic curve: ES256, ES384, ES512
info

If you use custom keys to sign JWTs, you must instantiate privy-node with customSigningFn. Then, when you call createAccessToken(), customSigningFn will be used sign the JWT claims.

Generating access tokens signed with a custom keyโ€‹

Once your public key is registered in the Privy console, create a custom signing function that signs JWT claims using the private key corresponding to the registered public key. Then initialize the privy-node client with your custom signing function.

import {PrivyClient, PrivyData, AccessTokenClaims} from '@privy-io/privy-node';

const mySigningFn = (claims: AccessTokenClaims): Promise<string> => {
// ...
// Sign the access token claims using your custom private key.
// ...
return signedAccessToken;
};

// Initialize client with your custom signing function.
const client = new PrivyClient(PRIVY_API_KEY, PRIVY_API_SECRET, {
customSigningFn: mySigningFn,
});

// Create the access token as usual.
const token = await client.createAccessToken('0x123');

Privy JWT Formatโ€‹

A JWT is an encoded JSON object with three parts: a header, payload, and signature. The following is an example of a Privy access token:

eyJhbGciOiJFZERTQSJ9.eyJhaWQiOiIiLCJhdWQiOiJhcGkucHJpdnkuaW8iLCJleHAiOjE2NDYzNDkyMjMsImlhdCI6MTY0NjM0ODYyMywiaXNzIjoiTWVCdVV1TGF1dDJ2SHZ1d2I1QmxjLUxoTWhhZ3hEZXZDdjF0Y0xBcDQ1bz0iLCJybHMiOlsiYWRtaW4iXSwic3ViIjoiMHgxMjM0NTYifQ.MaGXBcaY0luVxU8qDBa468V1XI3gEp7BAmH7nbmuKEGR2Hnh6YrVZmcZZ6bWNoBpatfGuGYGMHsU5YxHDwC9Ag

If you inspect its contents using the JWT debugger at https://jwt.io, you'll find the following contents:

The header section encodes the format of the token:

  • alg is the algorithm used to encode the token.
  • typ is the type of token.
{
"alg": "EdDSA",
"typ": "JWT"
}

Claimsโ€‹

The claims section contains claims the token attests to:

  • aid is the account ID. This claim can be left empty since the account ID can be determined from the API key contained in iss.
  • aud is the intended recipient of the JWT. Privy expects the aud to be api.privy.io.
  • exp is the timestamp at which the token will expire. By default tokens expire in 10 minutes.
  • iat is the timestamp at which the token was issued.
  • iss is the issuer. Privy expects the issuer to be the API key corresponding to the account.
  • sub is the user ID to whom this token is issued.
{
"aid": "",
"aud": "api.privy.io",
"exp": 1646349223,
"iat": 1646348623,
"iss": "MeBuUuLaut2vHvuwb5Blc-LhMhagxDevCv1tcLAp45o=",
"sub": "0x123456"
}