跳转到主要内容

概述

OneSignal提供了一个名为身份验证的增强安全功能,以帮助防止用户冒充。此功能使用JSON Web Tokens(即JWTs),在您的服务器上安全生成。为了验证订阅信息,这些令牌被传递到您的应用和OneSignal的API。 我们建议启用身份验证以:
  • 用户登录
  • 添加电子邮件订阅
  • 添加短信订阅
  • 修改用户身份
联系support@onesignal.com以启用此功能。

先决条件

设置

1

生成新密钥

登录您的OneSignal帐户并导航到设置 > 密钥和ID > 身份验证

身份验证配置

点击生成新密钥以创建新的密钥对。

创建新密钥对

下载PEM文件或复制私钥,确保安全存储私钥。

身份验证密钥对

始终将私钥存储在安全环境中,例如密钥管理系统。永远不要在代码中暴露私钥
2

在后端生成验证JWT

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

JWT 载荷

JWT 可以具有以下属性:
iss
required
您的 OneSignal 应用 ID
exp
required
令牌过期日期。
identity
required
用户的别名。
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 载荷中。如果这些详细信息不能预先获得,您的验证服务器必须提供端点以在订阅信息可用时动态生成令牌。示例:生成 JWT 以添加订阅
const subscriptions = [
  {
      "type": "Email",
      "token": "[email protected]"
  },
  {
      "type": "SMS",
      "token": "+12345678"
  }
]
const onesignalJWT = signOneSignalJWT('APP_ID', 'EXTERNAL_ID', subscriptions)
3

将 JWT 传递给 `login` 方法

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

// The JWT is generated on your backend using the authenticated user's
// External ID or any other custom aliases you may have set.
String onesignalJWT = "eyJhbGciOiJFUzI1NiIsInR5cCI6IkpXVCJ9.eyJpc3MiOiI3OGUzMjA4Mi1lYTI3LTQyZTMtYTg5OC1jNzJlMTQxODI0ZWEiLCJleHAiOjE2NTc3NzU4NzIsImlkZW50aXR5Ijp7ImFsaWFzX2xhYmVsX2V4YW1wbGUiOiJhbGlhc19pZF9leGFtcGxlIn0sInN1YnNjcmlwdGlvbnMiOlt7InR5cGUiOiJFbWFpbCIsInRva2VuIjoidGVzdEBkb21haW4uY29tIn0seyJ0eXBlIjoiU01TIiwidG9rZW4iOiIrMTIzNDU2NzgifV19.\_iazvUy6krturWicV1eXqPzptzIB8y_GmvDXfFp6OXNxiLvI2wRkWS5iH_gJWPmyZc48KLpJXgR2RT6Jn8_5Aw"

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,切换令牌身份验证以启用。

启用令牌身份验证

启用后,您的应用必须发送 OneSignal JWT 来验证订阅的真实性。此外,您的应用需要使用由身份验证令牌服务器生成的 JWT 来调用 login 方法。

添加订阅

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

REST API

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