Search code examples
owinsaml-2.0sustainsys-saml2

Send SignIn request to Idp- Sustainsys Saml2


I want to send sign in request for IdP for every unauthenticated request to my Web Application. I am using Sustainsys.Saml2.Owin. I am using the default StubIdp.

In the configuration method, I have added a filter which checks if incoming request is authenticated. If it is not, I issue an OWIN challenge.

My problem is that, the OWIN challenge is not redirecting the application to StubIdp login page. What am I missing here?

Following is the code for Startup.Auth.cs class

    public void Configuration(IAppBuilder app)
{
    app.SetDefaultSignInAsAuthenticationType(CookieAuthenticationDefaults.AuthenticationType);

    app.CreatePerOwinContext(ApplicationDbContext.Create);
    app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
    app.CreatePerOwinContext<ApplicationSignInManager>(ApplicationSignInManager.Create);

    // Enable the application to use a cookie to store information for the signed in user
    // and to use a cookie to temporarily store information about a user logging in with a third party login provider
    // Configure the sign in cookie
    app.UseCookieAuthentication(new CookieAuthenticationOptions
    {
        CookieName = "MyJobSizeToken",
        CookieSecure = CookieSecureOption.Always,
        CookieHttpOnly = true,
        AuthenticationType = DefaultAuthenticationTypes.ApplicationCookie,
        LoginPath = new PathString("/Account/Login"),
        Provider = new CookieAuthenticationProvider
        {
            // Enables the application to validate the security stamp when the user logs in.
            // This is a security feature which is used when you change a password or add an external login to your account.  
            OnValidateIdentity = SecurityStampValidator.OnValidateIdentity<ApplicationUserManager, ApplicationUser>(
                    validateInterval: TimeSpan.FromMinutes(30),
                    regenerateIdentity: (manager, user) => user.GenerateUserIdentityAsync(manager))
        }
    });   

    app.UseSaml2Authentication(CreateSaml2Options());

    app.Use((context, next) =>
    {
        if (!context.Authentication.User.Identity.IsAuthenticated)
        {
            //context.Environment.Add("saml2.idp", new EntityId("https://stubidp.sustainsys.com/Metadata"));
            //context.Authentication.Challenge("https://stubidp.sustainsys.com/Metadata");

            HttpContext.Current.GetOwinContext().Authentication.Challenge(new 
            AuthenticationProperties { RedirectUri = "/" }, 
            "KentorAuthServices"); // This line does not redirect to the stubidp
        }
        return next.Invoke();
    });


}    

private static Saml2AuthenticationOptions CreateSaml2Options()
{
    var spOptions = CreateSPOptions();
    var Saml2Options = new Saml2AuthenticationOptions(false)
    {
        SPOptions = spOptions
    };

    var idp = new IdentityProvider(new EntityId("https://stubidp.sustainsys.com/Metadata"), spOptions)
    {
        AllowUnsolicitedAuthnResponse = true,
        Binding = Saml2BindingType.HttpRedirect,
        SingleSignOnServiceUrl = new Uri("https://stubidp.sustainsys.com")
    };

    idp.SigningKeys.AddConfiguredKey(
        new X509Certificate2(
            HostingEnvironment.MapPath(
                "~/App_Data/stubidp.sustainsys.com.cer")));

    Saml2Options.IdentityProviders.Add(idp);

    // It's enough to just create the federation and associate it
    // with the options. The federation will load the metadata and
    // update the options with any identity providers found.
    new Federation("http://localhost:52071/Federation", true, Saml2Options);

    return Saml2Options;
}

private static SPOptions CreateSPOptions()
{
    var nz = CultureInfo.GetCultureInfo("en-nz");

    var organization = new Organization();
    organization.Names.Add(new LocalizedName("Flink Solutions", nz));
    organization.DisplayNames.Add(new LocalizedName("Flink Solutions", nz));
    organization.Urls.Add(new LocalizedUri(new Uri("http://www.Sustainsys.se"), nz));

    var spOptions = new SPOptions
    {
        EntityId = new EntityId("https://localhost:44339/Saml2"),
        ReturnUrl = new Uri("http://localhost:44339/"),
        DiscoveryServiceUrl = new Uri("http://localhost:44339/DiscoveryService"),
        Organization = organization
    };

    var techContact = new ContactPerson
    {
        Type = ContactType.Technical
    };
    techContact.EmailAddresses.Add("Saml2@example.com");
    spOptions.Contacts.Add(techContact);

    var supportContact = new ContactPerson
    {
        Type = ContactType.Support
    };
    supportContact.EmailAddresses.Add("support@example.com");
    spOptions.Contacts.Add(supportContact);

    var attributeConsumingService = new AttributeConsumingService("Saml2")
    {
        IsDefault = true,
    };

    attributeConsumingService.RequestedAttributes.Add(
        new RequestedAttribute("urn:someName")
        {
            FriendlyName = "Some Name",
            IsRequired = true,
            NameFormat = RequestedAttribute.AttributeNameFormatUri
        });

    attributeConsumingService.RequestedAttributes.Add(
        new RequestedAttribute("Minimal"));

    spOptions.AttributeConsumingServices.Add(attributeConsumingService);

    spOptions.ServiceCertificates.Add(new X509Certificate2(
        AppDomain.CurrentDomain.SetupInformation.ApplicationBase + "/App_Data/Sustainsys.Saml2.Tests.pfx"));

    return spOptions;
}

If I issue the request from a cshtml page like;

<script type="text/javascript">
   window.location.href = "/Saml2/Signin?idp=https://stubidp.sustainsys.com/Metadata";
</script>

then it works. Why can't I issue the challenge from the OWIN filter?


Solution

  • The second param to Challenge() must be the authentication scheme as set in the Saml2 options. The default is now Saml2, so replace your KentorAuthServices scheme to Saml2.