使用 ADFS 实施 ACS 作为 STS

发布于 2024-12-11 01:23:41 字数 3754 浏览 0 评论 0原文

我们正在尝试使用 ACS 示例 4(来自 http://claimsid.codeplex.com/)作为模板对于我们的 ADFS 项目。 我们对 ADFS 身份验证服务的被动请求没有任何问题。在示例中,联合提供程序是自定义 STS,并且该示例工作正常。

现在我们希望用我们自己的 ADFS 替换自定义联合提供程序(示例中的 Adatum FP)。

我们现在的设置如下(隐藏命名空间)

  • ServiceClient:控制台应用程序,调用服务
  • 服务:WCF Web服务,返回字符串的单个方法。这是默认的 [示例中的 Ordertracking.Services]
  • Services.Authentication:我们的自定义身份提供商。这是默认的 [示例中的 Litware.SimulatedIssuer]
  • ADFS:我们的联合提供程序 [FederationProvider.Adatum 中 例如]

ServiceClient 想要调用 Services,并且从配置中它知道它必须从 IP 获取令牌(Services.Authentication)。然后将令牌传递给 ADFS,由 ADFS 验证令牌 并将新令牌发送回 ServiceClient。客户端将 FP 令牌传递给服务,服务(作为 ADFS 的依赖方)根据 ADFS 验证令牌,并执行服务方法。

问题:

用 ADFS 替换示例中的 STS 似乎会破坏集成。我们似乎正确地从 IP 获取了令牌,但在将 IP 令牌传递到 ADFS 时遇到了问题。 我们的 Audience Uri 似乎有问题,但我们已经添加了

https://'adfs fqdn'/adfs/services/Trust/13/IssuedTokenMixedSymmetricBasic256

客户端异常 我们在客户端中收到带有此 InnerException 的 MessageSecurityException 内部异常 {“ID3242:无法验证或授权安全令牌。”}

[System.ServiceModel.FaultException]: {"ID3242: The security token could not be authenticated or authorized."}
Data: {System.Collections.ListDictionaryInternal}
HelpLink: null
InnerException: null
Message: "ID3242: The security token could not be authenticated or authorized."
Source: null
StackTrace: null
TargetSite: null

ADFS 调试日志

<TraceRecord xmlns="http://schemas.microsoft.com/2009/10/IdentityModel/TraceRecord" Severity="Error">
    <Description>Handled exception.</Description>
    <AppDomain>Microsoft.IdentityServer.ServiceHost.exe</AppDomain>
    <Exception>
        <ExceptionType>Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35</ExceptionType>
        <Message>ID1038: The AudienceRestrictionCondition was not valid because the specified Audience is not present in AudienceUris. Audience: 'https://<adfs fqdn>/adfs/services/Trust/13/IssuedTokenMixedSymmetricBasic256'</Message>
        <StackTrace>
  at Microsoft.IdentityModel.Tokens.SamlSecurityTokenRequirement.ValidateAudienceRestriction(IList`1 allowedAudienceUris, IList`1 tokenAudiences) at Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.ValidateConditions(Saml2Conditions conditions, Boolean enforceAudienceRestriction) at Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.ValidateToken(SecurityToken token) at Microsoft.IdentityServer.Service.Tokens.MSISSaml2TokenHandler.ValidateToken(SecurityToken token) at Microsoft.IdentityModel.Tokens.WrappedSaml2SecurityTokenAuthenticator.ValidateTokenCore(SecurityToken token) at System.IdentityModel.Selectors.SecurityTokenAuthenticator.ValidateToken(SecurityToken token) at Microsoft.IdentityModel.Tokens.WrappedSamlSecurityTokenAuthenticator.ValidateTokenCore(SecurityToken token) at System.IdentityModel.Selectors.SecurityTokenAuthenticator.ValidateToken(SecurityToken token) at System.ServiceModel.Security.ReceiveSecurityHeader.ReadToken(XmlReader reader, SecurityTokenResolver tokenResolver, IList`1 allowedTokenAuthenticators, SecurityTokenAuthenticator&amp;amp; usedTokenAuthenticator) at
  ....
        </StackTrace>
    </Exception>
</TraceRecord>

我们已将受众 uri 添加到我们的 IP Web.config:

<audienceUris mode="Always">
    <add value="https://<adfs fqdn>/adfs/services/Trust/13/IssuedTokenMixedSymmetricBasic256" />
</audienceUris>

如有必要,我们可以发布其他配置文件和屏幕截图ADFS 配置。

We are attempting to use the ACS sample 4 (from http://claimsid.codeplex.com/) as template for our ADFS project.
We have no problem with passive requests to ADFS authenticated services. In the sample, the federation provider is a custom STS, and the sample works fine.

Now we wish to replace the custom federation provider (Adatum FP in the sample) with our own ADFS.

Our setup right now is as follows (Namespaces hidden)

  • ServiceClient: Console Applicaton, calls Services
  • Services: WCF Webservice, Single method returning a string. This as is default
    [Ordertracking.Services in sample]
  • Services.Authentication: Our custom Identity Provider. This is as default [Litware.SimulatedIssuer in sample]
  • ADFS: Our Federation Provider [FederationProvider.Adatum in
    example]

ServiceClient wants to call Services, and from configuration it knows it has to get a token from IP (Services.Authentication). The token is then passed to ADFS, who validates the token
and sends a new token back to ServiceClient. The client new passes the FP token to the service, and the service (being a relying party on ADFS) verifies the token against ADFS, and performs the service method.

The issue:

Replacing the STS in the example with ADFS, seems to break the integration. We seem to be getting the token from the IP back correctly, but we are running into problems when passing the IP token to ADFS.
It seems that we have a problem with our Audience Uri's, but we have added

https://'adfs fqdn'/adfs/services/Trust/13/IssuedTokenMixedSymmetricBasic256

Client Exception
We get an MessageSecurityException in the client with this InnerException
InnerException
{"ID3242: The security token could not be authenticated or authorized."}

[System.ServiceModel.FaultException]: {"ID3242: The security token could not be authenticated or authorized."}
Data: {System.Collections.ListDictionaryInternal}
HelpLink: null
InnerException: null
Message: "ID3242: The security token could not be authenticated or authorized."
Source: null
StackTrace: null
TargetSite: null

ADFS Debug log

<TraceRecord xmlns="http://schemas.microsoft.com/2009/10/IdentityModel/TraceRecord" Severity="Error">
    <Description>Handled exception.</Description>
    <AppDomain>Microsoft.IdentityServer.ServiceHost.exe</AppDomain>
    <Exception>
        <ExceptionType>Microsoft.IdentityModel.Tokens.AudienceUriValidationFailedException, Microsoft.IdentityModel, Version=3.5.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35</ExceptionType>
        <Message>ID1038: The AudienceRestrictionCondition was not valid because the specified Audience is not present in AudienceUris. Audience: 'https://<adfs fqdn>/adfs/services/Trust/13/IssuedTokenMixedSymmetricBasic256'</Message>
        <StackTrace>
  at Microsoft.IdentityModel.Tokens.SamlSecurityTokenRequirement.ValidateAudienceRestriction(IList`1 allowedAudienceUris, IList`1 tokenAudiences) at Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.ValidateConditions(Saml2Conditions conditions, Boolean enforceAudienceRestriction) at Microsoft.IdentityModel.Tokens.Saml2.Saml2SecurityTokenHandler.ValidateToken(SecurityToken token) at Microsoft.IdentityServer.Service.Tokens.MSISSaml2TokenHandler.ValidateToken(SecurityToken token) at Microsoft.IdentityModel.Tokens.WrappedSaml2SecurityTokenAuthenticator.ValidateTokenCore(SecurityToken token) at System.IdentityModel.Selectors.SecurityTokenAuthenticator.ValidateToken(SecurityToken token) at Microsoft.IdentityModel.Tokens.WrappedSamlSecurityTokenAuthenticator.ValidateTokenCore(SecurityToken token) at System.IdentityModel.Selectors.SecurityTokenAuthenticator.ValidateToken(SecurityToken token) at System.ServiceModel.Security.ReceiveSecurityHeader.ReadToken(XmlReader reader, SecurityTokenResolver tokenResolver, IList`1 allowedTokenAuthenticators, SecurityTokenAuthenticator&amp; usedTokenAuthenticator) at
  ....
        </StackTrace>
    </Exception>
</TraceRecord>

We have added the audience uri to our IP Web.config:

<audienceUris mode="Always">
    <add value="https://<adfs fqdn>/adfs/services/Trust/13/IssuedTokenMixedSymmetricBasic256" />
</audienceUris>

If necessary we can post additional config files and screenshots of ADFS configuration.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

友谊不毕业 2024-12-18 01:23:41

这需要一些工作,但我们终于解决了问题。我们没有配置它,而是在代码中构建了连接。我想我们可能在客户端配置中的某个地方出现了错误。

对任何尝试此操作的人的一些建议 - 首先在代码中建立连接。 XML 配置有点难以使用。

我们在leastprivilege.com上找到了一些示例代码

private static SecurityToken GetIdPToken()
    {

        var factory = new WSTrustChannelFactory(
            new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential),
            "https://systemidp.dk/Issuer.svc");
        factory.TrustVersion = TrustVersion.WSTrust13;

        factory.Credentials.UserName.UserName = "LITWARE\\rick";
        factory.Credentials.UserName.Password = "thisPasswordIsNotChecked";

        var rst = new RequestSecurityToken
        {
            RequestType = WSTrust13Constants.RequestTypes.Issue,
            AppliesTo = new EndpointAddress("https://adfsfqdn/adfs/services/trust"),
            KeyType = WSTrust13Constants.KeyTypes.Symmetric,
            ReplyTo = "https://adfsfqdn/adfs/services/trust/13/issuedtokenmixedsymmetricbasic256/"
        };
        factory.ConfigureChannelFactory();
        var channel = factory.CreateChannel();
        return channel.Issue(rst);
    }

    private static SecurityToken GetRSTSToken(SecurityToken idpToken)
    {
        var binding = new IssuedTokenWSTrustBinding();
        binding.SecurityMode = SecurityMode.TransportWithMessageCredential;

        var factory = new WSTrustChannelFactory(
            binding,
            "https://adfsfqdn/adfs/services/trust/13/issuedtokenmixedsymmetricbasic256/");
        factory.TrustVersion = TrustVersion.WSTrust13;
        factory.Credentials.SupportInteractive = false;

        var rst = new RequestSecurityToken
        {
            RequestType = WSTrust13Constants.RequestTypes.Issue,
            AppliesTo = new EndpointAddress("https://services.dk/WebService.svc"),
            KeyType = WSTrust13Constants.KeyTypes.Symmetric
        };

        factory.ConfigureChannelFactory();
        var channel = factory.CreateChannelWithIssuedToken(idpToken);
        return channel.Issue(rst);
    }

使用令牌创建WCF调用

var ipdtoken = GetIdPToken();
var stsToken = GetRSTSToken(ipdtoken);
var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.TransportWithMessageCredential);
binding.Security.Message.EstablishSecurityContext = false;
var factory = new ChannelFactory<IWebService>(binding, "https://services.dk/WebService.svc");

factory.ConfigureChannelFactory();
factory.Credentials.SupportInteractive = false;

var serviceChannel = factory.CreateChannelWithIssuedToken(stsToken);

var s = serviceChannel.GetUserInformation();

This took a bit of work but we finally solved the problem. Instead of configuring this, we built the connection in code. I'm thinking we probably had an error somewhere in the client configuration.

Some advice to anyone trying this - build the connections in code first. The XML configuration is a bit harder to work with.

We found some sample code on leastprivilege.com

private static SecurityToken GetIdPToken()
    {

        var factory = new WSTrustChannelFactory(
            new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential),
            "https://systemidp.dk/Issuer.svc");
        factory.TrustVersion = TrustVersion.WSTrust13;

        factory.Credentials.UserName.UserName = "LITWARE\\rick";
        factory.Credentials.UserName.Password = "thisPasswordIsNotChecked";

        var rst = new RequestSecurityToken
        {
            RequestType = WSTrust13Constants.RequestTypes.Issue,
            AppliesTo = new EndpointAddress("https://adfsfqdn/adfs/services/trust"),
            KeyType = WSTrust13Constants.KeyTypes.Symmetric,
            ReplyTo = "https://adfsfqdn/adfs/services/trust/13/issuedtokenmixedsymmetricbasic256/"
        };
        factory.ConfigureChannelFactory();
        var channel = factory.CreateChannel();
        return channel.Issue(rst);
    }

    private static SecurityToken GetRSTSToken(SecurityToken idpToken)
    {
        var binding = new IssuedTokenWSTrustBinding();
        binding.SecurityMode = SecurityMode.TransportWithMessageCredential;

        var factory = new WSTrustChannelFactory(
            binding,
            "https://adfsfqdn/adfs/services/trust/13/issuedtokenmixedsymmetricbasic256/");
        factory.TrustVersion = TrustVersion.WSTrust13;
        factory.Credentials.SupportInteractive = false;

        var rst = new RequestSecurityToken
        {
            RequestType = WSTrust13Constants.RequestTypes.Issue,
            AppliesTo = new EndpointAddress("https://services.dk/WebService.svc"),
            KeyType = WSTrust13Constants.KeyTypes.Symmetric
        };

        factory.ConfigureChannelFactory();
        var channel = factory.CreateChannelWithIssuedToken(idpToken);
        return channel.Issue(rst);
    }

Creating a WCF call with the token

var ipdtoken = GetIdPToken();
var stsToken = GetRSTSToken(ipdtoken);
var binding = new WS2007FederationHttpBinding(WSFederationHttpSecurityMode.TransportWithMessageCredential);
binding.Security.Message.EstablishSecurityContext = false;
var factory = new ChannelFactory<IWebService>(binding, "https://services.dk/WebService.svc");

factory.ConfigureChannelFactory();
factory.Credentials.SupportInteractive = false;

var serviceChannel = factory.CreateChannelWithIssuedToken(stsToken);

var s = serviceChannel.GetUserInformation();
时光无声 2024-12-18 01:23:41

您的 IP 上的 AudienceUri 配置看起来不错。我认为 ADFS 是引发 ID3242 故障的原因。您能否检查以确保您的 IP 在 ADFS 服务器上的声明提供者信任下正确配置?

如果您手边有 IP 的联合元数据,您还可以尝试在 ADFS 中重新创建它。

The audienceUri configuration on your IP looks fine. I think ADFS is the one that's throwing the ID3242 fault. Can you check to make sure your IP is correctly configured under Claim Provider Trusts on your ADFS server?

If you have your IP's federation metadata handy, you could also try recreating it in ADFS.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文