【问题标题】:How to authenticate a request from a c# application to a WIF enabled ASP.NET WebApi application using a SAML assertion如何使用 SAML 断言验证从 c# 应用程序到启用 WIF 的 ASP.NET WebApi 应用程序的请求
【发布时间】:2013-10-16 07:36:40
【问题描述】:

我已将 ThinkTecture 身份服务器设置为 STS,设置了 Web api 项目,并使用了 Visual Studio 中的“身份和访问”工具,并将其指向我的联合元数据以启用使用 WIF 的联合身份验证。这是 web.config 的相关部分的样子:

<system.identityModel>
    <identityConfiguration saveBootstrapContext="true">
      <audienceUris>
        <add value="http://localhost:41740/" />
      </audienceUris>

    <securityTokenHandlers>
        <add type="System.IdentityModel.Tokens.SamlSecurityTokenHandler, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
        <add type="System.IdentityModel.Tokens.Saml2SecurityTokenHandler, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
    </securityTokenHandlers>            

      <issuerNameRegistry type="System.IdentityModel.Tokens.ValidatingIssuerNameRegistry, System.IdentityModel.Tokens.ValidatingIssuerNameRegistry">
        <authority name="http://auth.myserver.com/samples">
          <keys>
            <add thumbprint="F89C10B505E015774D02E323DEDA32878F794028" />
          </keys>
          <validIssuers>
            <add name="http://auth.myserver.com/samples" />
          </validIssuers>
        </authority>
      </issuerNameRegistry>
      <!--certificationValidationMode set to "None" by the the Identity and Access Tool for Visual Studio. For development purposes.-->
      <certificateValidation certificateValidationMode="None" />
    </identityConfiguration>
  </system.identityModel>
  <system.identityModel.services>
    <federationConfiguration>
      <cookieHandler requireSsl="false" />
      <wsFederation passiveRedirectEnabled="true" issuer="https://10.40.40.68/issue/wsfed" realm="http://localhost:41740/" requireHttps="false" />
    </federationConfiguration>
  </system.identityModel.services>

这非常适合验证从浏览器使用 API 的用户。

我现在需要从客户端应用程序中的代码 (C#) 调用相同的 API - 让我们调用 APIClient - 使用 HTTPClient。

为此,我将其添加到 web.config:

<securityTokenHandlers>
        <!--<add type="System.IdentityModel.Tokens.JwtSecurityTokenHandler, System.IdentityModel.Tokens.Jwt" />-->
        <add type="System.IdentityModel.Tokens.SamlSecurityTokenHandler, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
        <add type="System.IdentityModel.Tokens.Saml2SecurityTokenHandler, System.IdentityModel, Version=4.0.0.0, Culture=neutral, PublicKeyToken=B77A5C561934E089" />
</securityTokenHandlers>

我的假设是,如果我添加 SAML 令牌处理程序并将 SAML 断言添加到 HTTP Authorize 标头,WIF 将选择它并对请求进行身份验证。

我可以调用 STS 来获取 SAML 令牌,如此处的 GetSamlToken 方法所述:enter link description here

这给了我一个附加到 HTTPClient 标头的 SAML 断言:

client.SetToken("SAML", AuthenticationHeader);

AuthenticationHeader 是我从服务器收到的 SAML 断言。 问题是 web api 没有对 samle 断言做任何事情 - 好像它甚至没有看到它,我得到的只是一个重定向到 STS 的响应。

我做错了什么?如何在无需切换到 JWT 等的情况下验证并从其他代码调用受保护的 Web api 方法?

提前感谢您的帮助!

--更新

按照@Brock 的建议,我已将以下内容添加到我的 WebApiConfig.cs 中:

public static void Register(HttpConfiguration config)
{
    // Cross Origin Resource Sharing
    //CorsConfig.RegisterCors(GlobalConfiguration.Configuration);
    CorsConfig.RegisterCors(config);


    //CorsConfiguration corsConfig = new CorsConfiguration();
    //corsConfig.AllowAll();
    //var corsHandler = new CorsMessageHandler(corsConfig, config);
    //config.MessageHandlers.Add(corsHandler);


    // authentication configuration for identity controller
    var authentication = CreateAuthenticationConfiguration();
    config.MessageHandlers.Add(new AuthenticationHandler(authentication));



    // ASP.Net web api uses NewtonSoft Json.net natively, 
    // the following line forces the web api to use the xml serializer instead of data contract serializer
    config.Formatters.XmlFormatter.UseXmlSerializer = true;

    log.Debug("Registering Web API Routes");


    // register api routes

}




private static AuthenticationConfiguration CreateAuthenticationConfiguration()
{
    var authentication = new AuthenticationConfiguration
    {
        ClaimsAuthenticationManager = new ClaimsTransformer(),
        RequireSsl = false,
        EnableSessionToken = true
    };

    #region IdentityServer SAML
    authentication.AddSaml2(
        issuerThumbprint: "F89C10B505E015774D02E323DEDA32878F794028",
        issuerName: "https://10.40.40.68/issue/wsfed",
        audienceUri: "http://localhost:41740/",//Constants.Realm,
        certificateValidator: System.IdentityModel.Selectors.X509CertificateValidator.None,
        options: AuthenticationOptions.ForAuthorizationHeader("SAML"),
        scheme: AuthenticationScheme.SchemeOnly("SAML"));
    #endregion

    #region Client Certificates
    authentication.AddClientCertificate(ClientCertificateMode.ChainValidation);
    #endregion

    return authentication;
}

但是我仍然收到 302 响应。这就是我提出请求的方式:

ServicePointManager.ServerCertificateValidationCallback += (sender, certificate, chain, sslPolicyErrors) => true;


var factory = new WSTrustChannelFactory(
    new UserNameWSTrustBinding(SecurityMode.TransportWithMessageCredential),
    "https://10.40.40.68/issue/wstrust/mixed/username");
factory.TrustVersion = TrustVersion.WSTrust13;

factory.Credentials.UserName.UserName = "myusername";
factory.Credentials.UserName.Password = "password";

var rst = new RequestSecurityToken
{
    RequestType = RequestTypes.Issue,
    KeyType = KeyTypes.Bearer,
    TokenType = Thinktecture.IdentityModel.Constants.TokenTypes.Saml2TokenProfile11,
    AppliesTo = new EndpointReference("http://localhost:41740/")
};

var token = factory.CreateChannel().Issue(rst) as System.IdentityModel.Tokens.GenericXmlSecurityToken;

string myToken = token.TokenXml.OuterXml;

HttpClient client = new HttpClient(new HttpClientHandler
{
    ClientCertificateOptions = ClientCertificateOption.Automatic,
    AllowAutoRedirect = false
});

client.SetToken("SAML", myToken);
//client.SetBearerToken(myToken);

var resp = client.GetAsync("http://localhost:41740/api/clients", HttpCompletionOption.ResponseContentRead).Result;
Assert.IsTrue(resp.IsSuccessStatusCode);

【问题讨论】:

    标签: security asp.net-web-api wif saml thinktecture-ident-server


    【解决方案1】:

    Web API v1 没有自动在请求中查找令牌的管道。 Thinktecture IdentityModel 在其 Web API 身份验证消息处理程序中提供了这个缺失的功能。查看示例文件夹以获取示例(特别是 AuthenticationConfiguration 类和 AddSaml2 API):

    https://github.com/thinktecture/Thinktecture.IdentityModel.45/tree/master/Samples/Web%20API%20Security

    【讨论】:

    • 非常感谢您的帮助布洛克。我按照您的解释添加了 Saml2 AuthenticationHandler,但没有得到任何结果。你知道我还有什么可以尝试的吗?我将我从 STS 获得的断言与 STS 在“正常”登录场景中的 wsresult 帖子字段中发送到 RP 的断言进行了比较,除了时间戳和摘要值、签名值等。其余的或多或少是相同的。我还删除了已添加到 web.config 但仍然无法获取任何内容的令牌处理程序。
    • 我终于解决了这个问题。问题是 WSFederationAuthenticationModule 和 SessionAuthenticationModule 在 ThinkTecture IdentityModel Authentication hnadlers 可以到达之前重定向了请求。为了解决这个问题,在“身份和访问”向导中,我选择了“生成控制器以处理身份验证...”,它将身份验证模式设置为表单并删除授权/拒绝用户=?属性表单 web.config 并将所有未经身份验证的调用重定向到另一个控制器,但也让其他处理程序有机会处理请求并在必要时对其进行身份验证
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-06-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多