SSO Sustainsys.Saml2.Owin Request is not Authenticated - access_denied

[亡魂溺海] 提交于 2021-02-18 08:50:31

问题


I have to do SSO authentication with saml2 for my existing asp.net web application.

I am using Sustainsys.Saml2.Owin example to do that.

Identity provider is Azure ADFS ( https://sts.windows.net/TENANTID )

I have configured the Startup file. It loads the metadata file and certificate.

And in my Login page, I am challenging if not authenticated.

It is successfully redirecting to the login page but the Request is never getting authenticated after the login. And in the reply URL we are getting error=access_denied

[neither Request.IsAuthenticated or owinContext.Authentication.User.Identity.IsAuthenticated is set to true]

So it keep on challenging for many times and error with bad request.

What I am doing wrong? Which module of Owin/Sustainsys is reposnsible to set the IsAuthenticated status?

*a Saml2. cookie [Saml2.DAeP63c***UTX0h***_***] is passed along with the request after login into Microsoft [https://login.microsoftonline.com/TENANTID/saml2]

Startup.cs file

    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:


(all code posted here are the same sample from Github)

You need to understand how SAML works, here's a simple saml implementation class that I used before I dive into SustainsysSAML. AspNetSaml

This is the basic flow of SAML Implementation:

  1. User access your app, if user is not yet authenticated your app should redirect the user to your saml provider.

    //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. From saml provider, user enters credentials and if valid user, saml provider will authenticate and redirect the user to your app.

  3. SAML provider will post the samlresponse to your app (eg. 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. Your app will read the samlresponse and if valid will let the user use your app, your app will now handle the roles of the user depending on your policies.

Some tips:

  1. Make sure your app is identifiable by your saml provider.
  2. Use Firebug to trace your http requests (or any http tracing tool)
  3. Understand the difference between samlresponse and samlrequest
  4. Using Firebug you should be able to see the samlresponse.
  5. If you have multiple web apps that you want to have SSO using your saml provider. I suggest you create an httprequest/httphandler to handle the samlresponse from your provider. You can then install this dll to your server and just add the handler to each web app's config. No code change require to your web apps :).

I hope this helps.



来源:https://stackoverflow.com/questions/56439364/sso-sustainsys-saml2-owin-request-is-not-authenticated-access-denied

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!