本页面提供了使用 SAML 身份验证协议在 Cloudflare Access 中设置 SaaS 应用程序的通用说明。
- 在 Cloudflare One 中配置的身份提供商
- 对 SaaS 应用程序账户的管理员访问权限
从您的 SaaS 应用程序账户中获取以下 URL:
- Entity ID(实体 ID):为您的 SaaS 应用程序签发的唯一 URL,例如
https://<your-domain>.my.salesforce.com。 - Assertion Consumer Service URL(断言使用者服务 URL):服务提供商用于接收和解析 SAML 断言的端点。
-
在 Cloudflare 仪表板 ↗中,转到 Zero Trust > Access controls(访问控制)> Applications(应用程序)。
-
选择 Create new application(创建新应用程序)。
-
选择 SaaS application(SaaS 应用程序)。
-
从下拉菜单中选择您的 Application(应用程序)。如果您的应用程序未列出,请在 Application(应用程序) 字段中输入自定义名称,并选择下方出现的文本框。
-
选择 SAML。
-
选择 Add application(添加应用程序)。
-
输入从您的 SaaS 应用程序账户中获取的 **Entity ID(实体 ID)**和 Assertion Consumer Service URL(断言使用者服务 URL)。
-
选择您的 SaaS 应用程序所预期的 Name ID format(名称 ID 格式)(通常是 Email)。
-
(可选)配置您的 SaaS 应用程序所需的任何其他 SAML 属性声明。
-
复制 SSO endpoint(SSO 端点)、**Access Entity ID or Issuer(Access 实体 ID 或签发者)**和 Public key(公钥)。
在 Access policies 下,添加现有策略或创建新策略,以控制哪些用户可以连接到您的应用程序。所有 Access 应用程序默认均为拒绝状态——用户必须匹配 Allow 策略才能被授予访问权限。
配置用户的身份验证方式:
选择您希望为应用程序启用的身份提供商。
(推荐)如果您计划仅允许通过单一 IdP 进行访问,请开启 Apply instant authentication。最终用户将不会看到 Cloudflare Access 登录页面,Cloudflare 将直接将用户重定向到您的 SSO 登录事件。
- (可选)开启 Authenticate with Cloudflare One Client,允许用户使用其 Cloudflare One Client 会话身份对应用程序进行身份验证。
-
(可选)转到 **Additional settings(其他设置)**以自定义应用程序体验:
- App Launcher customization(应用启动器自定义):配置此应用程序在应用启动器中对用户的显示方式。
自定义拦截页面:选择用户被拒绝访问应用程序时将看到的内容。
-
选择 Create(创建)。
接下来,配置您的 SaaS 应用程序以要求用户通过 Cloudflare Access 进行登录。有关如何配置第三方 SAML SSO 提供商的说明,请参阅您的 SaaS 应用程序文档。您将需要来自 Cloudflare One 的以下值:
- SSO endpoint(SSO 端点)
- Access Entity ID or Issuer(Access 实体 ID 或签发者)
- Public key(公钥)
您可以手动将此数据输入到您的 SaaS 应用程序中,也可以上传元数据 XML 文件。元数据位于以下 URL:<SSO endpoint>/saml-metadata。
当充当 SAML 身份提供商时,Cloudflare 将使用 SHA-256 算法对 SAML Response 和 SAML Assertion 进行签名。SaaS 应用程序可以使用您上传到 SaaS 应用程序的 **Public key(公钥)**来验证该签名。
打开无痕/隐私浏览器窗口,并转到 SaaS 应用程序的登录 URL。您将被重定向到 Cloudflare Access 登录页面,并被提示使用您的身份提供商进行登录。
SAML 属性是指在成功身份验证后,Cloudflare Access 与您的 SAML SaaS 应用程序共享的用户身份特征。默认情况下,Cloudflare Access 会向 SaaS 应用程序传递以下属性(如果可用):
id- 用户的 Access 身份的 UUIDname- 用户的全名(例如,John Doe)email- 用户的电子邮件地址groups- 身份提供商的组成员身份
在 Access for SaaS 中,您可以添加其他 SAML 属性或自定义发送给 SaaS 应用程序的 SAML 声明。这允许您集成具有特定 SAML 属性要求的 SaaS 应用程序。
要向您的 SaaS 应用程序发送其他 SAML 属性,请为每个属性配置以下字段:
- Name(名称):SAML 属性名称
- SAML friendly name(SAML 友好名称):(可选)SAML 属性的人类可读名称
- Name format(名称格式):指定 SaaS 应用程序预期的 **Name(名称)**格式:
Unspecified:(默认)不需要特定格式。URI:名称采用诸如urn:ietf:params:scim:schemas:core:2.0:User:userName或urn:oid:2.5.4.42的格式。Basic:名称是普通字符串,例如userName。
- IdP claim(IdP 声明):应该映射到此 SAML 属性的身份提供商值。您可以选择在 Cloudflare One IdP 集成中配置的任何 SAML 属性或 OIDC 声明。
- Required(必需):如果某个属性被标记为必需,但 IdP 未提供,Cloudflare 将导致身份验证请求失败并显示错误页面。
- Add per IdP claim(按 IdP 声明添加):(可选)如果您为该 SaaS 应用程序启用了多个身份提供商,您可以为每个 IdP 选择不同的属性映射。这些值将覆盖父级 IdP claim(IdP 声明)。
在 Advanced settings(高级设置)> **Transformation(转换)**中,您可以输入一个 JSONata ↗ 脚本来修改 User Registry identity(用户注册表身份)的副本。这对于设置默认值、排除电子邮件地址或确保用户名符合任意标准非常有用。Access 将把修改后的用户身份作为 SAML 属性发送给 SaaS 应用程序。
这对应于 Access 应用程序 API 中的 saml_attribute_transform_jsonata 字段。
例如,以下 JSONata 脚本将组名合并到一个列表中,并添加一个映射到用户电子邮件的 eduPersonPrincipalName 字段。
$merge([$, {"groups": groups.name, 'eduPersonPrincipalName': email}])以下是应用 JSONata 转换前用户身份的示例:
{
"account_id": "699d98642c564d2e855e9661899b7252",
"amr": [
"pwd"
],
"auth_status": "NONE",
"common_name": "",
"device_id": "c1744f8b-faa1-48a4-9e5c-02ac921467fa",
"device_sessions": {
"49e653db-991e-11ee-af26-2243bf8c3428": {
"last_authenticated": 1703004275
}
},
"devicePosture": {
"8534a230-e85e-4183-8964-a4b7dcf72986": {
"rule_name": "Warp",
"success": true,
"type": "warp"
}
},
"email": "[email protected]",
"gateway_account_id": "bTSquyUGwLQjYJn8cI8S1h6M6wU",
"geo": {
"country": "US"
},
"groups": [
{
"id": "12fdf91a-fb23-41b3-995a-de2f72c61d0e",
"name": "IdentityProtection-RiskyUser-RiskLevel-low"
},
{
"id": "12348f47-8234-4860-a03f-c2a1513f267b",
"name": "Global Administrator"
},
{
"id": "11235980-87d7-4917-b0aa-74c01914c40e",
"name": "Application Administrator"
}
],
"iat": 1659474397,
"id": "OidHvkPt-I-13IBSnd77UJ8cHgsrUpjs3W6_4t6ES7M",
"idp": {
"id": "b08e8c0c-a75d-4b3f-8e7b-cd427b7c7b47",
"type": "azureAD"
}
}应用示例 JSONata 脚本后的结果:
{
"account_id": "699d98642c564d2e855e9661899b7252",
"amr": [
"pwd"
],
"auth_status": "NONE",
"common_name": "",
"device_id": "c1744f8b-faa1-48a4-9e5c-02ac921467fa",
"device_sessions": {
"49e653db-991e-11ee-af26-2243bf8c3428": {
"last_authenticated": 1703004275
}
},
"devicePosture": {
"8534a230-e85e-4183-8964-a4b7dcf72986": {
"rule_name": "Warp",
"success": true,
"type": "warp"
}
},
"email": "[email protected]",
"gateway_account_id": "bTSquyUGwLQjYJn8cI8S1h6M6wU",
"geo": {
"country": "US"
},
"groups": [
"IdentityProtection-RiskyUser-RiskLevel-low",
"Global Administrator",
"Application Administrator"
],
"iat": 1659474397,
"id": "OidHvkPt-I-13IBSnd77UJ8cHgsrUpjs3W6_4t6ES7M",
"idp": {
"id": "b08e8c0c-a75d-4b3f-8e7b-cd427b7c7b47",
"type": "azureAD"
},
"eduPersonPrincipalName": "[email protected]"
}有关更多 JSONata 转换用例,请参阅以下示例。
删除 groups 属性
以下 JSONata 脚本删除 groups SAML 属性。如果您的 SaaS 应用程序不需要接收用户组信息,这会很有用。
$ ~> |$|{}, ['groups']|应用 JSONata 转换后的结果:
{
"account_id": "699d98642c564d2e855e9661899b7252",
"amr": [
"pwd"
],
"auth_status": "NONE",
"common_name": "",
"device_id": "c1744f8b-faa1-48a4-9e5c-02ac921467fa",
"device_sessions": {
"49e653db-991e-11ee-af26-2243bf8c3428": {
"last_authenticated": 1703004275
}
},
"devicePosture": {
"8534a230-e85e-4183-8964-a4b7dcf72986": {
"rule_name": "Warp",
"success": true,
"type": "warp"
}
},
"email": "[email protected]",
"gateway_account_id": "bTSquyUGwLQjYJn8cI8S1h6M6wU",
"geo": {
"country": "US"
},
"iat": 1659474397,
"id": "OidHvkPt-I-13IBSnd77UJ8cHgsrUpjs3W6_4t6ES7M",
"idp": {
"id": "b08e8c0c-a75d-4b3f-8e7b-cd427b7c7b47",
"type": "azureAD"
}
}重命名 groups 字段并删除组 ID
以下 JSONata 脚本将 groups.name 字段从 name 更改为 group_name,并删除 groups.id 字段:
{
"account_id": account_id,
"amr": amr,
"auth_status": auth_status,
"common_name": common_name,
"devicePosture": devicePosture,
"device_id": device_id,
"device_sessions": device_sessions,
"email": email,
"gateway_account_id": gateway_account_id,
"geo": geo,
"groups": $map($.groups, function($group) {
{"group_name": $group.name}}),
"iat": iat,
"id": id,
"idp": idp
}应用 JSONata 转换后的结果:
{
"account_id": "699d98642c564d2e855e9661899b7252",
"amr": [
"pwd"
],
"auth_status": "NONE",
"common_name": "",
"devicePosture": {
"8534a230-e85e-4183-8964-a4b7dcf72986": {
"rule_name": "Warp",
"success": true,
"type": "warp"
}
},
"device_id": "c1744f8b-faa1-48a4-9e5c-02ac921467fa",
"device_sessions": {
"49e653db-991e-11ee-af26-2210bf8c3428": {
"last_authenticated": 1703004275
}
},
"email": "[email protected]",
"gateway_account_id": "bTSquyUGwLQjYJn8cI8S1h6M6wU",
"geo": {
"country": "US"
},
"groups": [
{
"group_name": "IdentityProtection-RiskyUser-RiskLevel-low"
},
{
"group_name": "Global Administrator"
},
{
"group_name": "Application Administrator"
}
],
"iat": 1659474397,
"id": "OidHvkPt-I-13IBSnd77UJ8cHgsrUpjs3W6_4t6ES7M",
"idp": {
"id": "b08e8c0c-a75d-4b3f-8e7b-cd427b7c7b47",
"type": "azureAD"
}
}按名称过滤组
以下 JSONata 脚本将组过滤为与正则表达式匹配的组。
$merge([$, { "groups": $filter(groups, function($v) { $contains($v.name, /Administrator/) }) }])应用 JSONata 转换后的结果:
{
"account_id": "699d98642c564d2e855e9661899b7252",
"amr": [
"pwd"
],
"auth_status": "NONE",
"common_name": "",
"device_id": "c1744f8b-faa1-48a4-9e5c-02ac921467fa",
"device_sessions": {
"49e653db-991e-11ee-af26-2243bf8c3428": {
"last_authenticated": 1703004275
}
},
"devicePosture": {
"8534a230-e85e-4183-8964-a4b7dcf72986": {
"rule_name": "Warp",
"success": true,
"type": "warp"
}
},
"email": "[email protected]",
"gateway_account_id": "bTSquyUGwLQjYJn8cI8S1h6M6wU",
"geo": {
"country": "US"
},
"groups": [
{
"id": "12348f47-8234-4860-a03f-c2a1513f267b",
"name": "Global Administrator"
},
{
"id": "11235980-87d7-4917-b0aa-74c01914c40e",
"name": "Application Administrator"
}
],
"iat": 1659474397,
"id": "OidHvkPt-I-13IBSnd77UJ8cHgsrUpjs3W6_4t6ES7M",
"idp": {
"id": "b08e8c0c-a75d-4b3f-8e7b-cd427b7c7b47",
"type": "azureAD"
}
}默认情况下,Access 将用户的电子邮件地址作为 SAML NameID 发送。某些 SaaS 应用程序需要不同的值,例如员工 ID、修改后的电子邮件地址或来自旧系统的用户名。
您可以通过 Access 应用程序 API,在 SaaS 应用程序上设置 name_id_transform_jsonata 字段来自定义 NameID。该字段接受针对用户身份进行评估的 JSONata ↗ 表达式,并且必须返回单个字符串值。该结果将替换 SAML 断言中的默认 NameID。
例如,修改用户的电子邮件使其包含 +sandbox 后缀(当连接同一 SaaS 应用的多个实例时很有用):
curl --request PUT \
https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps/{app_id} \
--header "Authorization: Bearer {api_token}" \
--header "Content-Type: application/json" \
--data '{
"saas_app": {
"auth_type": "saml",
"name_id_transform_jsonata": "$substringBefore(email, '\''@'\'') & '\''+sandbox@'\'' & $substringAfter(email, '\''@'\'')"
}
}'对于电子邮件为 [email protected] 的用户,此表达式产生的 NameID 为 [email protected]。
使用员工 ID 作为 NameID
要发送非电子邮件属性(例如员工 ID),请在 JSONata 表达式中直接引用该属性名称。该属性必须在来自 IdP 的用户身份中可用。
curl --request PUT \
https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps/{app_id} \
--header "Authorization: Bearer {api_token}" \
--header "Content-Type: application/json" \
--data '{
"saas_app": {
"auth_type": "saml",
"name_id_transform_jsonata": "employee_id"
}
}'对于包含 "employee_id": "efgh5678" 的用户身份,在 SAML 断言中发送的 NameID 将是 efgh5678。
删除 NameID 转换
要恢复到默认行为(将用户的电子邮件作为 NameID 发送),请将该字段设置为空字符串:
curl --request PUT \
https://api.cloudflare.com/client/v4/accounts/{account_id}/access/apps/{app_id} \
--header "Authorization: Bearer {api_token}" \
--header "Content-Type: application/json" \
--data '{
"saas_app": {
"auth_type": "saml",
"name_id_transform_jsonata": ""
}
}'