SSO Sustainsys.Saml2.Owin请求未通过身份验证-access_denied

时间:2019-06-04 07:35:03

标签: c# asp.net cookies single-sign-on sustainsys-saml2

我必须为现有的asp.net Web应用程序使用saml2进行SSO身份验证。

我正在使用Sustainsys.Saml2.Owin示例来做到这一点。

身份提供者是Azure ADFS(https://sts.windows.net/TENANTID

我已经配置了启动文件。它会加载元数据文件和证书。

在我的“登录”页面中,如果未通过身份验证,我将面临挑战。

它已成功重定向到登录页面,但是登录后请求从未得到认证。在回复URL中,我们得到 error = access_denied

[Request.IsAuthenticated或owinContext.Authentication.User.Identity.IsAuthenticated均未设置为true]

因此,它会持续挑战许多次,并因错误的请求而出错。

我做错了什么? Owin / Sustainsys的哪个模块可以设置IsAuthenticated状态?

* a Saml2。登录到Microsoft [https://login.microsoftonline.com/TENANTID/saml2]

后, cookie 与请求一起传递了[Saml2.DAeP63c *** UTX0h *** _ ***]

Startup.cs 文件

    public void ConfigureAuth(IAppBuilder appBuilder)
    {
        try
        {
            appBuilder.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

            appBuilder.UseCookieAuthentication(new CookieAuthenticationOptions());

            appBuilder.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);

            appBuilder.UseSaml2Authentication(CreateSaml2Options());
        }
        catch (Exception exp)
        {

        }
    }


    private Saml2AuthenticationOptions CreateSaml2Options()
    {
        try
        {
            var spOptions = CreateSPOptions();

            var Saml2AuthOptions = new Saml2AuthenticationOptions(false)
            {
                SPOptions = spOptions,
                Notifications = new Saml2Notifications(),
            };

            var idp = new IdentityProvider(new EntityId(authority), spOptions)
            {
                MetadataLocation = metadataLocation,
                Binding = Saml2BindingType.HttpRedirect
            };

            idp.SigningKeys.AddConfiguredKey(
                new X509Certificate2(certificateLocation));

            Saml2AuthOptions.IdentityProviders.Add(idp);

            return Saml2AuthOptions;
        }
        catch (Exception exp)
        {
        }
    }

    private SPOptions CreateSPOptions()
    {
        try
        {
            var engAus = "en-AU";

            var organization = new Organization();

            var spOptions = new SPOptions
            {
                EntityId = new EntityId(ApplicationId),
                ReturnUrl = new Uri(redirectUrl),
                Organization = organization,
            };

            return spOptions;
        }
        catch (Exception exp)
        {
        }
    }

Login.aspx.cs

protected void Page_Load(object sender, EventArgs e)
{
    if (!IsPostBack)
    {
        IOwinContext owinContext = HttpContext.Current.GetOwinContext();

        //if (Request.IsAuthenticated)
        if (owinContext.Authentication.User != null &&
            owinContext.Authentication.User.Identity != null &&
            owinContext.Authentication.User.Identity.IsAuthenticated)
        {
            //Authenticated
            string name = owinContext.Authentication.User.Identity.Name;
        }
        else
        {
            var authenticationTypes = owinContext.Authentication.GetAuthenticationTypes().Select(d => d.AuthenticationType).ToArray();

            owinContext.Authentication.Challenge(new AuthenticationProperties { RedirectUri = "/" }, authenticationTypes);
        }
    }
}

1 个答案:

答案 0 :(得分:1)

(此处发布的所有代码都是来自Github的同一示例)

您需要了解SAML的工作原理,这是我学习SustainsysSAML之前使用的一个简单的saml实现类。 AspNetSaml

这是SAML实现的基本流程:

  1. 用户访问您的应用程序,如果尚未通过用户身份验证,则您的应用程序应将用户重定向到您的saml提供程序。

    //specify the SAML provider url here, aka "Endpoint"
    var samlEndpoint = "http://saml-provider-that-we-use.com/login/";
    
    var request = new AuthRequest(
    "http://www.myapp.com", //put your app's "unique ID" here
    "http://www.myapp.com/SamlConsume" //assertion Consumer Url - the redirect URL where the provider will send authenticated users
    );
    
    //generate the provider URL
    string url = request.GetRedirectUrl(samlEndpoint);
    
    //then redirect your user to the above "url" var
    //for example, like this:
    Response.Redirect(url);
    
  2. 从saml提供程序中,用户输入凭据,如果有效用户,saml提供程序将对用户进行身份验证并将其重定向到您的应用。

  3. SAML提供程序会将samlresponse发布到您的应用程序(例如http://www.myapp.com/SamlConsum)。

    //ASP.NET MVC action method... But you can easily modify the code for Web-forms etc.
    public ActionResult SamlConsume()
    {
        //specify the certificate that your SAML provider has given to you
        string samlCertificate = @"-----BEGIN CERTIFICATE-----
    BLAHBLAHBLAHBLAHBLAHBLAHBLAHBLAHBLAHBLAHBLAHBLAH123543==
    -----END CERTIFICATE-----";
    
        Saml.Response samlResponse = new Response(samlCertificate);
        samlResponse.LoadXmlFromBase64(Request.Form["SAMLResponse"]); //SAML providers usually POST the data into this var
    
        if (samlResponse.IsValid())
        {
            //WOOHOO!!! user is logged in
            //YAY!
    
            //Some more optional stuff for you
            //lets extract username/firstname etc
            string username, email, firstname, lastname;
            try
            {
                username = samlResponse.GetNameID();
                email = samlResponse.GetEmail();
                firstname = samlResponse.GetFirstName();
                lastname = samlResponse.GetLastName();
            }
            catch(Exception ex)
            {
                //insert error handling code
                //no, really, please do
                return null;
            }
    
            //user has been authenticated, put your code here, like set a cookie or something...
            //or call FormsAuthentication.SetAuthCookie() or something
        }
    }
    
  4. 您的应用程序将读取samlresponse,并且如果有效将使用户使用您的应用程序,则您的应用程序现在将根据您的策略来处理用户的角色。

一些提示:

  1. 确保您的应用可以被saml提供商识别。
  2. 使用Firebug跟踪您的http请求(或任何http跟踪工具)
  3. 了解samlresponse和samlrequest之间的区别
  4. 使用Firebug,您应该可以看到samlresponse。
  5. 如果您有多个Web应用程序,则希望使用saml提供程序进行SSO。建议您创建一个httprequest / httphandler来处理提供者的samlresponse。然后,您可以将此dll安装到您的服务器,然后将处理程序添加到每个Web应用程序的配置中。无需更改您的网络应用程序的代码即可:)。

我希望这会有所帮助。