SAML 2.0身份验证
了解如何为您选择的SAML 2.0兼容IDP设置和验证最终用户(而非AEM作者)。
SAML 2.0与AEM Publish(或Preview)集成,允许基于AEM的Web体验的最终用户向非Adobe IDP(身份提供程序)进行身份验证,并以已命名授权用户的身份访问AEM。
AEM Publish SAML集成的典型流程如下所示:
-
用户向AEM Publish发出请求,表示需要进行身份验证。
- 用户请求受CUG/ACL保护的资源。
- 用户请求受身份验证要求约束的资源。
- 用户跟随指向AEM登录终结点(即
/system/sling/login)的链接,该链接显式请求登录操作。
-
AEM会向IDP发出AuthnRequest,请求IDP启动身份验证流程。
-
用户向IDP进行身份验证。
- IDP会提示用户输入凭据。
- 用户已使用IDP进行身份验证,无需再提供凭据。
-
IDP会生成包含用户数据的SAML断言,并使用IDP的专用证书对其进行签名。
-
IDP通过HTTPPOST通过用户的Web浏览器(RESPECTIVE_PROTECTED_PATH/saml_login)将SAML断言发送至AEM Publish。
-
AEM Publish接收SAML断言,并使用IDP公共证书验证SAML断言的完整性和真实性。
-
AEM Publish根据SAML 2.0 OSGi配置和SAML断言的内容管理AEM用户记录。
- 创建用户
- 同步用户属性
- 更新AEM用户组成员资格
-
AEM Publish在HTTP响应上设置AEM
login-tokenCookie,该响应用于验证对AEM Publish的后续请求。 -
AEM Publish将用户重定向到
saml_request_pathCookie指定的AEM Publish上的URL。
配置演练
本视频将逐步介绍如何将SAML 2.0与AEM的集成设置为Cloud Service Publish服务,并使用Okta作为IDP。
先决条件
The following are required when setting up SAML 2.0 authentication:
- Deployment Manager access to Cloud Manager
- AEM Administrator access to AEM as a Cloud Service environment
- Administrator access to the IDP
- Optionally, access to a public/private keypair used to encryption SAML payloads
- AEM Sites页面(或页面树),已发布到AEM Publish,并受封闭用户组(CUG)保护
SAML 2.0 is only supported to authenticate uses to AEM Publish or Preview. To manage the authentication of AEM Author using and IDP, integrate the IDP with Adobe IMS.
AEM as a Cloud Service Preview service support
SAML 2.0 is supported on AEM as a Cloud Service, including AEM Preview. However, SAML configurations in AEM rely on OSGi configurations, and both AEM Preview and AEM Publish share the same OSGi runmode resolution (config.publish). As a result, you cannot create separate SAML configurations files for Preview and Publish.
而是应在OSGi配置中使用特定于环境的配置值,并为Preview和Publish环境设置相应的变量值。
在AEM上安装IDP公共证书
IDP的公共证书将添加到AEM的全球信任存储区,并用于验证IDP发送的SAML断言是否有效。
- 用户向IDP进行身份验证。
- IDP生成包含用户数据的SAML断言。
- IDP使用IDP的私有证书签署SAML声明。
- IDP向AEM发布的SAML端点(
.../saml_login)发起客户端HTTP POST,该端点包括已签名的SAML断言。 - AEM Publish接收包含已签名SAML声明的HTTP POST,可以使用IDP公共证书验证签名。
-
从IDP获取 公共证书 文件。 该证书允许AEM验证IDP提供给AEM的SAML断言。
证书采用PEM格式,应类似于:
code language-none -----BEGIN CERTIFICATE----- MIIC4jCBAcoCCQC33wnybT5QZDANBgkqhkiG9w0BAQsFADAyMQswCQYDVQQGEwJV ... m0eo2USlSRTVl7QHRTuiuSThHpLKQQ== -----END CERTIFICATE----- -
以AEM管理员身份登录AEM Author。
-
导航到工具>安全>信任存储区。
-
创建或打开全局信任存储区。 如果创建全局信任存储区,请将密码保存在安全的地方。
-
展开 从CER文件 添加证书。
-
选择选择证书文件,然后上传IDP提供的证书文件。
-
将 将证书映射到用户 保留为空。
-
选择提交。
-
新添加的证书显示在 从CRT文件 添加证书部分上方。
-
记下别名,因为该值在SAML 2.0身份验证处理程序OSGi配置中使用。
-
选择保存并关闭。
全局信任存储区在AEM Author上使用IDP的公共证书进行配置,但由于SAML仅在AEM Publish上使用,因此必须将全局信任存储区复制到AEM Publish,才能在其中访问IDP公共证书。
-
导航到工具>部署>包。
-
创建包
- 包名称:
Global Trust Store - 版本:
1.0.0 - 组:
com.your.company
- 包名称:
-
编辑新的 全局信任存储 包。
-
选择“筛选器”选项卡,然后为根路径
/etc/truststore添加筛选器。 -
选择完成,然后选择保存。
-
为 全局信任存储 包选择 构建 按钮。
-
生成后,选择更多 > 复制以将全局信任存储节点(
/etc/truststore)激活到AEM Publish。
创建身份验证服务密钥库 authentication-service-keystore
当SAML 2.0身份验证处理程序OSGi配置属性handleLogout设置为true或需要AuthnRequest签名/SAML断言加密时,需要为身份验证服务创建密钥库
-
以AEM管理员身份登录AEM Author以上传私钥。
-
导航到工具>安全性>用户,选择 身份验证服务 用户,然后从顶部操作栏中选择属性。
-
选择 密钥库 选项卡。
-
创建或打开密钥库。 如果创建密钥库,请确保密码安全。
- 仅当需要AuthnRequest签名/SAML断言加密时,公共/专用密钥库才会安装在此密钥库中。
- 如果此SAML集成支持注销,但不支持AuthnRequest签名/SAML断言,则空密钥库就足够了。
-
选择保存并关闭。
-
创建包含已更新的 authentication-service 用户的包。
使用包使用以下临时解决方法(U):
-
导航到工具>部署>包。
-
创建包
- 包名称:
Authentication Service - 版本:
1.0.0 - 组:
com.your.company
- 包名称:
-
编辑新的 身份验证服务密钥存储 包。
-
选择“筛选器”选项卡,然后为根路径
/home/users/system/cq:services/internal/security/<AUTHENTICATION SERVICE UUID>/keystore添加筛选器。- The
<AUTHENTICATION SERVICE UUID>can be found by navigating to Tools > Security > Users, and selecting authentication-service user. UUID是URL的最后一部分。
- The
-
Select Done and then Save.
-
Select the Build button for the Authentication Service Key Store package.
-
Once built, select More > Replicate to activate the Authentication Service key store to AEM Publish.
-
Install AEM public/private key pair install-aem-public-private-key-pair
可以选择是否安装AEM公钥/私钥对
AEM Publish可以配置为对AuthnRequests(到IDP)进行签名,并对SAML断言(到AEM)进行加密。 这是通过提供专用密钥到AEM Publish来实现的,并且可将公共密钥与IDP进行匹配。
AuthnRequest(从AEM Publish向IDP发出的启动登录过程的请求)可由AEM Publish签名。 为此,AEM Publish使用私钥对AuthnRequest签名,然后IDP使用公钥验证签名。 这向IDP保证AuthnRequest是由AEM Publish发起和请求的,而不是恶意的第三方。
- 用户向AEM Publish发出HTTP请求,从而向IDP发出SAML身份验证请求。
- AEM Publish会生成要发送到IDP的SAML请求。
- AEM Publish使用AEM的私钥对SAML请求进行签名。
- AEM Publish会启动AuthnRequest,这是一个HTTP客户端重定向,指向包含已签名SAML请求的IDP。
- IDP接收AuthnRequest,并使用AEM的公共密钥验证签名,从而确保AEM Publish启动了AuthnRequest。
- 然后,AEM Publish使用IDP公共证书验证解密的SAML断言的完整性和真实性。
IDP与AEM Publish之间的所有HTTP通信都应通过HTTPS,因此默认情况下都是安全的。 但是,根据需要,可以在需要在HTTPS提供的保密性之外额外保密的情况下对SAML断言进行加密。 为此,IDP使用私钥加密SAML断言数据,AEM Publish使用私钥解密SAML断言。
- 用户向IDP进行身份验证。
- IDP生成包含用户数据的SAML声明,并使用IDP的私有证书对其进行签名。
- 然后,IDP使用AEM的公共密钥加密SAML断言,该密钥需要AEM私钥进行解密。
- The encrypted SAML assertion is sent, by way of the user's web browser to AEM Publish.
- AEM Publish receives the SAML assertion, and decrypts it using AEM's private key.
- IDP prompts user to authenticate.
AuthnRequest签名和SAML断言加密都是可选的,但是它们都使用SAML 2.0身份验证处理程序OSGi配置属性useEncryption启用,这意味着两者都无法使用或都不使用。
-
获取用于签署AuthnRequest的公钥、私钥(DER格式中的PKCS#8)和证书链文件(这可能是公钥),并加密SAML断言。 这些密钥通常由IT组织的安全团队提供。
- 可使用 openssl 生成自签名密钥对:
code language-none $ openssl req -x509 -sha256 -days 365 -newkey rsa:4096 -keyout aem-private.key -out aem-public.crt # Provide a password (keep in safe place), and other requested certificate information # Convert the keys to AEM's required format $ openssl rsa -in aem-private.key -outform der -out aem-private.der $ openssl pkcs8 -topk8 -inform der -nocrypt -in aem-private.der -outform der -out aem-private-pkcs8.der -
将公钥上传到IDP。
- 使用上面的
openssl方法,公钥是aem-public.crt文件。
- 使用上面的
-
以AEM管理员身份登录AEM Author以上传私钥。
-
导航到工具>安全性>信任存储,选择 身份验证服务 用户,然后从顶部操作栏中选择属性。
-
导航到工具>安全性>用户,选择 身份验证服务 用户,然后从顶部操作栏中选择属性。
-
选择 密钥库 选项卡。
-
创建或打开密钥库。 如果创建密钥库,请确保密码安全。
-
选择从DER文件添加私钥,并将私钥和链文件添加到AEM:
- 别名:提供有意义的名称,通常是IDP的名称。
- 私钥文件:上载私钥文件(DER格式的PKCS#8)。
- 使用上面的
openssl方法,这是aem-private-pkcs8.der文件
- 使用上面的
- 选择证书链文件:上载随附的链文件(这可能是公钥)。
- 使用上述
openssl方法,这是aem-public.crt文件
- 使用上述
- 选择提交
-
新添加的证书显示在 从CRT文件 添加证书部分上方。
- 记下别名,因为该别名在SAML 2.0身份验证处理程序OSGi配置中使用
-
选择保存并关闭。
-
创建包含已更新的 authentication-service 用户的包。
使用包使用以下临时解决方法(U):
-
导航到工具>部署>包。
-
创建包
- 包名称:
Authentication Service - 版本:
1.0.0 - 组:
com.your.company
- 包名称:
-
编辑新的 身份验证服务密钥存储 包。
-
选择“筛选器”选项卡,然后为根路径
/home/users/system/cq:services/internal/security/<AUTHENTICATION SERVICE UUID>/keystore添加筛选器。- 通过导航到
<AUTHENTICATION SERVICE UUID>工具>安全性>用户 ,然后选择 身份验证服务用户,可找到。 UUID是URL的最后一部分。
- 通过导航到
-
Select Done and then Save.
-
Select the Build button for the Authentication Service Key Store package.
-
Once built, select More > Replicate to activate the Authentication Service key store to AEM Publish.
-
Configure SAML 2.0 authentication handler configure-saml-2-0-authentication-handler
AEM's SAML configuration is performed via the Adobe Granite SAML 2.0 Authentication Handler OSGi configuration.
该配置是OSGi工厂配置,这意味着单个AEM as a Cloud Service Publish服务可能有多个SAML配置,其涵盖存储库的离散资源树;这对于多站点AEM部署很有用。
Adobe Granite SAML 2.0身份验证处理程序OSGi配置 configure-saml-2-0-authentication-handler-osgi-configuration
| table 0-row-6 1-row-6 2-row-6 3-row-6 4-row-6 5-row-6 6-row-6 7-row-6 8-row-6 9-row-6 10-row-6 11-row-6 12-row-6 13-row-6 14-row-6 15-row-6 16-row-6 17-row-6 18-row-6 19-row-6 20-row-6 21-row-6 22-row-6 23-row-6 24-row-6 25-row-6 26-row-6 27-row-6 3-align-center 4-align-center 10-align-center 11-align-center 17-align-center 18-align-center 24-align-center 25-align-center 31-align-center 32-align-center 38-align-center 39-align-center 45-align-center 46-align-center 52-align-center 53-align-center 59-align-center 60-align-center 66-align-center 67-align-center 73-align-center 74-align-center 80-align-center 81-align-center 87-align-center 88-align-center 94-align-center 95-align-center 101-align-center 102-align-center 108-align-center 109-align-center 115-align-center 116-align-center 122-align-center 123-align-center 129-align-center 130-align-center 136-align-center 137-align-center 143-align-center 144-align-center 150-align-center 151-align-center 157-align-center 158-align-center 164-align-center 165-align-center 171-align-center 172-align-center 178-align-center 179-align-center 185-align-center 186-align-center 192-align-center 193-align-center | |||||
|---|---|---|---|---|---|
| OSGi属性 | 必需 | 值格式 | 默认值 | 描述 | |
| 路径 | path |
✔ | 字符串数组 | / |
此身份验证处理程序用于的AEM路径。 |
| IDP URL | idpUrl |
✔ | 字符串 | 发送SAML身份验证请求的IDP URL。 | |
| IDP证书别名 | idpCertAlias |
✔ | 字符串 | 在AEM全局信任存储区中找到的IDP证书的别名 | |
| IDP HTTP重定向 | idpHttpRedirect |
✘ | 布尔值 | false |
指示是否向IDP URL进行HTTP重定向而不是发送AuthnRequest。 对于IDP启动的身份验证,设置为true。 |
| IDP identifier | idpIdentifier |
✘ | 字符串 | Unique IDP Id to ensure AEM user and group uniqueness. 如果为空,则改用serviceProviderEntityId。 |
|
| 断言使用者服务URL | assertionConsumerServiceURL |
✘ | 字符串 | AuthnRequest中的AssertionConsumerServiceURL URL属性,用于指定必须将<Response>消息发送到AEM的位置。 |
|
| SP实体ID | serviceProviderEntityId |
✔ | 字符串 | 向IDP唯一标识AEM;通常是AEM主机名。 | |
| SP加密 | useEncryption |
✘ | 布尔值 | true |
指示IDP是否加密SAML断言。 需要设置spPrivateKeyAlias和keyStorePassword。 |
| SP私钥别名 | spPrivateKeyAlias |
✘ | 字符串 | authentication-service用户密钥存储中私钥的别名。 如果useEncryption设置为true,则需要。 |
|
| SP密钥存储密码 | keyStorePassword |
✘ | 字符串 | “authentication-service”用户的密钥存储的密码。 如果useEncryption设置为true,则需要。 |
|
| 默认重定向 | defaultRedirectUrl |
✘ | 字符串 | / |
成功身份验证后的默认重定向URL。 可以相对于AEM主机(例如,/content/wknd/us/en/html)。 |
| 用户ID属性 | userIDAttribute |
✘ | 字符串 | uid |
包含AEM用户的用户ID的SAML断言属性的名称。 留空以使用Subject:NameId。 |
| 自动创建AEM用户 | createUser |
✘ | 布尔值 | true |
指示是否创建AEM用户时身份验证成功。 |
| AEM用户中间路径 | userIntermediatePath |
✘ | 字符串 | 创建AEM用户时,此值用作中间路径(例如,/home/users/<userIntermediatePath>/jane@wknd.com)。 需要将createUser设置为true。 |
|
| AEM用户属性 | synchronizeAttributes |
✘ | 字符串数组 | List of SAML attribute mappings to store on the AEM user, in the format [ "saml-attribute-name=path/relative/to/user/node" ] (for example, [ "firstName=profile/givenName" ]). 查看本机AEM属性的完整列表。 |
|
| Add user to AEM groups | addGroupMemberships |
✘ | 布尔值 | true |
Indicates if an AEM user is automatically added to AEM user groups after successful authentication. |
| AEM组成员资格属性 | groupMembershipAttribute |
✘ | 字符串 | groupMembership |
SAML断言属性的名称,该属性包含应将该用户添加到的AEM用户组的列表。 需要将addGroupMemberships设置为true。 |
| 默认AEM组 | defaultGroups |
✘ | 字符串数组 | 已验证身份的用户的AEM用户组列表始终添加到(例如,[ "wknd-user" ])。 需要将addGroupMemberships设置为true。 |
|
| NameIDPolicy格式 | nameIdFormat |
✘ | 字符串 | urn:oasis:names:tc:SAML:2.0:nameid-format:transient |
在AuthnRequest消息中发送的NameIDPolicy格式参数的值。 |
| 存储SAML响应 | storeSAMLResponse |
✘ | 布尔值 | false |
指示samlResponse值是否存储在AEM cq:User节点上。 |
| 句柄注销 | handleLogout |
✘ | 布尔值 | false |
指示此SAML身份验证处理程序是否处理注销请求。 需要设置logoutUrl。 |
| 注销URL | logoutUrl |
✘ | 字符串 | 发送SAML注销请求的IDP URL。 如果handleLogout设置为true,则此为必填字段。 |
|
| 时钟容差 | clockTolerance |
✘ | 整数 | 60 |
验证SAML断言时,IDP和AEM (SP)时钟偏差容错。 |
| 摘要方法 | digestMethod |
✘ | 字符串 | http://www.w3.org/2001/04/xmlenc#sha256 |
IDP在签名SAML消息时使用的摘要算法。 |
| 签名方法 | signatureMethod |
✘ | 字符串 | http://www.w3.org/2001/04/xmldsig-more#rsa-sha256 |
IDP在签名SAML消息时使用的签名算法。 |
| 身份同步类型 | identitySyncType |
✘ | default 或 idp |
default |
请勿更改AEM as a Cloud Service的from默认值。 |
| 服务排名 | service.ranking |
✘ | 整数 | 5002 |
同一path首选排名较高的配置。 |
AEM用户属性 aem-user-attributes
AEM使用以下用户属性,这些属性可以通过AdobeGranite SAML 2.0身份验证处理程序OSGi配置中的synchronizeAttributes属性进行填充。 任何IDP属性都可以同步到任何AEM用户属性,但是,映射到AEM使用属性属性(如下所列)允许AEM自然使用这些属性。
| table 0-row-2 1-row-2 2-row-2 3-row-2 4-row-2 5-row-2 6-row-2 7-row-2 8-row-2 9-row-2 10-row-2 11-row-2 | |
|---|---|
| 用户属性 | rep:User节点的相对属性路径 |
标题(例如,Mrs) |
profile/title |
| 名字(即名字) | profile/givenName |
| 姓氏(即姓氏) | profile/familyName |
| 职务 | profile/jobTitle |
| 电子邮件地址 | profile/email |
| 街道地址 | profile/street |
| 城市 | profile/city |
| 邮政编码 | profile/postalCode |
| 国家/地区 | profile/country |
| 电话号码 | profile/phoneNumber |
| 自我介绍 | profile/aboutMe |
-
在
/ui.config/src/main/content/jcr_root/wknd-examples/osgiconfig/config.publish/com.adobe.granite.auth.saml.SamlAuthenticationHandler~saml.cfg.json的项目中创建OSGi配置文件,然后在IDE中打开。- 将
/wknd-examples/更改为您的/<project name>/ - 文件名中
~之后的标识符应唯一标识此配置,因此它可能是IDP的名称,如...~okta.cfg.json。 该值应为带连字符的字母数字。
- 将
-
将以下JSON粘贴到
com.adobe.granite.auth.saml.SamlAuthenticationHandler~...cfg.json文件中,并根据需要更新wknd引用。code language-json { "path": [ "/content/wknd", "/content/dam/wknd" ], "idpCertAlias": "$[env:SAML_IDP_CERT_ALIAS;default=certalias___1652125559800]", "idpIdentifier": "$[env:SAML_IDP_ID;default=http://www.okta.com/exk4z55r44Jz9C6am5d7]", "idpUrl": "$[env:SAML_IDP_URL;default=https://dev-5511372.okta.com/app/dev-5511372_aemasacloudservice_1/exk4z55r44Jz9C6am5d7/sso/saml]", "serviceProviderEntityId": "$[env:SAML_AEM_ID;default=https://publish-p123-e456.adobeaemcloud.com]", "useEncryption": false, "createUser": true, "userIntermediatePath": "wknd/idp", "synchronizeAttributes":[ "firstName=profile/givenName" ], "addGroupMemberships": true, "defaultGroups": [ "wknd-users" ] } -
根据项目需要更新值。 有关配置属性说明,请参阅上面的SAML 2.0身份验证处理程序OSGi配置词汇表。 The
pathshould contain the content trees that are protected by Closed User Groups (CUGs) and require authentication and this authentication handler should be responsible for protecting. -
It is recommended, but not required, to use OSGi environment variables and secrets, when values may change out of sync with the release cycle, or when the values different between similar environment types/service tiers. Default values can be set using the
$[env:..;default=the-default-value]"syntax as shown above.
OSGi configurations per environment (config.publish.dev, config.publish.stage, and config.publish.prod) can be defined with specific attributes if the SAML configuration varies between environments.
Use encryption
在加密AuthnRequest和SAML断言时,需要以下属性: useEncryption、spPrivateKeyAlias和keyStorePassword。 The keyStorePassword contains a password therefore the value must not be stored in the OSGi configuration file, but rather injected using secret configuration values
-
在IDE中打开
/ui.config/src/main/content/jcr_root/wknd-examples/osgiconfig/config.publish/com.adobe.granite.auth.saml.SamlAuthenticationHandler~saml.cfg.json。 -
添加三个属性
useEncryption、spPrivateKeyAlias和keyStorePassword,如下所示。code language-json { "path": [ "/content/wknd", "/content/dam/wknd" ], "idpCertAlias": "$[env:SAML_IDP_CERT_ALIAS;default=certalias___1234567890]", "idpIdentifier": "$[env:SAML_IDP_ID;default=http://www.okta.com/abcdef1235678]", "idpUrl": "$[env:SAML_IDP_URL;default=https://dev-5511372.okta.com/app/dev-123567890_aemasacloudservice_1/abcdef1235678/sso/saml]", "serviceProviderEntityId": "$[env:SAML_AEM_ID;default=https://publish-p123-e456.adobeaemcloud.com]", "useEncryption": true, "spPrivateKeyAlias": "$[env:SAML_AEM_KEYSTORE_ALIAS;default=aem-saml-encryption]", "keyStorePassword": "$[secret:SAML_AEM_KEYSTORE_PASSWORD]", "createUser": true, "userIntermediatePath": "wknd/idp" "synchronizeAttributes":[ "firstName=profile/givenName" ], "addGroupMemberships": true, "defaultGroups": [ "wknd-users" ] } -
加密所需的三个OSGi配置属性包括:
useEncryption设置为truespPrivateKeyAlias包含SAML集成使用的私钥的密钥库条目别名。keyStorePassword包含包含用户密钥库密码的OSGi密钥配置变量authentication-service。
配置反向链接过滤器
在SAML身份验证过程中,IDP启动一个客户端的HTTP POST到AEM Publish的.../saml_login端点。 如果IDP和AEM Publish存在于不同的源中,则会通过OSGi配置将AEM Publish的 反向链接过滤器 配置为允许来自IDP源的HTTP POST。
-
在
/ui.config/src/main/content/jcr_root/wknd-examples/osgiconfig/config.publish/org.apache.sling.security.impl.ReferrerFilter.cfg.json的项目中创建(或编辑)OSGi配置文件。- 将
/wknd-examples/更改为您的/<project name>/
- 将
-
请确保
allow.empty值设置为true,allow.hosts(或者如果您愿意,allow.hosts.regexp)包含IDP的源,并且filter.methods包含POST。 OSGi配置应类似于:code language-json { "allow.empty": true, "allow.hosts.regexp": [ ], "allow.hosts": [ "$[env:SAML_IDP_REFERRER;default=dev-123567890.okta.com]" ], "filter.methods": [ "POST", ], "exclude.agents.regexp": [ ] }
AEM Publish支持单个反向链接过滤器配置,因此请将SAML配置要求与任何现有配置合并。
如果config.publish.dev (或config.publish.stage)在不同环境之间不同,则可以使用特定属性定义每个环境(config.publish.prod、allow.hosts和allow.hosts.regex)的OSGi配置。
配置跨源资源共享(CORS)
在SAML身份验证过程中,IDP向AEM Publish的.../saml_login端点发起客户端HTTP POST。 如果IDP和AEM Publish存在于不同的主机/域中,则必须将AEM Publish的 CRoss源资源共享(CORS) 配置为允许来自IDP主机/域的HTTP POST。
此HTTP POST请求的Origin标头的值通常与AEM Publish主机的值不同,因此需要CORS配置。
在本地AEM SDK (localhost:4503)上测试SAML身份验证时,IDP可能会将Origin标头设置为null。 如果是,请将"null"添加到alloworigin列表。
-
在
/ui.config/src/main/content/jcr_root/wknd-examples/osgiconfig/config.publish/com.adobe.granite.cors.impl.CORSPolicyImpl~saml.cfg.json处的项目中创建一个OSGi配置文件- 将
/wknd-examples/更改为您的项目名称 - 文件名中
~之后的标识符应唯一标识此配置,因此它可能是IDP的名称,如...CORSPolicyImpl~okta.cfg.json。 该值应为带连字符的字母数字。
- 将
-
将以下JSON粘贴到
com.adobe.granite.cors.impl.CORSPolicyImpl~...cfg.json文件中。
{
"alloworigin": [
"$[env:SAML_IDP_ORIGIN;default=https://dev-1234567890.okta.com]",
"null"
],
"allowedpaths": [
".*/saml_login"
],
"supportedmethods": [
"POST"
]
}
如果config.publish.dev和config.publish.stage在不同环境之间不同,则可以使用特定属性定义每个环境(config.publish.prod、alloworigin和allowedpaths)的OSGi配置。
配置AEM Dispatcher以允许SAML HTTP POST
成功对IDP进行身份验证后,IDP将编排HTTP POST以返回到AEM注册的/saml_login端点(在IDP中配置)。 默认情况下,Dispatcher阻止了对/saml_login的此HTTP POST,因此必须使用以下Dispatcher规则明确允许它:
- 在IDE中打开
dispatcher/src/conf.dispatcher.d/filters/filters.any。 - 在文件底部添加一个允许规则,用于向以
/saml_login结尾的URL发送HTTP POST。
...
# Allow SAML HTTP POST to ../saml_login end points
/0190 { /type "allow" /method "POST" /url "*/saml_login" }
如果已配置Apache Webserver上的URL重写(dispatcher/src/conf.d/rewrites/rewrite.rules),请确保不会意外损坏对.../saml_login端点的请求。
动态组成员资格
动态组成员资格是Apache Jackrabbit Oak中的一项功能,可提升组评估和设置的性能。 本节介绍启用此功能时如何存储用户和组,以及如何修改SAML身份验证处理程序的配置,以便为新环境或现有环境启用它。
如何为新环境中的SAML用户启用动态组成员资格
为了显着增强新AEM即云服务环境中的组评估性能,建议在新环境中激活动态组成员资格功能。
这也是激活数据同步时必需执行的步骤。 更多详细信息此处 。
为此,请将以下属性添加到OSGI配置文件中:
/apps/example/osgiconfig/config.publish/com.adobe.granite.auth.saml.SamlAuthenticationHandler~example.cfg.json
使用此配置,用户和组将创建为Oak外部用户。 在AEM中,外部用户和组具有由rep:principalName或[user name];[idp]组成的默认[group name];[idp]。
请注意,访问控制列表(ACL)与用户或组的PrincipalName相关联。
在现有部署中部署此配置时,如果先前的identitySyncType未指定或设置为default,则将创建新用户和组,并且必须将ACL应用于这些新用户和组。 请注意,外部组不能包含本地用户。 Repoinit可用于为SAML外部组创建ACL,即使仅在用户执行登录时创建它们。
为避免对ACL进行此重构,已实施标准迁移功能。
成员资格如何存储在具有动态组成员资格的本地和外部组中
在本地组中,组成员存储在oak属性中: rep:members。 该属性包含组中每个成员的uid列表。 可在此处找到其他详细信息。
示例:
{
"jcr:primaryType": "rep:Group",
"rep:principalName": "operators",
"rep:managedByIdp": "SAML",
"rep:members": [
"635afa1c-beeb-3262-83c4-38ea31e5549e",
"5e496093-feb6-37e9-a2a1-7c87b1cec4b0",
...
],
...
}
具有动态组成员资格的外部组不存储组条目中的任何成员。
组成员资格将存储在用户条目中。 可在此处找到其他文档。 例如,这是组的OAK节点:
{
"jcr:primaryType": "rep:Group",
"jcr:mixinTypes": [
"rep:AccessControllable"
],
"jcr:createdBy": "",
"jcr:created": "Tue Jul 16 2024 08:58:47 GMT+0000",
"rep:principalName": "GROUP_1;aem-saml-idp-1",
"rep:lastSynced": "Tue Jul 16 2024 08:58:47 GMT+0000",
"jcr:uuid": "d9c6af8a-35c0-3064-899a-59af55455cd0",
"rep:externalId": "GROUP_1;aem-saml-idp-1",
"rep:authorizableId": "GROUP_1;aem-saml-idp-1"
}
这是该组的用户成员的节点:
{
"jcr:primaryType": "rep:User",
"jcr:mixinTypes": [
"rep:AccessControllable"
],
"surname": "Test",
"rep:principalName": "testUser",
"rep:externalId": "test;aem-saml-idp-1",
"rep:authorizableId": "test",
"rep:externalPrincipalNames": [
"projects-users;aem-saml-idp-1",
"GROUP_2;aem-saml-idp-1",
"GROUP_1;aem-saml-idp-1",
"operators;aem-saml-idp-1"
],
...
}
如何在现有环境中为SAML用户启用动态组成员资格
如上一节所述,外部用户和组的格式与用于本地用户和组的格式略有不同。 您可以为外部组定义新的ACL并配置新的外部用户,也可以使用如下所述的迁移工具。
为具有外部用户的现有环境启用动态组成员资格
SAML身份验证处理程序在指定以下属性时创建外部用户: "identitySyncType": "idp"。 在这种情况下,可以启用动态组成员资格,以便将此属性修改为: "identitySyncType": "idp_dynamic"。 无需迁移。
自动迁移到具有本地用户的现有环境的动态组成员资格
SAML身份验证处理程序在指定以下属性时创建本地用户: "identitySyncType": "default"。 如果未指定属性,这也是默认值。 在此部分中,我们将介绍自动迁移过程执行的步骤。
启用此迁移后,将在用户身份验证期间执行,包括以下步骤:
- 本地用户将迁移到外部用户,同时保留原始用户名。 这意味着已迁移的本地用户(现在充当外部用户)将保留其原始用户名,而不是遵循上一节中提到的命名语法。 将添加一个名为的附加属性:
rep:externalId,其值为[user name];[idp]。 未修改用户PrincipalName。 - 对于在SAML断言中收到的每个外部组,将创建一个外部组。 如果存在相应的本地组,则外部组将作为成员添加到本地组。
- 用户将作为外部组成员添加。
- 然后,该本地用户将从他所属的所有Saml本地组中删除。 Saml本地组由OAK属性标识:
rep:managedByIdp。 当未指定属性syncType或将其设置为default时,此属性由Saml身份验证处理程序设置。
例如,如果在迁移user1之前是本地用户并且是本地组group1的成员,则在迁移之后会发生以下更改:user1将成为外部用户。 属性rep:externalId已添加到其配置文件中。user1成为外部组的成员: group1;idpuser1不再是本地组group1的直接成员group1;idp是本地组group1的成员。user1是本地组的成员: group1(通过继承)
外部组的组成员资格存储在属性rep:externalPrincipalNames的用户配置文件中
如何配置自动迁移到动态组成员资格
- 启用SAML OSGi配置文件中的属性
"identitySyncType": "idp_dynamic_simplified_id":com.adobe.granite.auth.saml.SamlAuthenticationHandler~...cfg.json - 使用工厂PID配置新的OSGi服务,开始于:
com.adobe.granite.auth.saml.migration.SamlDynamicGroupMembershipMigration~。 例如,PID可以是:com.adobe.granite.auth.saml.migration.SamlDynamicGroupMembershipMigration~myIdP。 设置以下属性:
{
"idpIdentifier": "<value of IDP Identifier (idpIdentifier)" property from the "com.adobe.granite.auth.saml.SamlAuthenticationHandler" configuration to be migrated>"
}
要迁移多个SAML配置,必须为com.adobe.granite.auth.saml.migration.SamlDynamicGroupMembershipMigration创建多个OSGi工厂配置,每个工厂配置指定要迁移的idpIdentifier。
自定义SAML登录挂接
对于高级用例,AEM支持开发自定义SAML登录挂接,这些挂接是实施com.adobe.granite.auth.saml.SamlLoginHook界面的OSGi服务。 这些挂接在SAML身份验证过程中执行,可用于实施自定义逻辑,如其他用户配置或自定义日志记录。
有关如何开发和注册自定义SAML登录挂接的更多信息,请参阅自定义SAML登录挂接文档。
部署SAML配置
OSGi配置必须提交到Git并使用Cloud Manager部署到AEM as a Cloud Service。
$ git remote -v
adobe https://git.cloudmanager.adobe.com/myOrg/myCloudManagerGit/ (fetch)
adobe https://git.cloudmanager.adobe.com/myOrg/myCloudManagerGit/ (push)
$ git add .
$ git commit -m "SAML 2.0 configurations"
$ git push adobe saml-auth:develop
使用全栈部署管道部署目标Cloud Manager Git分支(在此示例中为develop)。
调用SAML身份验证
可以通过创建巧尽心思构建的链接或按钮,从AEM Site网页调用SAML身份验证流程。 下面描述的参数可以根据需要进行编程设置,因此,例如,登录按钮可以根据按钮的上下文将saml_request_path(成功SAML身份验证后用户在该处进行身份验证)设置到不同的AEM页面。
使用SAML时的安全缓存
在AEM发布实例上,通常都会缓存大多数页面。 但是,对于受SAML保护的路径,应使用auth_checker配置禁用缓存或启用安全缓存。 有关详细信息,请参阅此处提供的详细信息
请注意,如果您在缓存受保护的路径时没有启用auth_checker,则可能会遇到无法预测的行为。
GET请求
可以通过创建HTTP GET请求来调用SAML身份验证,格式为:
HTTP GET /system/sling/login
并提供查询参数:
resourcepath属性中所定义。saml_request_path例如,此HTML链接将触发SAML登录流程,成功后将用户转到/content/wknd/us/en/protected/page.html。 可以根据需要以编程方式设置这些查询参数。
<a href="/system/sling/login?resource=/content/wknd&saml_request_path=/content/wknd/us/en/protected/page.html">
Log in using SAML
</a>
POST请求
可通过以下格式创建HTTPPOST请求来调用SAML身份验证:
HTTP POST /system/sling/login
并提供表单数据:
resourcepath属性中所定义。saml_request_path例如,此HTML按钮将使用HTTP POST触发SAML登录流程,成功后,将用户带到/content/wknd/us/en/protected/page.html。 可以根据需要以编程方式设置这些表单数据参数。
<form action="/system/sling/login" method="POST">
<input type="hidden" name="resource" value="/content/wknd">
<input type="hidden" name="saml_request_path" value="/content/wknd/us/en/protected/page.html">
<input type="submit" value="Log in using SAML">
</form>
Dispatcher 配置
HTTP GET和POST方法都需要客户端访问AEM的/system/sling/login端点,因此必须允许通过AEM Dispatcher访问它们。
根据是否使用了GET或POST,允许使用必要的URL模式
# Allow GET-based SAML authentication invocation
/0191 { /type "allow" /method "GET" /url "/system/sling/login" /query "*" }
# Allow POST-based SAML authentication invocation
/0192 { /type "allow" /method "POST" /url "/system/sling/login" }