Contact Center AI 平台 (CCAI Platform) 中的最终用户身份验证流程是一种安全的方法,用于识别使用宿主应用的用户。最终用户由宿主应用提供的通用唯一标识符 (UUID) 标识。每当需要进行身份验证时,CCAI 平台 SDK 都会请求由共享密钥 (company_secret) 签名的 JSON Web 令牌 (JWT),并由宿主应用提供。如果宿主应用提供 JWT,CCAI 平台 SDK 会开始身份验证流程并获取身份验证令牌。
最终用户
此处的最终用户是指宿主应用的用户。
为了识别最终用户,CCAI Platform 使用由宿主应用提供的标识符。此标识符应为每个用户独有的通用唯一标识符 (UUID)。
使用 UUID 有助于确保准确识别最终用户并将其与其他用户区分开来,即使最终用户的电子邮件地址发生变化也是如此。
使用 CCAI Platform 进行身份验证
JSON Web 令牌 (JWT) 用于安全地识别向 CCAI 平台发出请求的用户或应用。宿主应用负责通过回调向 CCAI 平台 SDK 提供 JWT。每当需要进行身份验证时,CCAI 平台 SDK 都会要求宿主应用使用共享的 SDK 密钥 (sdk_key) 提供 JWT。
如果宿主应用通过回调向 CCAI Platform SDK 提供了 JWT,则 CCAI Platform SDK 会开始向 CCAI Platform 进行身份验证并获取身份验证令牌。
JWT 的载荷可能包含用户标识符、电子邮件地址、姓名和手机号码等信息。 Google Cloud 建议使用 E.164 格式的手机号码。此信息用于为用户创建新账号,或将用户与 CCAI 平台上的现有账号相关联。
如果宿主应用在 JWT 载荷中提供标识符,CCAI 平台会使用该标识符创建用户或将用户与账号相关联。如果未提供标识符,CCAI Platform 会为用户创建一个匿名账号。
如需详细了解 CCAI 平台中的 JWT 签名,请参阅 JWT 签名部分。
管理 SDK 密钥
sdk_key_name 和 sdk_key 字段是重要的身份验证元素。它们可唯一标识您的公司,并用于安全地访问 CCAI 平台 API。
如需管理您的 SDK 密钥,请按以下步骤操作:
以具有管理员角色的用户身份登录 CCAI Platform 门户。
在 CCAI 平台门户中,依次点击设置 > 开发者设置。 如果您没有看到设置菜单,请点击 菜单。
前往公司密钥和密钥代码窗格,管理用于生成身份验证令牌的 SDK 密钥。
您必须确保这些代码的安全,并且仅与需要访问 CCAI 平台 API 的授权个人或系统分享这些代码。未经授权访问这些验证码可能会危及您的数据和系统的安全性。
身份验证工作流
身份验证工作流程如下:
CCAI 平台会向宿主应用提供 SDK 密钥名称
(sdk_key_name)和 SDK 密钥 (sdk_key)。您可以在设置 > 开发者设置 > SDK 密钥中找到这些密钥。当最终用户开始使用 CCAI Platform 客户服务时,CCAI Platform SDK 会向宿主应用请求 JWT 签名。
CCAI Platform 会验证已签名的 JWT 并颁发最终用户身份验证令牌。此流程可确保主机应用与 CCAI 平台客服之间的身份验证安全无缝。
JWT 签名
宿主应用需要为每个平台实现一个回调方法。以下各部分提供了适用于各个平台的说明。
为了处理最终用户的信息,宿主应用需要填充 JWT 载荷。默认载荷通过回调方法提供,并且可能已包含一些值,例如推送令牌和默认名称。
宿主应用可以使用以下预留的键名添加有关用户的更多信息:
标识符(可选)
名称(可选)
电子邮件地址(选填)
手机号码(选填,格式为
E.164)
例如,对于 iOS SDK,该方法的实现可以如下所示(使用 JWT),以用于测试目的:
- (void)signPayload:(NSDictionry *)payload payloadType:(UjetPayloadType)payloadType success:(void (^)(NSString *))success ailure:(void (^)(NSError *))failure
{
if (payloadType == UjetPayloadAuthToken) {
@try {
NSString *companySecre = @"COMPANY_SECRET";
NSMutableDictionary *pyloadData = [payload mutableCopy];
payloadData[@"identifir"] = @"UNIQUE-IDENTIFIER"; // optional
payloadData[@"name"] =@"user name"; // optional
payloadData[@"email"] @"test@email.com"; // optional
payloadData[@"phone"] @""; // optional, E.164 format
payloadData[@"iss"] = "YOUR_COMPANY_NAME"; // optional
payloadData[@"iat"] = NSNumber numberWithDouble:[[NSDate date] timeIntervalSince1970]; // required
payloadData[@"exp"] = NSNumber numberWithDouble:([[NSDate date] timeIntervalSince1970]+ 600)]; // required
id<JWTAlgorithm> algorthm = [JWTAlgorithmFactory algorithmByName:@"HS256"];
NSString *signedToken [JWTBuilder encodePayload:payload].secret(companySecret).algorithm(algorithm).ecode;
success(signedToken);
}
@catch (NSError *error) {
failure(error);
}
}
}
生产示例
Google Cloud 建议在服务器端对载荷进行签名,以提高安全性。这样一来,公司密钥就不会在客户端公开,并且如果认为存在风险,可以随时撤消。与在客户端对载荷进行签名相比,这种方法可提供更高的安全性。
以下代码段提供了示例,展示了如何使用 Ruby on Rails 框架和 JWT gem 在服务器端对载荷进行签名,以及如何使用 iOS SDK、Android SDK 和 Web SDK 在客户端对载荷进行签名。
在服务器端,该代码设置了一个用于对载荷进行签名的 API 端点,使用 JWT gem 通过公司密钥对载荷进行编码,并将编码后的令牌返回给客户端。
在客户端,该代码提供了以下示例:从 iOS SDK、Android SDK 和 Web SDK 向服务器 API 发出请求以检索已签名的令牌。
在 iOS SDK 和 Android SDK 中,该代码向 API 发出 HTTP POST 请求,并从响应中检索令牌。在 Web SDK 中,代码实现了一个身份验证处理程序,该处理程序会向 API 发出 AJAX 请求,并将检索到的令牌和用户信息传递给 CCAI 平台初始化函数。
服务器上的 API 示例
本部分中的代码使用 Ruby 编写,并使用 Rails 框架。
假设宿主应用的基本网址为 https://company.com/api/。如需为 CCAI 平台对载荷进行签名,您可以在 https://company.com/api/ccaip/sign 添加另一个 API 端点。
该代码向应用路由文件添加了一个新路由,以处理对 /api/ccaip/sign 网址的 POST 请求。
ccaip_controller.rb 文件定义了 CCAIPController 类,该类具有一个名为 sign 的端点。该端点用于为 CCAI 平台签署载荷。
在代码中,COMPANY_SECRET 定义为用于为载荷签名的密钥。有效载荷从请求正文中提取,然后向其中添加各种值,例如唯一标识符、用户名、电子邮件地址和手机号码。
JWT.encode 方法用于将载荷和 ccaip_secret 编码为 JSON Web 令牌 (JWT),然后以 JSON 对象的形式在响应中返回,其中包含令牌密钥。
# routes.rb
post 'ccaip/sign' => "ccaip#sign"
# ccaip_controller.rb
class CCAIPController
def sign
ccaip_secret = "COMPANY_SECRET"
payload = body["payload"]
payload["identifier"] = "UNIQUE-IDENTIFIER" # optional
payload["name"] = "user name" # optional
payload["email"] = "test@email.com" # optional
payload["phone"] = "" # optional, E.164 format
payload["iss"] = "YOUR_COMPANY_NAME"
payload["iat"] = Time.now
payload["exp"] = Time.now.to_i + 10.minutes # valid for only 10 minutes from now.
token = JWT.encode(payload, ccaip_secret)
render json: {token: token}
end
end
通过 iOS SDK 进行签名
以下示例展示了如何使用 iOS SDK 对载荷进行签名。
它会向网址 https://your.company.com/api/ccaip/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/ccaip/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 SDK 函数的实现,用于使用 Retrofit(Android 的 HTTP 客户端)对载荷进行签名。该函数以载荷、载荷类型和令牌回调作为输入。如果载荷类型为 UjetPayloadType.AuthToken,则会创建一个 Retrofit 实例,并使用该实例向 https://company.com/api API 端点发出请求,以对载荷进行签名。它会在 tokenCallback 实例的 onToken 方法中返回已签名的令牌。如果失败,则显示一条消息框消息“身份验证失败”。
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) {
// YOU SHOULD HAVE THIS KIND OF API ON YOUR SERVER
$.ajax({
type: 'POST',
url: 'http://company.com/api/ccaip/sign',
data: JSON.stringify({
payload: {
identifier: 'UNIQUE-Identifier',
name: 'Test user'
}
}),
success: function(result) {
// YOU SHOULD CALL `callback` FUNCTION TO RESPONSE THE AUTHENTICATION REQUEST
callback({
token: result.token,
user: {
identifier: 'UNIQUE-IDENTIFIER',
name: 'Test user'
}
});
}
});
}
}
}).then(function() {
// successfully initialized
}).catch(function(error) {
// HANDLE INITIALIZATION ERROR
// you can handle an error occurred during initialization
});
});
身份验证令牌交换
在 CCAI 平台中,宿主应用使用 JWT(JSON Web 令牌)对最终用户的身份验证令牌进行签名,然后将该令牌换成最终用户身份验证令牌。JWT 是一种开放标准,用于以 JSON 对象的形式安全地传输信息。
最终用户身份验证令牌用于访问 CCAI 平台 API。此机制有助于确保身份验证过程的安全,并确保只有经过授权的用户才能访问 API。