Contact Center AI 平台使用最终用户身份验证来安全地识别使用您的宿主应用的用户。此机制可确保只有经过授权的用户才能访问 CCAI Platform API,并确保其聊天会话和数据始终安全地与其特定身份相关联。
为了识别最终用户,您的宿主应用必须提供一个代表该特定人员的通用唯一标识符 (UUID)。
CCAI 平台中的身份验证机制
CCAI 平台中的身份验证依赖于使用 JSON Web 令牌 (JWT) 的安全握手。JWT 是一种开放标准,用于以 JSON 对象的形式安全地传输信息。
以下是标准身份验证流程:
请求:当最终用户开始使用 CCAI Platform 客户服务时,CCAI Platform SDK 会向您的宿主应用请求已签名的 JWT。
签名:宿主应用使用您的共享 CCAI 平台公司密钥 (
company_secret) 为 JWT 签名。交换:宿主应用将已签名的 JWT 传递回 CCAI 平台 SDK。然后,SDK 会将此 JWT 发送到 CCAI 平台服务器。
验证:CCAI Platform 服务器验证签名。如果有效,CCAI 平台会颁发授权令牌,授予用户对 API 的访问权限,并将用户与其账号相关联(如果用户没有账号,则创建一个新账号)。
如果宿主应用未在 JWT 载荷中提供标识符,CCAI Platform 将为用户创建一个匿名访客账号。
前提条件
在实现身份验证之前,您需要获取唯一的 SDK 身份验证元素。这些密钥可安全地向 CCAI 平台 API 标识您的公司。
使用管理员账号登录 CCAI 平台。
依次前往设置 > 开发者设置 > API 凭据。
找到您的 SDK 密钥名称 (
sdk_key_name)、SDK 密钥 (sdk_key) 和公司密钥 (company_secret)。
请妥善保管这些凭据。请仅与授权的系统和开发者分享这些密钥。
开发者实现指南
以下部分概述了开发者应如何在不同平台上构建 JWT 载荷并初始化 CCAI 平台 SDK。
JWT 载荷要求
如需将最终用户的信息传递给 CCAI Platform,宿主应用必须构建 JWT 载荷。回调方法会提供默认载荷(可能包含推送令牌和默认名称),但您可以使用以下预留键添加特定用户详细信息:
identifier(可选,但强烈建议提供 UUID)name(可选)email(可选)phone(可选,必须采用 E.164 格式)iss(可选,您的公司名称)iat(必需,签发时间戳)exp(必需,到期时间戳)
服务器端签名(推荐)
服务器上的 API 示例 (Ruby on Rails)
此示例展示了如何使用 Ruby on Rails 框架和 JWT gem 在服务器端对载荷进行签名。
该代码使用 jwt gem 设置 API 端点 (/api/ujet/sign),以使用公司密钥对载荷进行编码,并将编码后的令牌返回给客户端。
假设宿主应用的基本网址为 https://company.com/api/。 如需为 CCAI 平台签名载荷,您可以在 https://company.com/api/ujet/sign 添加另一个 API 端点。
该代码向应用添加了一个新路由,以处理对 /api/ujet/sign 网址的 POST 请求。
ujet_controller.rb 文件定义了 UjetController 类,该类具有一个端点 sign,用于为 CCAI 平台签名载荷。
在代码中,COMPANY_SECRET 被定义为用于为载荷签名的密钥。有效载荷从请求正文中提取,然后向其中添加各种值,例如 UNIQUE-IDENTIFIER、用户名、电子邮件地址、手机号码。
JWT.encode 方法用于将载荷和 ujet_secret 编码为 JSON Web 令牌 (JWT),然后以包含令牌键的 JSON 对象形式在响应中返回该令牌。
# routes.rb
post 'ujet/sign' => "ujet#sign"
# ujet_controller.rb
class UjetController
def sign
# In production, securely store and call your secret (e.g., via environment variables)
ujet_secret = "COMPANY_SECRET"
payload = body["payload"]
payload["identifier"] = "UNIQUE-IDENTIFIER"
payload["name"] = "user name"
payload["email"] = "test@email.com"
payload["phone"] = "" # E.164 format
payload["iss"] = "YOUR_COMPANY_NAME"
payload["iat"] = Time.now.to_i
payload["exp"] = Time.now.to_i + 10.minutes # Valid for 10 minutes
token = JWT.encode(payload, ujet_secret)
render json: {token: token}
end
end
客户端初始化
请按照以下指南初始化 CCAI 平台移动 SDK。
通过 iOS SDK 进行签名
此示例展示了如何使用 iOS SDK 对载荷进行签名,它会向网址 https://your.company.com/api/ujet/sign 的服务器发出 POST 请求,并将载荷作为请求正文。
服务器应在响应中返回签名令牌,然后以 JSON 对象中“token”键的形式将其传递给成功回调。
如果请求期间出现错误,则会将其传递给失败回调。
- (void)signPayload:(NSDictionary *)payload payloadType:(UjetPayloadType)payloadType success:(void (^)(NSString *))success failure:(void (^)(NSError *))failure
{
if (payloadType == UjetPayloadAuthToken) {
NSURLSessionConfiguration *sessionConfiguration = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfiguration];
NSMutableURLRequest *mutableRequest = [[NSMutableURLRequest alloc] init];
mutableRequest.URL = [NSURL URLWithString:@"https://your.company.com/api/ujet/sign"];
mutableRequest.HTTPMethod = @"POST";
NSError *error;
NSDictionary *data = @{@"payload": payload};
mutableRequest.HTTPBody = [NSJSONSerialization dataWithJSONObject:data options:0 error:&error];
NSURLSessionDataTask *task = [session dataTaskWithRequest:mutableRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
if(error) {
failure(error);
}
else {
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
success(json[@"token"]);
}
}];
[task resume];
}
}
通过 Android SDK 进行签名
以下示例展示了如何使用 Android SDK 对载荷进行签名。
此示例使用 Android 的 HTTP 客户端 Retrofit 向您的服务器请求已签名的载荷。该函数以载荷、载荷类型和令牌回调作为输入。
如果载荷类型为 UjetPayloadType.AuthToken,则会创建一个 Retrofit 实例,使用该实例向 https://company.com/api API 端点发出请求以对载荷进行签名,并在 tokenCallback 实例的 onToken 方法中返回签名后的令牌。
如果失败,系统会显示一条 Toast 消息 "Authentication failed"。
public void onSignPayloadRequest(Map<String, Object> payload, UjetPayloadType ujetPayloadType, final UjetTokenCallback tokenCallback) {
if (ujetPayloadType == UjetPayloadType.AuthToken) {
Retrofit retrofit = new Retrofit.Builder()
.baseUrl("https://company.com/api/")
.addConverterFactory(GsonConverterFactory.create())
.build();
AuthService authService = retrofit.create(AuthService.class);
Call<AuthToken> authenticate = authService.authenticate(new AuthRequest(payload));
authenticate.enqueue(new Callback<AuthToken>() {
@Override
public void onResponse(Call<AuthToken> call, Response<AuthToken> response) {
if (response.isSuccessful()) {
AuthToken authToken = response.body();
tokenCallback.onToken(authToken.getToken());
} else {
Toast.makeText(ExampleApplication.this, "Authentication failed", Toast.LENGTH_SHORT).show();
}
}
@Override
public void onFailure(Call<AuthToken> call, Throwable t) {
Toast.makeText(ExampleApplication.this, "Authentication failed", Toast.LENGTH_SHORT).show();
}
});
}
}
通过 Web SDK 进行签名
以下示例演示了如何在 Web SDK 中通过向服务器发送包含载荷的 API 请求来对载荷进行签名。
服务器应设置为处理 API 请求,并使用安全方法对载荷进行签名。然后,结果会返回到网页,该网页会使用回调函数将已签名的令牌传递回 CCAI 平台。
$(function() {
UJET.initialize({
// ... other parameters
handlers: {
authentication(callback) {
$.ajax({
type: 'POST',
url: 'https://company.com/api/ujet/sign',
data: JSON.stringify({
payload: {
identifier: 'UNIQUE-Identifier',
name: 'Test user'
}
}),
success: function(result) {
callback({
token: result.token,
user: {
identifier: 'UNIQUE-IDENTIFIER',
name: 'Test user'
}
});
}
});
}
}
}).then(function() {
// successfully initialized
}).catch(function(error) {
// Handle initialization error
});
});
会话中身份验证和 SDK 重新初始化
在某些情况下,最终用户可能会以访客身份(未经身份验证)开始聊天会话,并在会话中验证自己的身份(例如,通过虚拟助理或流程中的登录界面)。为确保有效会话得到安全更新并与新完成身份验证的用户相关联,请按以下步骤操作:
会话中身份验证的步骤
使用临时标识符初始化 SDK:当用户未通过身份验证时,使用随机标识符或访客标识符初始化 CCAI 平台 SDK。
引导用户进行身份验证:引导用户进入您的身份验证流程,例如 CCAI 平台虚拟助理 (VA) 或应用的内置登录界面。
通过 API 更新最终用户:在用户成功通过身份验证后(并且在用户仍处于虚拟客服或身份验证流程中时),您的后端必须调用 CCAI Platform Apps API,以使用用户的真实标识符更新最终用户的聊天会话。
使用新的 JWT 重新初始化 SDK:后端成功更新后,为经过身份验证的用户生成新的 JWT。使用此新 JWT 再次调用初始化方法,重新初始化 CCAI Platform SDK。
升级会话(如果使用虚拟助理):如果用户之前使用虚拟助理进行身份验证,虚拟客服现在应将消费者升级到其最终目标队列。
示例 (Web SDK)
如需重新初始化,请再次调用 UJET.initialize 函数。这会触发身份验证处理程序来获取新令牌。
// Call this after successful authentication and the CCAI Platform Apps API update
UJET.initialize({
// ...include your existing parameters
handlers: {
authentication(callback) {
// Fetch the new JWT for the newly authenticated user
$.ajax({
type: 'POST',
url: 'https://your.company.com/api/ujet/sign',
data: JSON.stringify({
payload: {
identifier: 'AUTHENTICATED-USER-UUID',
name: 'Authenticated User Name'
}
}),
success: function(result) {
callback({
token: result.token,
user: {
identifier: 'AUTHENTICATED-USER-UUID',
name: 'Authenticated User Name'
}
});
}
});
}
}
}).then(function() {
// SDK successfully reinitialized with the authenticated user
}).catch(function(error) {
// Handle reinitialization errors
});
为何要这样做?
这样可确保所有后续操作、路由和历史记录都安全地与已通过身份验证的用户相关联,而不是与匿名访客会话相关联。
这样可以防止数据泄露,并保持 CRM 和用户记录的准确性。
摘要表
| 场景 | 需要采取行动 |
|---|---|
| 用户启动了经过身份验证的会话 | 使用用户的真实 UUID 和 JWT 初始化 SDK。 |
| 用户以未经身份验证的状态开始 | 使用访客/随机标识符初始化 SDK。 |
| 用户在会话中进行身份验证 | 使用 API 更新 CCAI 平台,生成新的 JWT,然后重新初始化 SDK。 |