IBM Security Verify WebAuthn Relying Party Server for Swift 基于 Vapor 框架,并公开了一些端点,这些端点会将 OAuth 和 FIDO2 请求从 Web 和移动客户端代理到 IBM Security Verify。
先决条件中的资源链接说明并演示了如何创建新租户,并自动化 Relying Party Server 使用的应用程序和 FIDO2 配置。
在此处创建一个免费试用租户:https://www.ibm.com/account/reg/us-en/signup?formid=urx-30041。
您需要一个 IBMid,但可以同时完成注册。
此链接说明了如何设置租户:https://docs.verify.ibm.com/verify/docs/signing-up-for-a-free-trial
在试用租户上创建一个 API 客户端。请参阅此配置指南获取说明。
确保 API 客户端具有以下权利
克隆 relying party 存储库。在终端窗口中运行此命令
git clone https://github.com/ibm-security-verify/webauthn-relying-party-server.git
修改 config.json
以使用在上一步中创建的 API 客户端中的客户端标识符和客户端密钥。
relyingPartyHostname
是运行 relying party 服务器的 Docker 主机。
以下是 config.json
的示例。
{
"tenantUrl":"https://example.verify.ibm.com",
"clientSecret":"abc123",
"clientId":"abc123-a1b2-4567-a1b2-c3d4e5f6",
"appName": "Passkey Starter Kit",
"relyingPartyHostname": "example.com"
}
使用 starter-kit.py
在您的租户上创建应用程序和 FIDO2 relying party。
运行此命令以创建应用程序和 FIDO2 relying party
python3 starter-kit.py -f config.json
注意:在 MAC M1 上,在 Python 命令前添加前缀:
arch -arm64 python3 starter-kit.py -f config.json
starter-kit.py
的输出是一个 .env
文件,可用于配置 relying party 服务器环境变量。.env
文件将位于执行 starter-lit.py
的同一文件夹中。
relying-party-server 需要几个环境变量才能启动。
platform 标志指示 relying party 服务器是 IBM Security Verify (ISV) 还是 IBM Security Verify Access (ISVA)。 例如:
PLATFORM=ISV
(可选) 当 PLATFORM=ISVA
时,AUTH_SESSION
允许 relying party 服务器解析 /v1/signin
响应中的 JSON 数据,以生成经过身份验证的会话。 可用的值包括:
名称 | 描述 |
---|---|
EAI | 要求 FIDO2 介体在 credentialData JSON 有效负载中提供额外的凭据信息。 |
TOKEN | 如果未提供 AUTH_SESSION (或提供了无效值),则这是默认值。 要返回令牌,它需要 FIDO2 介体将 access_token 注入到 JSON 有效负载的 responseData 元素中。 |
COOKIE | 将 FIDO assertion/result 端点的响应返回到调用客户端。 |
有关更多信息,请参见 IBM Security Verify Access FIDO Mediation。
这是一个字符串,表示 Apple 用于在域和您的应用程序之间建立安全关联的 JSON。 以下 JSON 代码表示简单关联的内容
{
"webcredentials":{
"apps":[
"ABCDE12345.com.example.app"
]
}
}
将 JSON 内容分配给环境变量时应将其最小化。 例如:
APPLE_APP_SITE_ASSOC={"webcredentials":{"apps":["ABCDE12345.com.example.app"]}}
此外,您的 iOS 移动应用程序需要一个引用 relyingPartyHostname
的关联域条目。 例如:
webcredential:example.com
有关更多信息,请参见 支持关联域。
这是一个字符串,表示 Google 用于在应用程序和网站之间关联登录凭据的 JSON。 以下 JSON 代码表示简单 assetlink 格式的内容
[{
"relation": ["delegate_permission/common.get_login_creds"],
"target": {
"namespace": "web",
"site": "https://example.com"
}
},
{
"relation": ["delegate_permission/common.get_login_creds"],
"target": {
"namespace": "android_app",
"package_name": "com.example.app",
"sha256_cert_fingerprints": [
"DE:AD:BE:EF:****"
]
}
}]
将 JSON 内容分配给环境变量时应将其最小化。 例如:
GOOGLE_ASSET_LINKS=[{"relation":["delegate_permission/common.get_login_creds"],"target":{"namespace":"web","site":"https://example.com"}},{"relation":["delegate_permission/common.get_login_creds"],"target":{"namespace":"android_app","package_name":"com.exampl.app","sha256_cert_fingerprints":["DE:AD:BE:EF:****"]}}]
有关更多信息,请参见 Google 数字资产链接。
这是在 IBM Security Verify 中创建 FIDO2 服务时创建的唯一标识符 (UUID)。 例如:
FIDO2_RELYING_PARTY_ID=634cd513-dc6a-5e28-06fg-40c3dc81a79e
有关更多信息,请参见检索 relying party 配置列表 或 查找 Relying Party ID。
这是唯一的客户端标识符和机密客户端密钥,relying party 服务器在内部使用它们来建立与 FIDO2 和 factors 端点的经过身份验证的会话。 例如:
API_CLIENT_ID=40c3dc81a79e-dc6a-5e28-06fg-634cd513
API_CLIENT_SECRET=a1b2c3d4
有关更多信息,请参见 FIDO2。
这是唯一的客户端标识符和机密客户端密钥,relying party 服务器在内部使用它们来建立与 OIDC 令牌端点的经过身份验证的会话。 例如:
AUTH_CLIENT_ID=40c3dc81a79e-dc6a-5e28-06fg-634cd513
AUTH_CLIENT_SECRET=a1b2c3d4
有关更多信息,请参见 客户端凭据。
base URL 是您租户的完全限定主机名。 例如:
BASE_URL=https://example.verify.ibm.com
(可选) 允许将对 relying party 服务器的代理请求转发到 BASE_URL
定义的主机。 例如:
HTTP_PROXY=https://proxy.example.verify.ibm.com:8888
注意:通过将环境变量设置为以下值,支持经过身份验证的代理:
HTTP_PROXY=https://username:password@proxy.example.verify.ibm.com:8888
(可选) 将其他证书添加到信任存储区以进行 TLS 请求验证。 例如:
ROOT_CA=t4Ck1jbktkQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0=
注意:
ROOT_CA
值必须是从 Privacy Enhanced Mail (PEM) 证书文本进行 base64 编码。
(可选) 输出日志消息以进行诊断。 以下是可接受的值和描述。
名称 | 描述 |
---|---|
TRACE | 适用于包含通常仅在跟踪程序执行时使用的信息的消息。 |
DEBUG | 适用于包含通常仅在调试程序时使用的信息的消息。 |
INFO | 适用于信息性消息。 |
NOTICE | 适用于不是错误情况但可能需要特殊处理的情况。 |
WARNING | 适用于不是错误情况但比通知更严重的消息。 |
ERROR | 适用于错误情况。 |
CRITICAL | 适用于通常需要立即关注的严重错误情况。 |
注意:默认值为
INFO
日志记录级别。 在生产环境中运行时,使用NOTICE
来提高性能。
返回表示 APPLE_APP_SITE_ASSOC
环境变量的 JSON 内容。
返回表示 GOOGLE_ASSET_LINKS
环境变量的 JSON 内容。
当用户有一个使用密码的现有帐户时,执行 ROPC 请求到令牌端点。 以下是请求有效负载的示例
{
"username": "anne_johnson@icloud.com",
"password": "a1b2c3d4"
}
如果成功,则响应格式如下
{
"id_token": "eyJ0eXA.2NDUxMjV9.5Od-8LjVM",
"token_type": "Bearer",
"access_token": "6ImNsb3VkSWRlbnRpdHlSZW",
"expires_in": 604800
}
允许创建一个新帐户,其中电子邮件的所有权经过验证。 以下是请求有效负载的示例
{
"name": "Anne Johnson",
"email": "anne_johnson@icloud.com"
}
如果成功,则响应格式如下
{
"expiry": "2022-11-28T12:26:34Z",
"correlation": "1719",
"transactionId": "95f36a22-558a-438b-bdac-1490f279bb0d"
}
验证由 signup
生成的一次性密码。 以下是请求有效负载的示例
{
"transactionId": "95f36a22-558a-438b-bdac-1490f279bb0d",
"otp": "12345"
}
如果成功,则响应格式如下
{
"id_token": "eyJ0eXA.2NDUxMjV9.5Od-8LjVM",
"token_type": "Bearer",
"access_token": "6ImNsb3VkSWRlbnRpdHlSZW",
"expires_in": 604800
}
为用户注册新的公钥凭据。 以下是请求有效负载的示例
{
"nickname": "John's iPhone",
"clientDataJSON": "eyUyBg8Li8GH...",
"attestationObject": "o2M884Yt0a3B7...",
"credentialId": "VGhpcyBpcyBh..."
}
如果成功,则响应状态为 201 Created
。
必须在请求授权标头中提供
access_token
。 经过身份验证的会话 cookie 也可以在请求标头中传递。 例如:Authorization: Bearer NLL8EtOJFdbPiwPwZ
否则,将导致
401 Unauthorized
。
生成新的 challenge 以执行 WebAuthn 注册或验证。
验证 (assertion)
以下是 assertion (signin) 的请求有效负载的示例
{
"type": "assertion"
}
如果成功,则响应格式是一个基于 Web Authentication: An API for assertion generation (PublicKeyCredentialRequestOptions) 的 JSON 结构,如下所示
{
"rpId": "example.com",
"timeout": 240000,
"challenge": "3W9xV1-n6Qvvs9y0YrAr5MpNNba8Q9czsGH4hRdGFwk"
}
注册 (attestation)
以下是 attestation 的请求有效负载的示例
{
"displayName": "Anne's iPhone",
"type": "attestation"
}
如果成功,则响应格式是一个基于 Web Authentication: An API for credential creation (PublicKeyCredentialCreationOptions) 的 JSON 结构,如下所示
{
"rp": {
"id": "example.com",
"name": "IBM Cloud Relying Party"
},
"user": {
"id": "ePGatpTNRBaoHdQ",
"name": "anne",
"displayName": "Anne's iPhone"
},
"timeout": 240000,
"challenge": "g9yz-s_rsH4c_ulfLujO96U1wybV_Zut5tQeoKIcmtk",
"excludeCredentials": [],
"extensions": {},
"authenticatorSelection": {},
"pubKeyCredParams": [
{
"alg": -7,
"type": "public-key"
},
{
"alg": -257,
"type": "public-key"
}
]
}
必须在请求授权标头中提供
access_token
。 例如:Authorization: Bearer NLL8EtOJFdbPiwPwZ
否则,将导致
401 Unauthorized
。
验证用户具有现有注册的公钥凭据。 以下是请求有效负载的示例
{
"clientDataJSON": "eyUyBg8Li8GH...",
"authenticatorData": "o2M884Yt0a3B7...",
"credentialId": "VGhpcyBpcyBh...",
"signature": "OP84jBpcyB...",
"userHandle": "ePGatpTNR..."
}
如果成功,则响应格式如下
{
"id_token": "eyJ0eXA.2NDUxMjV9.5Od-8LjVM",
"token_type": "Bearer",
"access_token": "6ImNsb3VkSWRlbnRpdHlSZW",
"expires_in": 604800
}
access_token
可用于向 relying party server 项目中的其他自定义端点发出请求。
Vapor 支持多种部署选项。 relying-party-server 包含一个 dockerfile
,用于通过 docker-compose build
构建镜像。 对于其他托管选项,请参阅 Vapor 文档。
此软件包包含根据 MIT 许可证(“许可证”)获得许可的代码。 您可以在此软件包的 LICENSE 文件中查看许可证。