跳转到主要内容

概述

OneSignal提供了一个名为身份验证的增强安全功能,以帮助防止用户冒充。此功能使用JSON Web Tokens(即JWTs),在您的服务器上安全生成。为了验证订阅信息,这些令牌被传递到您的应用和OneSignal的API。 启用身份验证以保护:
  • 用户登录
  • 添加电子邮件订阅
  • 添加短信订阅
  • 修改用户身份
身份验证目前处于测试阶段。联系 support@onesignal.com 为您的帐户启用此功能。支持团队启用后,您可以在控制台中激活它(请参阅第 5 步)。

先决条件

包装 SDK 支持(Flutter、React Native、Unity 等)即将推出。

设置

1

生成新密钥

登录您的OneSignal帐户并导航到设置 > 密钥和ID > 身份验证
Settings page showing Keys and IDs with Identity Verification section
点击生成新密钥以创建新的密钥对。
Generate New Keys button in the Identity Verification section
下载PEM文件或复制私钥,确保安全存储私钥。
Identity Verification key pair with private key and PEM download
始终将私钥存储在安全环境中,例如密钥管理系统。永远不要在客户端代码、公共仓库或日志中暴露私钥。
2

在后端生成验证JWT

身份验证需要在将终端用户登录到 OneSignal 之前,先使用您的认证服务器对终端用户进行身份验证。当终端用户通过您的后端进行身份验证时,生成令牌并将其包含在对设备的认证响应中。如果您的应用没有运行后端服务器,请考虑设置一个轻量级服务器来验证用户并生成这些令牌。

JWT 载荷

JWT 可以具有以下属性:
iss
必填
您的 OneSignal 应用 ID
exp
必填
令牌过期日期。
identity
必填
用户的别名。
subscriptions
仅在为用户添加电子邮件和短信订阅时才需要。

JWT 签名

使用 ES256 算法对 JWT 进行签名。确保您的后端配置为使用此签名方法,以避免将 JWT 发送到 OneSignal 时出现验证问题。我们建议使用 JWT 库 来完成此操作。使用 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');

私钥位于我们从控制台下载的上一步文件中。

验证您的 JWT

在与 SDK 集成之前,通过启动服务器并调用端点来验证 JWT 是否正确生成:
  node server.js
  curl http://localhost:3000/generate-jwt/your-external-id
您应该收到如下响应:
{
  "jwt": "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9..."
}
将 JWT 值粘贴到 jwt.io 并确认解码后的载荷包含以下参数:
{
  "iss": "your-onesignal-app-id",
  "exp": 1234567890,
  "identity": {
    "external_id": "your-external-id"
  }
}
在进行下一步之前,确认以下内容:
  • iss 与您在 设置 > 密钥和ID 中的 OneSignal 应用 ID 匹配
  • identity.external_id 存在并与您将传递给 OneSignal.login() 的值匹配
  • exp 是未来的时间戳 — 过期的令牌将被 OneSignal 拒绝

包含订阅

理想情况下,在用户登录时,订阅详细信息(如电子邮件或电话号码)应包含在 JWT 载荷中。如果这些详细信息不能预先获得,您的验证服务器必须提供端点以在订阅信息可用时动态生成令牌。示例:生成 JWT 以添加订阅
const subscriptions = [
  {
      "type": "Email",
      "token": "[email protected]"
  },
  {
      "type": "SMS",
      "token": "+12345678"
  }
]
const onesignalJWT = signOneSignalJWT('EXTERNAL_ID', subscriptions)
3

将 JWT 传递给 `login` 方法

一旦后端生成 JWT,就用它调用 login 方法。此令牌确保在进行任何更改(如添加电子邮件或短信订阅)之前验证用户身份。登录示例:
String externalId = "YOUR_EXTERNAL_ID";
String onesignalJWT = "YOUR_JWT_TOKEN";

OneSignal.login(externalId, onesignalJWT);
4

处理 JWT 生命周期事件

您需要在后端实施专用端点来处理令牌失效等场景。当 OneSignal 请求更新时,此端点应提供刷新的 JWT。处理令牌失效和刷新 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);
});
这确保当用户的 JWT 失效时,可以从后端获取新的令牌并传递给 OneSignal。如果在身份验证期间创建的令牌不包含电子邮件和电话号码,您还可以使用此功能生成包含电子邮件和电话号码的令牌,以便管理电子邮件和短信订阅。
5

在控制台中启用令牌身份验证

设置 > 密钥和 ID,切换令牌身份验证以启用。
Token Identity Verification toggle enabled in dashboard settings
启用后,您的应用必须发送 OneSignal JWT 来验证订阅的真实性。此外,您的应用需要使用由身份验证令牌服务器生成的 JWT 来调用 login 方法。

添加订阅

您无需额外步骤从移动应用添加订阅;调用登录方法会自动为您处理此操作。
OneSignal.getUser().addEmail(emailAddress);

REST API

当启用令牌身份验证时,对以下 API 的所有请求都必须在标头中包含服务器生成的 JWT 作为 bearer 令牌,例如:Authorization: Bearer <JWT>

常见问题

身份验证是必需的吗?

不,但强烈建议使用。没有它,任何知道用户外部 ID 的客户端都可以冒充该用户并修改其订阅或数据。

如果 JWT 在会话期间过期会怎样?

SDK 会触发 JWT 失效事件。实现 addUserJwtInvalidatedListener(请参阅处理 JWT 生命周期事件)以从后端获取刷新的令牌并将其传递给 updateUserJwt

哪些 SDK 支持身份验证?

目前,原生 Android SDK(5.2.0+)和 iOS SDK(5.3.0+)。包装 SDK 支持(Flutter、React Native、Unity 等)即将推出。

REST API 需要身份验证吗?

当令牌身份验证启用时,对支持的 API 的所有请求必须在 Authorization 标头中包含服务器生成的 JWT 作为 bearer 令牌。JWT 的生成方式与 SDK 使用相同。

JWT 使用什么算法?

身份验证要求 JWT 使用 ES256 算法签名(使用 P-256 和 SHA-256 的 ECDSA)。其他算法将被拒绝。