如何在ASP.NET MVC中实现单点登录(ADFS)

3
FYI:请参见2019年2月12日更新
我创建了一个ASP.NET MVC应用程序(使用Visual Studio),并尝试使用Active Directory联合服务器处理SSO。请注意,这不是使用Azure。
因此,第一步起作用-我导航到我的登录页面,有一个按钮允许我登录到另一个服务[“联合”]。这将启动ADFS网页,在那里我输入我的凭据,但返回到我的网站时,我收到以下错误:
IDX10214:受众验证失败。受众群体:'[PII is hidden]'。 未匹配:validationParameters.ValidAudience:'[PII is hidden]' 或validationParameters.ValidAudiences:'[PII is hidden]'。
异常详细信息: Microsoft.IdentityModel.Tokens.SecurityTokenInvalidAudienceException: IDX10214:受众验证失败。受众群体:'[PII is hidden]'。 未匹配:validationParameters.ValidAudience:'[PII is hidden]' 或validationParameters.ValidAudiences:'[PII is hidden]'。
显然,我没有正确设置这个....所以需要知道我缺少什么...
这是我的(简化的)代码:

Startup.Auth.cs

public partial class Startup
{
    public void ConfigureAuth(IAppBuilder app)
    {
        // Configure the db context, user manager and signin manager to use a single instance per request
        app.CreatePerOwinContext(ApplicationDbContext.Create);
        app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
        app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);    

        app.UseCookieAuthentication(new CookieAuthenticationOptions
        {
            AuthenticationType = WsFederationAuthenticationDefaults.AuthenticationType
        });

        app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

        ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(ValidateServerCertificate);

        app.UseWsFederationAuthentication(new WsFederationAuthenticationOptions
        {
            MetadataAddress = "https://adfs.Mydomain.com/FederationMetadata/2007-06/FederationMetadata.xml",
            Wtrealm = "https://myWebServer/myWebApplication"
        });
    }

    private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslpolicyerrors)
    {
        return true; // Our "TEST" ADFS has a fake certficate, so we don't want to validate it.
    }
}

Web.Config中的Sections

  <appSettings>
    <add key="webpages:Version" value="3.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />

    <add key="ClaimsNameIdentifier" value="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier" />
    <add key="ClaimsUPNIdentifier" value="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/upn" />
    <add key="ClaimsEmailIdentifier" value="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/emailaddress" />
  </appSettings>

  <system.web>
    <authentication mode="None" />
    <compilation debug="true" targetFramework="4.7.1" />
    <httpRuntime targetFramework="4.7.1" />
  </system.web>

(Note: 在上面的认证元素中,智能感知给了我“联合”的选项,但这会导致编译错误)。
一个有用的资源是alligatortek,但那并没有填补所有的空缺。还有其他的资源看起来很接近,但不够具体。
更新于2019年2月12日:根据下面的评论,我被建议改为按照Vittorio Bertocci的文章的方法,使用“On-Premesis”选项(这与Rober Finch的文章几乎完全相同)。生成的代码有点不同(见下文),但结果仍然相同。

Startup.Auth.cs

public partial class Startup
{
    private static readonly string realm = ConfigurationManager.AppSettings["ida:Wtrealm"];
    private static readonly string adfsMetadata = ConfigurationManager.AppSettings["ida:ADFSMetadata"];

    /// <summary>
    ///     Configures the authentication.
    /// </summary>
    /// <param name="app">The current application.</param>
    public void ConfigureAuth(IAppBuilder app)
    {
        app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);
        app.UseCookieAuthentication(new CookieAuthenticationOptions());

        ServicePointManager.ServerCertificateValidationCallback = this.ValidateServerCertificate;
        app.UseWsFederationAuthentication(
            new WsFederationAuthenticationOptions
            {
                Wtrealm = Startup.realm,
                MetadataAddress = Startup.adfsMetadata
            });
    }

    private bool ValidateServerCertificate(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslpolicyerrors)
    {
        return true; // Skips certificate validation as using a temp certificate.
    }
}

Web.Config中的部分

<appSettings>
    <add key="webpages:Version" value="3.0.0.0" />
    <add key="webpages:Enabled" value="false" />
    <add key="ClientValidationEnabled" value="true" />
    <add key="UnobtrusiveJavaScriptEnabled" value="true" />
    <add key="ida:ADFSMetadata" value="https://adfs.Mydomain.com/FederationMetadata/2007-06/FederationMetadata.xml" />
    <add key="ida:Wtrealm" value="https://myWebServer/myWebApplication" />
</appSettings>
2个回答

4

最终解决了这个问题。

在Startup.Auth.cs文件中,我暂时添加了以下行到ConfigAuth(...)方法中:

Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;

这让我意识到必须在web.config条目的“Wtrealm”值后添加一个斜杠。因此,从以下格式:
<add key="ida:Wtrealm" value="https://myWebServer/myWebApplication" />

致:

<add key="ida:Wtrealm" value="https://myWebServer/myWebApplication/" />

3

迄今为止,最简单的方法是通过 VS 中的 "On-Premises" 选项来完成。


我按照"On-Premises"文章的步骤进行操作(这似乎比我最初遵循的"alligatortek"文章更好),但当ADFS返回到我的应用程序时仍然收到相同的错误消息。不确定该如何继续。 - DrGriff
你可以在浏览器中访问ADFS元数据吗?ADFS是否具有获取证书吊销列表的外部访问权限? - rbrayb
  1. 我可以从防火墙后访问所需的服务器以及浏览器中的元数据,但它不是公开的。
  2. 对证书吊销列表不太清楚...
  3. 元数据包含<ds:DigestValue>、<ds:SignatureValue>和<X509Certificate>。除此之外,它还提到了指纹(但没有提供)。我原以为认证框架会解释这一切,并直接使用它。
- DrGriff
以下Microsoft文章显示的web.config配置比使用On-Premises链接添加的配置要多得多。不清楚Microsoft的文章是否已过时。 - DrGriff
使用"On Premises"本质上为OWIN堆栈提供元数据地址,并从中派生所有所需信息。这就是为什么web.config更小的原因。 - rbrayb
显示剩余2条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接