IBM Security Verify WebAuthn Relying Party Server for Swift

IBM Security Verify WebAuthn Relying Party Server for Swift 基于 Vapor 框架,并公开了一些端点,这些端点会将 OAuth 和 FIDO2 请求从 Web 和移动客户端代理到 IBM Security Verify。

入门指南

先决条件中的资源链接说明并演示了如何创建新租户,并自动化 Relying Party Server 使用的应用程序和 FIDO2 配置。

先决条件

配置服务器

环境变量

relying-party-server 需要几个环境变量才能启动。

PLATFORM

platform 标志指示 relying party 服务器是 IBM Security Verify (ISV) 还是 IBM Security Verify Access (ISVA)。 例如:

PLATFORM=ISV

AUTH_SESSION

(可选) 当 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_APP_SITE_ASSOC

这是一个字符串,表示 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_ASSET_LINKS

这是一个字符串,表示 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 数字资产链接

FIDO2_RELYING_PARTY_ID

这是在 IBM Security Verify 中创建 FIDO2 服务时创建的唯一标识符 (UUID)。 例如:

FIDO2_RELYING_PARTY_ID=634cd513-dc6a-5e28-06fg-40c3dc81a79e

有关更多信息,请参见检索 relying party 配置列表查找 Relying Party ID

API_CLIENT_IDAPI_CLIENT_SECRET

这是唯一的客户端标识符和机密客户端密钥,relying party 服务器在内部使用它们来建立与 FIDO2 和 factors 端点的经过身份验证的会话。 例如:

API_CLIENT_ID=40c3dc81a79e-dc6a-5e28-06fg-634cd513
API_CLIENT_SECRET=a1b2c3d4

有关更多信息,请参见 FIDO2

AUTH_CLIENT_IDAUTH_CLIENT_SECRET

这是唯一的客户端标识符和机密客户端密钥,relying party 服务器在内部使用它们来建立与 OIDC 令牌端点的经过身份验证的会话。 例如:

AUTH_CLIENT_ID=40c3dc81a79e-dc6a-5e28-06fg-634cd513
AUTH_CLIENT_SECRET=a1b2c3d4

有关更多信息,请参见 客户端凭据

BASE_URL

base URL 是您租户的完全限定主机名。 例如:

BASE_URL=https://example.verify.ibm.com

HTTP_PROXY

(可选) 允许将对 relying party 服务器的代理请求转发到 BASE_URL 定义的主机。 例如:

HTTP_PROXY=https://proxy.example.verify.ibm.com:8888

注意:通过将环境变量设置为以下值,支持经过身份验证的代理:

HTTP_PROXY=https://username:password@proxy.example.verify.ibm.com:8888

ROOT_CA

(可选) 将其他证书添加到信任存储区以进行 TLS 请求验证。 例如:

ROOT_CA=t4Ck1jbktkQT09Ci0tLS0tRU5EIENFUlRJRklDQVRFLS0tLS0=

注意:ROOT_CA 值必须是从 Privacy Enhanced Mail (PEM) 证书文本进行 base64 编码。

LOG_LEVEL

(可选) 输出日志消息以进行诊断。 以下是可接受的值和描述。

名称 描述
TRACE 适用于包含通常仅在跟踪程序执行时使用的信息的消息。
DEBUG 适用于包含通常仅在调试程序时使用的信息的消息。
INFO 适用于信息性消息。
NOTICE 适用于不是错误情况但可能需要特殊处理的情况。
WARNING 适用于不是错误情况但比通知更严重的消息。
ERROR 适用于错误情况。
CRITICAL 适用于通常需要立即关注的严重错误情况。

注意:默认值为 INFO 日志记录级别。 在生产环境中运行时,使用 NOTICE 来提高性能。

端点

GET /.well-known/apple-app-site-association

返回表示 APPLE_APP_SITE_ASSOC 环境变量的 JSON 内容。

GET /.well-known/assetlinks.json

返回表示 GOOGLE_ASSET_LINKS 环境变量的 JSON 内容。

POST /v1/authenticate

当用户有一个使用密码的现有帐户时,执行 ROPC 请求到令牌端点。 以下是请求有效负载的示例

{
    "username": "anne_johnson@icloud.com",
    "password": "a1b2c3d4"
}

如果成功,则响应格式如下

{
    "id_token": "eyJ0eXA.2NDUxMjV9.5Od-8LjVM",
    "token_type": "Bearer",
    "access_token": "6ImNsb3VkSWRlbnRpdHlSZW",
    "expires_in": 604800
}

POST /v1/signup

允许创建一个新帐户,其中电子邮件的所有权经过验证。 以下是请求有效负载的示例

{
    "name": "Anne Johnson", 
    "email": "anne_johnson@icloud.com"
}

如果成功,则响应格式如下

{
    "expiry": "2022-11-28T12:26:34Z",
    "correlation": "1719",
    "transactionId": "95f36a22-558a-438b-bdac-1490f279bb0d"
}

POST /v1/validate

验证由 signup 生成的一次性密码。 以下是请求有效负载的示例

{
    "transactionId": "95f36a22-558a-438b-bdac-1490f279bb0d",
    "otp": "12345"
}

如果成功,则响应格式如下

{
    "id_token": "eyJ0eXA.2NDUxMjV9.5Od-8LjVM",
    "token_type": "Bearer",
    "access_token": "6ImNsb3VkSWRlbnRpdHlSZW",
    "expires_in": 604800
}

POST /v1/register

为用户注册新的公钥凭据。 以下是请求有效负载的示例

{
    "nickname": "John's iPhone",
    "clientDataJSON": "eyUyBg8Li8GH...",
    "attestationObject": "o2M884Yt0a3B7...",
    "credentialId": "VGhpcyBpcyBh..."
}

如果成功,则响应状态为 201 Created

必须在请求授权标头中提供 access_token。 经过身份验证的会话 cookie 也可以在请求标头中传递。 例如:

Authorization: Bearer NLL8EtOJFdbPiwPwZ

否则,将导致 401 Unauthorized

POST /v1/challenge

生成新的 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

POST /v1/signin

验证用户具有现有注册的公钥凭据。 以下是请求有效负载的示例

{
    "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 文件中查看许可证。