跳转到正文

认证与 Token ​

宿主先登录自己的账号系统,再通过 authProvider 为当前用户取得 Popo IM 凭证。SDK 使用这份凭证访问 IM 接口;宿主密码、登录 Cookie 与 SDK Token 分别管理。

认证链路 ​

text
用户登录宿主应用
  → SDK 调用 authProvider
  → App / 浏览器请求宿主自己的认证接口
  → 宿主后端依据已验证登录态确定当前用户
  → 宿主后端请求 Popo IM POST /app/sdk/token
  → Provider 返回 user、token、expireAt
  → SDK 完成 /app/sdk/sync 并建立实时连接

authProvider 不接收需要签票的用户 ID。宿主后端应从自己的 Session 或 Access Token 确定账号,不能直接使用客户端传入的 user_id 为任意用户签票。

两种凭证,不同调用方 ​

凭证保存位置用途
宿主登录凭证宿主自己的登录机制访问宿主的账号与取票接口
sdkSecret宿主后端受控配置调用 Popo IM /app/sdk/token 等服务端集成接口
SDK tokenSDK 运行时以 Bearer 访问 /app/sdk/* 与实时鉴权

sdkSecret 不能出现在 App、浏览器脚本、URL 或普通日志中。SDK Token 由 Popo IM 服务端签发,宿主客户端无需实现 JWT 签名。

使用内置宿主账号系统

配套应用的 POST /app/auth/token 根据已验证的宿主登录态返回 IM 凭证。接入已有业务系统时,应建立自己的取票接口,由后端调用 /app/sdk/token;不要把这两个接口的认证方式混用。

宿主后端取票 ​

以下请求仅在宿主后端执行。user_id、昵称及头像来自该后端确认的当前用户:

http
POST https://example.com/app/sdk/token
Authorization: Bearer <sdkSecret>
Content-Type: application/json

{
  "user_id": "chenyue",
  "username": "chenyue",
  "nickname": "陈悦",
  "avatar": "https://example.com/media/chenyue.webp",
  "signature": "记录每一次出发"
}

成功响应的主要字段如下;为便于阅读省略宿主推送配置 push。id 是 Popo 内部用户 ID,SDK 身份采用 user_id:

json
{
  "code": 0,
  "msg": "ok",
  "data": {
    "user": {
      "id": "18",
      "user_id": "chenyue",
      "username": "chenyue",
      "nickname": "陈悦",
      "avatar": "https://example.com/media/chenyue.webp",
      "signature": "记录每一次出发",
      "profile_updated_at": 1792296000000
    },
    "token": "<服务端签发的 JWT>",
    "expire_at": 1794888000
  }
}

上面的 ID 与时间为结构示意。实际 push 是服务端按应用及平台生成的宿主推送初始化配置,不参与 SDK 的 AuthInfo。如需匹配原生推送规则,取票请求的 platform、manufacturer、package_name 必须三项一起传入;Web 接入不必提供。

请求字段必填约束
user_id是1–64 字符,不能有首尾空白或控制字符;宿主稳定用户 ID
nickname是1–80 字符,不能有首尾空白或控制字符
username否公开账号,非空时 1–64 字符;用于精确查找与好友二维码
avatar否最多 1024 字符;空值使用服务端默认头像
signature否最多 255 字符

资料字段均不能包含控制字符。取票成功时会同步该用户的公开资料,因此宿主应使用自己当前已确认的资料。

宿主接口应校验 HTTP 状态和 code,只在 code === 0 且 data 完整时返回认证结果,并设置 Cache-Control: no-store。失败时抛出可识别的宿主错误,不要返回空 Token 或沿用另一账号的凭证。

Provider 返回什么 ​

JavaScript 两端的标准形态为:

js
return {
  user: {
    userId: data.user.user_id,
    username: data.user.username,
    nickname: data.user.nickname,
    avatar: data.user.avatar,
    signature: data.user.signature
  },
  token: data.token,
  expireAt: data.expire_at
}
平台Provider 形式返回模型
Web() => Promise<IMAuth>{ user, token, expireAt }
AndroidPopoAuthProvider.fetchAuth(callback)callback.onSuccess(PopoAuthInfo) 或 onError(Throwable)
iOS@Sendable () async throws -> PopoAuthInfoPopoAuthInfo(user:token:expireAt:)
HarmonyOS() => Promise<PopoAuthInfo>new PopoAuthInfo(user, token, expireAt)
uni-app() => PopoAuthInfo | PromiseLike<PopoAuthInfo>{ user, token, expireAt }

expireAt 始终是 Unix 秒,不是 JavaScript 毫秒。SDK 会核对 JWT 中的 user_id、exp 与返回对象一致,这属于防串号与格式检查;服务端仍负责最终验签。

登录、续期与账号切换 ​

SDK 初始化后,宿主确认自身登录态,再调用 login()。SDK 内部合并续期并处理授权错误,宿主不需要对每个聊天操作再包一层刷新 Token 或重复重试。

用户在宿主主动切换账号后,先让 Provider 的身份来源切到新账号,再显式调用 login()。各端显式登录均可切换身份;自动续期必须保持原账号,如果 Provider 在续期时返回另一用户,会停止旧会话并报告身份变化。宿主也可以先 logout() 再登录,便于同步收起旧账号界面。

用户退出宿主时同时调用 SDK logout(),再清理宿主登录态。组件或页面卸载只移除自身监听;Web 实例销毁另调用 destroy()。不要因每次切换标签而重复初始化或退出进程级 SDK。

公开资料同步 ​

宿主保存昵称、头像或签名成功后,先更新自己的认证来源及后端取票缓存,再通知 SDK:

平台同步入口
Webclient.refreshCurrentUser(user);只更新本地展示,宿主后端应已完成服务端资料同步
Android / iOS / HarmonyOS / uni-appupdateCurrentUser;在当前登录身份下提交变化的公开资料

用户 ID 不能通过资料更新修改。服务端取票缓存若未随资料版本失效,下次续期可能用旧昵称或头像覆盖新资料。

出错时如何处理 ​

临时断网或服务不可用时保留已有页面和可读缓存,允许用户重试。宿主登录态确认失效时,清理 SDK 会话并回到宿主登录页。分支应依据平台错误码或 HTTP 状态,避免通过错误文案判断。

Token、Secret 和宿主密码不写入埋点或错误截图。排查问题优先保留操作、平台版本、业务错误码与请求跟踪 ID。