Skip to content

Commit b69914d

Browse files
ranbelajhollandpatriciasantaana
authored
[ZT] Access for SaaS: SAML attributes (#20503)
* SAML attribute features * Update src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/generic-saml-saas.mdx Co-authored-by: Alex Holland <[email protected]> * Update src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/generic-saml-saas.mdx Co-authored-by: Alex Holland <[email protected]> * update groups example * add more JSONata examples * Update src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/generic-saml-saas.mdx Co-authored-by: Patricia Santa Ana <[email protected]> * Update src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/index.mdx Co-authored-by: Patricia Santa Ana <[email protected]> --------- Co-authored-by: Alex Holland <[email protected]> Co-authored-by: Patricia Santa Ana <[email protected]>
1 parent 9edf89d commit b69914d

File tree

2 files changed

+317
-3
lines changed

2 files changed

+317
-3
lines changed

src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/generic-saml-saas.mdx

Lines changed: 315 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ sidebar:
55
order: 1
66
---
77

8-
import { Render } from "~/components";
8+
import { Render, Details } from "~/components";
99

1010
This page provides generic instructions for setting up a SaaS application in Cloudflare Access using the SAML authentication protocol.
1111

@@ -39,9 +39,9 @@ Obtain the following URLs from your SaaS application account:
3939

4040
8. Select the **Name ID Format** expected by your SaaS application (usually _Email_).
4141

42-
9. Copy the **SSO endpoint**, **Access Entity ID or Issuer**, and **Public key**.
42+
9. (Optional) Configure any additional [SAML attribute statements](#saml-attributes) required by your SaaS application.
4343

44-
10. If your SaaS application requires additional **SAML attribute statements**, add the mapping of your IdP's attributes you would like to include in the SAML statement sent to the SaaS application.
44+
10. Copy the **SSO endpoint**, **Access Entity ID or Issuer**, and **Public key**.
4545

4646
:::note[IdP groups]
4747

@@ -77,3 +77,315 @@ When acting as a SAML identity provider, Cloudflare will sign both the SAML Resp
7777
## 4. Test the integration
7878

7979
Open an incognito browser window and go to the SaaS application's login URL. You will be redirected to the Cloudflare Access login screen and prompted to sign in with your identity provider.
80+
81+
## SAML attributes
82+
83+
[SAML attributes](/cloudflare-one/identity/idp-integration/generic-saml/#saml-headers-and-attributes) refer to the user identity characteristics that Cloudflare Access shares with your SAML SaaS application upon successful authentication. By default, Cloudflare Access passes the following attributes (if available) to the SaaS application:
84+
85+
- `id` - UUID of the user's Access identity
86+
- `name` - Full name of the user (for example, `John Doe`)
87+
- `email` - User's email address
88+
- `groups` - Identity provider group membership
89+
90+
In Access for SaaS, you can add additional SAML attributes or customize the SAML statement sent to the SaaS application. This allows you to integrate SaaS applications which have specific SAML attribute requirements.
91+
92+
### SAML attribute statements
93+
94+
To send additional SAML attributes to your SaaS application, configure the following fields for each attribute:
95+
96+
- **Name**: SAML attribute name
97+
- **SAML friendly name**: (Optional) A human readable name for the SAML attribute
98+
- **Name format**: Specify the **Name** format expected by the SaaS application:
99+
- `Unspecified`: (default) No specific format required.
100+
- `URI`: Name is in a format such as `urn:ietf:params:scim:schemas:core:2.0:User:userName` or `urn:oid:2.5.4.42`.
101+
- `Basic`: Name is a normal string such as `userName`.
102+
- **IdP claim**: The identity provider value that should map to this SAML attribute. You can select any [SAML attribute](/cloudflare-one/identity/idp-integration/generic-saml/#saml-headers-and-attributes) or [OIDC claim](/cloudflare-one/identity/idp-integration/generic-oidc/#oidc-claims) that was configured in a Zero Trust IdP integration.
103+
- **Required**: If a claim is marked as required but is not provided by an IdP, Cloudflare will fail the authentication request and show an error page.
104+
- **Add per IdP claim**: (Optional) If you turned on multiple identity providers for the SaaS application, you can choose different attribute mappings for each IdP. These values will override the parent **IdP claim**.
105+
106+
### JSONata transforms
107+
108+
In **Advanced settings** > **Transformation**, you can enter a [JSONata](https://jsonata.org/) script that modifies a copy of the [User Registry identity](/cloudflare-one/insights/logs/users/). This is useful for setting default values, excluding email addresses, or ensuring usernames meet arbitrary criteria. Access will send the modified user identity to the SaaS application as SAML attributes.
109+
110+
:::note
111+
JSONata transformations are not compatible with [SAML attribute statements](#saml-attribute-statements). JSONata transformations will override any specified SAML attributes.
112+
:::
113+
114+
For example, the following JSONata script merges group names into a list and adds an `eduPersonPrincipalName` field which maps to the user email.
115+
116+
```jsonata title = "JSONata expression"
117+
$merge([$, {"groups": groups.name, 'eduPersonPrincipalName': email}])
118+
```
119+
120+
Here is an example of a user identity before applying the JSONata transform:
121+
122+
```json title= "User identity before JSONata transform"
123+
{
124+
"account_id": "699d98642c564d2e855e9661899b7252",
125+
"amr": [
126+
"pwd"
127+
],
128+
"auth_status": "NONE",
129+
"common_name": "",
130+
"device_id": "c1744f8b-faa1-48a4-9e5c-02ac921467fa",
131+
"device_sessions": {
132+
"49e653db-991e-11ee-af26-2243bf8c3428": {
133+
"last_authenticated": 1703004275
134+
}
135+
},
136+
"devicePosture": {
137+
"8534a230-e85e-4183-8964-a4b7dcf72986": {
138+
"rule_name": "Warp",
139+
"success": true,
140+
"type": "warp"
141+
}
142+
},
143+
"email": "[email protected]",
144+
"gateway_account_id": "bTSquyUGwLQjYJn8cI8S1h6M6wU",
145+
"geo": {
146+
"country": "US"
147+
},
148+
"groups": [
149+
{
150+
"id": "12fdf91a-fb23-41b3-995a-de2f72c61d0e",
151+
"name": "IdentityProtection-RiskyUser-RiskLevel-low"
152+
},
153+
{
154+
"id": "12348f47-8234-4860-a03f-c2a1513f267b",
155+
"name": "Global Administrator"
156+
},
157+
{
158+
"id": "11235980-87d7-4917-b0aa-74c01914c40e",
159+
"name": "Application Administrator"
160+
}
161+
],
162+
"iat": 1659474397,
163+
"id": "OidHvkPt-I-13IBSnd77UJ8cHgsrUpjs3W6_4t6ES7M",
164+
"idp": {
165+
"id": "b08e8c0c-a75d-4b3f-8e7b-cd427b7c7b47",
166+
"type": "azureAD"
167+
}
168+
}
169+
```
170+
171+
Result after applying the example JSONata script:
172+
173+
```json output
174+
{
175+
"account_id": "699d98642c564d2e855e9661899b7252",
176+
"amr": [
177+
"pwd"
178+
],
179+
"auth_status": "NONE",
180+
"common_name": "",
181+
"device_id": "c1744f8b-faa1-48a4-9e5c-02ac921467fa",
182+
"device_sessions": {
183+
"49e653db-991e-11ee-af26-2243bf8c3428": {
184+
"last_authenticated": 1703004275
185+
}
186+
},
187+
"devicePosture": {
188+
"8534a230-e85e-4183-8964-a4b7dcf72986": {
189+
"rule_name": "Warp",
190+
"success": true,
191+
"type": "warp"
192+
}
193+
},
194+
"email": "[email protected]",
195+
"gateway_account_id": "bTSquyUGwLQjYJn8cI8S1h6M6wU",
196+
"geo": {
197+
"country": "US"
198+
},
199+
"groups": [
200+
"IdentityProtection-RiskyUser-RiskLevel-low",
201+
"Global Administrator",
202+
"Application Administrator"
203+
],
204+
"iat": 1659474397,
205+
"id": "OidHvkPt-I-13IBSnd77UJ8cHgsrUpjs3W6_4t6ES7M",
206+
"idp": {
207+
"id": "b08e8c0c-a75d-4b3f-8e7b-cd427b7c7b47",
208+
"type": "azureAD"
209+
},
210+
"eduPersonPrincipalName": "[email protected]"
211+
}
212+
```
213+
214+
For more JSONata transform use cases, refer to the following examples.
215+
216+
<Details header="Remove groups attribute">
217+
218+
The following JSONata script removes the `groups` SAML attribute. This can be useful if your SaaS application does not need to receive user group information.
219+
220+
```jsonata title="JSONata expression"
221+
$ ~> |$|{}, ['groups']|
222+
```
223+
224+
Result after applying the JSONata transform:
225+
```json output
226+
{
227+
"account_id": "699d98642c564d2e855e9661899b7252",
228+
"amr": [
229+
"pwd"
230+
],
231+
"auth_status": "NONE",
232+
"common_name": "",
233+
"device_id": "c1744f8b-faa1-48a4-9e5c-02ac921467fa",
234+
"device_sessions": {
235+
"49e653db-991e-11ee-af26-2243bf8c3428": {
236+
"last_authenticated": 1703004275
237+
}
238+
},
239+
"devicePosture": {
240+
"8534a230-e85e-4183-8964-a4b7dcf72986": {
241+
"rule_name": "Warp",
242+
"success": true,
243+
"type": "warp"
244+
}
245+
},
246+
"email": "[email protected]",
247+
"gateway_account_id": "bTSquyUGwLQjYJn8cI8S1h6M6wU",
248+
"geo": {
249+
"country": "US"
250+
},
251+
"iat": 1659474397,
252+
"id": "OidHvkPt-I-13IBSnd77UJ8cHgsrUpjs3W6_4t6ES7M",
253+
"idp": {
254+
"id": "b08e8c0c-a75d-4b3f-8e7b-cd427b7c7b47",
255+
"type": "azureAD"
256+
}
257+
}
258+
```
259+
</Details>
260+
261+
<Details header="Rename groups field and remove group ID">
262+
263+
The following JSONata script changes the `groups.name` field from `name` to `group_name` and removes the `groups.id` field:
264+
265+
```jsonata title="JSONata expression"
266+
{
267+
"account_id": account_id,
268+
"amr": amr,
269+
"auth_status": auth_status,
270+
"common_name": common_name,
271+
"devicePosture": devicePosture,
272+
"device_id": device_id,
273+
"device_sessions": device_sessions,
274+
"email": email,
275+
"gateway_account_id": gateway_account_id,
276+
"geo": geo,
277+
"groups": $map($.groups, function($group) {
278+
{"group_name": $group.name}}),
279+
"iat": iat,
280+
"id": id,
281+
"idp": idp
282+
}
283+
```
284+
285+
Result after applying the JSONata transform:
286+
287+
```json output
288+
{
289+
"account_id": "699d98642c564d2e855e9661899b7252",
290+
"amr": [
291+
"pwd"
292+
],
293+
"auth_status": "NONE",
294+
"common_name": "",
295+
"devicePosture": {
296+
"8534a230-e85e-4183-8964-a4b7dcf72986": {
297+
"rule_name": "Warp",
298+
"success": true,
299+
"type": "warp"
300+
}
301+
},
302+
"device_id": "c1744f8b-faa1-48a4-9e5c-02ac921467fa",
303+
"device_sessions": {
304+
"49e653db-991e-11ee-af26-2210bf8c3428": {
305+
"last_authenticated": 1703004275
306+
}
307+
},
308+
"email": "[email protected]",
309+
"gateway_account_id": "bTSquyUGwLQjYJn8cI8S1h6M6wU",
310+
"geo": {
311+
"country": "US"
312+
},
313+
"groups": [
314+
{
315+
"group_name": "IdentityProtection-RiskyUser-RiskLevel-low"
316+
},
317+
{
318+
"group_name": "Global Administrator"
319+
},
320+
{
321+
"group_name": "Application Administrator"
322+
}
323+
],
324+
"iat": 1659474397,
325+
"id": "OidHvkPt-I-13IBSnd77UJ8cHgsrUpjs3W6_4t6ES7M",
326+
"idp": {
327+
"id": "b08e8c0c-a75d-4b3f-8e7b-cd427b7c7b47",
328+
"type": "azureAD"
329+
}
330+
}
331+
```
332+
333+
</Details>
334+
335+
<Details header="Filter groups by name">
336+
337+
The following JSONata script filters groups to those that match a regular expression.
338+
339+
```jsonata title="JSONata expression"
340+
$merge([$, { "groups": $filter(groups, function($v) { $contains($v.name, /Administrator/) }) }])
341+
```
342+
343+
Result after applying the JSONata transform:
344+
345+
```json output
346+
{
347+
"account_id": "699d98642c564d2e855e9661899b7252",
348+
"amr": [
349+
"pwd"
350+
],
351+
"auth_status": "NONE",
352+
"common_name": "",
353+
"device_id": "c1744f8b-faa1-48a4-9e5c-02ac921467fa",
354+
"device_sessions": {
355+
"49e653db-991e-11ee-af26-2243bf8c3428": {
356+
"last_authenticated": 1703004275
357+
}
358+
},
359+
"devicePosture": {
360+
"8534a230-e85e-4183-8964-a4b7dcf72986": {
361+
"rule_name": "Warp",
362+
"success": true,
363+
"type": "warp"
364+
}
365+
},
366+
"email": "[email protected]",
367+
"gateway_account_id": "bTSquyUGwLQjYJn8cI8S1h6M6wU",
368+
"geo": {
369+
"country": "US"
370+
},
371+
"groups": [
372+
{
373+
"id": "12348f47-8234-4860-a03f-c2a1513f267b",
374+
"name": "Global Administrator"
375+
},
376+
{
377+
"id": "11235980-87d7-4917-b0aa-74c01914c40e",
378+
"name": "Application Administrator"
379+
}
380+
],
381+
"iat": 1659474397,
382+
"id": "OidHvkPt-I-13IBSnd77UJ8cHgsrUpjs3W6_4t6ES7M",
383+
"idp": {
384+
"id": "b08e8c0c-a75d-4b3f-8e7b-cd427b7c7b47",
385+
"type": "azureAD"
386+
}
387+
}
388+
```
389+
</Details>
390+
391+

src/content/docs/cloudflare-one/applications/configure-apps/saas-apps/index.mdx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,6 @@ import { DirectoryListing } from "~/components"
1010

1111
Cloudflare Access allows you to add an additional authentication layer to your SaaS applications. When you integrate a SaaS application with Access, users log in to the application with Cloudflare as the Single Sign-On provider. The user is then redirected to the configured identity providers for that application and are only granted access if they pass your Access policies.
1212

13+
Cloudflare integrates with the majority of SaaS applications that support the SAML or OIDC authentication protocol. If you do not see your application listed below, refer to our [generic SAML](/cloudflare-one/applications/configure-apps/saas-apps/generic-saml-saas/) or [generic OIDC](/cloudflare-one/applications/configure-apps/saas-apps/generic-oidc-saas/) guide and consult your SaaS application's documentation.
14+
1315
<DirectoryListing />

0 commit comments

Comments
 (0)