Skip to main content

Overview

OneSignal offers an enhanced security feature called Identity Verification to help prevent user impersonation. This feature utilizes JSON Web Tokens – or JWTs, securely generated on your server. To verify subscription information, these tokens are passed to your app and OneSignal’s API. Enable Identity Verification to secure:
  • Logging in users
  • Adding email subscriptions
  • Adding SMS subscriptions
  • Modifying user identities
Identity Verification is currently in beta. Contact support@onesignal.com to have it enabled for your account. Once support enables it, you activate it in your dashboard (see Step 5).

Prerequisites

Wrapper SDK support (Flutter, React Native, Unity, etc.) is coming soon.

Setup

1

Generate new keys

Log in to your OneSignal account and navigate to Settings > Keys & IDs > Identity Verification.
Settings page showing Keys and IDs with Identity Verification section
Click Generate New Keys to create a new key pair.
Generate New Keys button in the Identity Verification section
Download the PEM file or copy the private key, making sure to store the private key securely.
Identity Verification key pair with private key and PEM download
Always store your private keys in a secure environment, such as a key management system. Never expose private keys in client-side code, public repositories, or logs.
2

Generate verification JWT on your backend

Identity verification requires authenticating the end-user with your authentication server before logging them into OneSignal. When the end-user authenticates with your backend, generate the token and include it in the auth response to the device. If your app doesn’t run a backend server, consider setting up a lightweight server to verify users and generate these tokens.

JWT payload

The JWT can have the following properties:
iss
required
Your OneSignal App ID
exp
required
The token expiration date.
identity
required
The user’s alias.
subscriptions
Required only when adding Email and SMS subscriptions to a user.

Signing the JWT

Sign the JWT using the ES256 algorithm. Ensure your backend is configured to use this signing method to avoid verification issues when sending the JWT to OneSignal. We recommend a JWT Library to do this.Example using jsonwebtoken:
import jwt from 'jsonwebtoken';

const APP_ID = process.env['ONESIGNAL_APP_ID']
const IDENTITY_VERIFICATION_SECRET = process.env['ONESIGNAL_IDENTITY_VERIFICATION_SECRET_KEY']

// Generates JWT, potentially with subscription claims, for the user identified by the External ID
function signOneSignalJWT(externalId, subscriptions) {
return jwt.sign({
iss: APP_ID,
exp: Math.floor(Date.now() / 1000) + 3600, // 1-hour expiration
identity: {
'external_id': externalId,
},
subscriptions
},
IDENTITY_VERIFICATION_SECRET,
{ algorithm: 'ES256' });
}

// Pass this token to your mobile app to use with the `login` SDK method
const onesignalJWT = signOneSignalJWT('EXTERNAL_ID');

The private key is in the previous step’s file we downloaded from the Dashboard.

Verify your JWT

Before integrating with the SDK, verify your JWT is being generated correctly by starting your server and calling the endpoint:
  node server.js
  curl http://localhost:3000/generate-jwt/your-external-id
You should receive a response like:
{
  "jwt": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9..."
}
Paste the JWT value at jwt.io and confirm the decoded payload contains the following parameters:
{
  "iss": "your-onesignal-app-id",
  "exp": 1234567890,
  "identity": {
    "external_id": "your-external-id"
  }
}
Confirm the following before moving on to the next step:
  • iss matches your OneSignal App ID from Settings > Keys & IDs
  • identity.external_id is present and matches the value you will pass to OneSignal.login()
  • exp is a future timestamp — an expired token will be rejected by OneSignal

Including subscriptions

Ideally, subscription details, such as email or phone number, get included in the JWT payload when logging a user in. If these details aren’t available upfront, your verification server must provide an endpoint to generate tokens dynamically as subscription information becomes available.Example: Generating JWT to add subscriptions
const subscriptions = [
  {
      "type": "Email",
      "token": "[email protected]"
  },
  {
      "type": "SMS",
      "token": "+12345678"
  }
]
const onesignalJWT = signOneSignalJWT('EXTERNAL_ID', subscriptions)
3

Pass JWT to the `login` method

Once your backend generates the JWT, call the login method with it. This token ensures the user’s identity is verified before any changes, such as adding an email or SMS subscription, can be made.Example of logging in:
String externalId = "YOUR_EXTERNAL_ID";
String onesignalJWT = "YOUR_JWT_TOKEN";

OneSignal.login(externalId, onesignalJWT);
4

Handle JWT lifecycle events

You’ll need to implement a dedicated endpoint on your backend to handle scenarios like token invalidation. This endpoint should provide a refreshed JWT when OneSignal requests an update.Example of handling token invalidation and refreshing the JWT:
OneSignal.addUserJwtInvalidatedListener(event -> {
  // Get the expired user's External ID
  String externalId = event.getExternalId();

  // Fetch a new JWT from your backend for the user
  String onesignalJWT = "yourUpdatedToken";

  // Provide the new JWT to the SDK
  OneSignal.updateUserJwt(externalId, onesignalJWT);
});
This ensures that when a user’s JWT is invalidated, a new one can be fetched from your backend and passed to OneSignal. You can also use this function to generate a token with an email and phone number, allowing you to manage email and SMS subscriptions if the token created during authentication does not contain them.
5

Enable token identity verification in the dashboard

From Settings > Keys & IDs, toggle Token Identity Verification to enable.
Token Identity Verification toggle enabled in dashboard settings
Once enabled, your app must send OneSignal JWTs to verify subscription authenticity. Additionally, your app is required to call the login method using a JWT generated by your identity verification token server.

Adding subscriptions

You don’t need to take extra steps to add subscriptions from your mobile app; calling the login method automatically handles this for you.
OneSignal.getUser().addEmail(emailAddress);

REST API

When Token Identity Verification is enabled, all requests to the following APIs must include a server-generated JWT in the headers as a bearer token, e.g., Authorization: Bearer <JWT>.

FAQ

Is identity verification required?

No, but it is strongly recommended. Without it, any client that knows a user’s External ID can impersonate that user and modify their subscriptions or data.

What happens if the JWT expires during a session?

The SDK triggers a JWT invalidation event. Implement the addUserJwtInvalidatedListener (see Handle JWT lifecycle events) to fetch a refreshed token from your backend and pass it to updateUserJwt.

Which SDKs support identity verification?

Currently, the native Android SDK (5.2.0+) and iOS SDK (5.3.0+). Wrapper SDK support (Flutter, React Native, Unity, etc.) is coming soon.

Do I need identity verification for the REST API?

When Token Identity Verification is enabled, all requests to the supported APIs must include a server-generated JWT as a bearer token in the Authorization header. The JWT is generated the same way as for SDK use.

What algorithm does the JWT use?

Identity Verification requires JWTs signed with the ES256 algorithm (ECDSA using P-256 and SHA-256). Other algorithms will be rejected.