【问题标题】:AEM 6.4.x + SAML authenticantion (Okta): How do I read (via Java) the SAML response from my SSO provider?AEM 6.4.x + SAML 身份验证 (Okta):如何读取(通过 Java)来自 SSO 提供商的 SAML 响应?
【发布时间】:2019-10-21 07:22:40
【问题描述】:

TLDR:使用 Java(或其他 AEM 相关技术),我如何检索用于登录并随后查看受保护页面的用户名?


我们已经通过使用我们的 SSO 提供商 (Oka) 的登录保护了一些页面。我想阅读 SAML 响应(或至少检索用于登录的用户名)。

我们想要自定义受保护页面上显示的一些内容。

示例:检索并显示存储在人力资源数据库中的登录用户的名字、姓氏、部门和其他信息

如何做到这一点?

我查看了 cookie(以及一般 Firefox 中的存储选项卡),但在那里找不到任何东西。唯一能看到 SAML 响应的地方是在使用浏览器工具时(例如:SAML-tracer)。

我在网上搜索过,我发现的结果只是关于设置 AEM 以连接到 SSO 提供程序这部分已经配置并且已经工作了)。

谢谢

【问题讨论】:

    标签: single-sign-on aem okta aem-6


    【解决方案1】:

    您不应该从 SAML 响应中读取此内容。这应该从用户配置文件中读取。 SAML 身份验证处理程序允许您将 SAML 响应中提供的属性保存到 AEM 用户。

    当 SAML Auth 处理程序将用户登录到 AEM 时,只要用户保持登录状态,用户主体就会与所有后续请求相关联。您可以根据请求中的主体/可授权获取用户信息

    UserPropertiesManager upm = resourceResolver.adaptTo(UserPropertiesManager.class);
    Authorizable authorizable = resourceResolver.adaptTo(Authorizable.class);
    UserProperties userProperties = upm.getUserProperties(authorizable, "profile");
    

    https://helpx.adobe.com/experience-manager/6-3/sites/developing/using/reference-materials/javadoc/com/adobe/granite/security/user/UserProperties.html

    虽然 SAML 身份验证处理程序可以将 SAML 响应中的属性保存到 AEM 用户;要使其在生产中按预期工作,它可能取决于许多因素,例如发布者的数量 [以保持数据同步]、用户量、会话亲和性等。

    根据我的经验,尽管该框架具有社区用户同步形式的解决方案、用于处理会话亲和性的封装令牌支持等。它无法像宣传的那样工作,您可能需要重新考虑在发布者并介绍一种从真实来源读取此信息的方法,只需将基本配置文件拉入 AEM。如果这只是用于创作环境,它应该仍然可以工作

    【讨论】:

    • 我想获取使用的用户名,然后我可以用它来查询 HR 系统数据库。让我试试你的。感谢您的建议。
    • 要获取用户 ID,请使用 ResourceResolver#getUserID。用户 ID 值将取决于 SAML 身份验证处理程序的配置,因为其中一个属性可以映射为 AEM 用户名
    • 这是在 6.x 版本的 AEM 中执行此操作的正确方法。在 AEM 中配置 SAML 并告诉它 SAML 断言映射中的哪些属性对应于 AEM 用户配置文件属性,然后通过内置 API 访问它们。每次用户登录时,映射的属性都会重新同步。您可能还需要在 IdP(例如 Okta)端进行一些配置,以确保它将所有相关属性传递给 AEM(SAML 中的服务提供者-说话)。
    【解决方案2】:

    免责声明:这并不容易,我还没有测试过。我刚刚反编译了 SAML 身份验证处理程序并检查了那里发生了什么。

    您应该知道自己在做什么,并且应该尽量让它坚如磐石。一般来说,在 AEM 中使用围绕身份验证的 API 非常麻烦。


    我认为您无法从“标准”SAML 令牌中获取部门等信息。但让我们假设这是令牌有效负载的一部分。

    您必须将这些信息存储在某个地方。可能是用户个人资料(例如/home/users/a/<userid>/profile)。

    我认为org.apache.sling.auth.core.spi.AuthenticationFeedbackHandler 可以做到这一点。该处理程序将有权访问用户的请求、响应和身份验证信息。所以你必须实现这样一个处理程序,然后在用户认证后调用。

    身份验证信息基本上只是一个包含具有相关信息的密钥的映射。一个这样的密钥应该是user.jcr.credentials。对于 SAML,这应该是 com.adobe.granite.auth.saml.extidp.SamlCredentials 的一个实例。

    这些凭据包含您可以通过getAttribute() 阅读的“属性”。包含“原始 SAML 响应”的属性称为 samlResponse。所以这应该给你你正在寻找的东西:

    private String getSamlResponse(final AuthenticationInfo authenticationInfo) {
        if (authenticationInfo == null) {
            return "";
        }
    
        Object credentialsObject = authenticationInfo.get("user.jcr.credentials");
        if (credentialsObject == null) {
            return "";
        }
    
        try {
            SamlCredentials credentials = (SamlCredentials) credentialsObject;
            String encryptedSamlResponse = credentials.getAttribute("samlResponse");
            if (encryptedSamlResponse == null || encryptedSamlResponse.trim().length() == 0) {
                return "";
            }
    
            return decryptSamlResponse(encryptedSamlResponse);
        } catch (ClassCastException e) {
            // Unable to cast "credentialsObject" to "SamlCredentials"
            return "";
        }
    }
    

    注意:

    1. 以上代码使用SamlCredentialscom.adobe.granite.auth.saml 捆绑包不会公开导出此类。您必须反编译该包并将该类复制并粘贴到您自己的包中。
    2. 您必须使用CryptoSupport 实现decryptSamlResponse 方法。

    如果 SAML 令牌不包含您要查找的信息,您可以尝试使用用户的电子邮件地址来查询某种包含该信息的外部数据库,然后将其存储在用户配置文件中。

    无论您做什么,如果您在一个发布者上执行此操作并且您有多个发布者(您通常应该有),那么您还必须考虑在这些发布者之间同步用户配置文件或使用粘性连接。据我所知,同步有点问题,并且有一些问题,您可能会遇到以下情况:第一个请求发送给发布者 1,下一个请求(不久之后)发送给尚未同步配置文件的发布者 2 .使用粘性连接可能会更好。

    【讨论】:

      猜你喜欢
      • 2017-08-21
      • 2020-05-12
      • 1970-01-01
      • 2013-05-12
      • 2018-12-17
      • 2017-05-04
      • 2018-08-31
      • 1970-01-01
      • 2020-04-25
      相关资源
      最近更新 更多