Sustainsys / Saml2

Saml2 Authentication services for ASP.NET
Other
952 stars 600 forks source link

Callback AuthenticateAsync external Succeeded always false #1460

Closed mariovh87 closed 1 month ago

mariovh87 commented 1 month ago

Hello,

Im trying to implement SAML2 authentication in Blazor Wasm Hosted, in Server project, similar to AspNetCoreExternalCallBack example. `public class CallbackModel : PageModel { public async Task OnGet() { var external = await HttpContext.AuthenticateAsync("external");

    if (!external.Succeeded)
    {
        throw new InvalidOperationException();
    }

    var claims = new List<Claim>
    {
        new("sub", external.Principal!.FindFirstValue(ClaimTypes.NameIdentifier)),
    };

    var givenName = external.Principal!.FindFirstValue("Subject_GivenName");
    var surName = external.Principal!.FindFirstValue("Subject_Surname");

    var name = (givenName + " " + surName).Trim();

    if (!string.IsNullOrEmpty(name))
    {
        claims.Add(new Claim("name", name));
    }

    // The logout nameidentifier and session index claims are required to be able to
    // initiate a Saml2 logout.
    var logoutNameId = external.Principal!.FindFirst(Saml2ClaimTypes.LogoutNameIdentifier);
    var sessionIndex = external.Principal.FindFirst(Saml2ClaimTypes.SessionIndex);

    if (logoutNameId != null && sessionIndex != null)
    {
        claims.Add(logoutNameId);
        claims.Add(sessionIndex);
    }

    foreach (var role in external.Principal!.FindAll(ClaimTypes.Role))
    {
        // Don't just accept roles from the Idp, pick what roles the Idp
        // is allowed to send and translate it to our app role claim type and
        // app role name.
        if (role.Value == "Administrator")
        {
            claims.Add(new Claim("role", "admin"));
        }
    }

    // Create an identity and principal that is in the right format for our application.
    // Always use the four param version of the ClaimsIdentity constructor
    var identity = new ClaimsIdentity(claims, "Saml2", "name", "role");
    var principal = new ClaimsPrincipal(identity);

    // Sign in to create a session in our application.
    await HttpContext.SignInAsync(principal);
    // Now we are done with the external identity, call signout on it to remove cookie.
    await HttpContext.SignOutAsync("external");

    // Finally redirect to the destination url that was put in the props by login.cshtml.cs
    return Redirect(external.Properties!.Items["returnUrl"]!);
}

}`

Always false so throws InvalidOperationException.

This is service configuration:

` services.AddAuthentication("cookie") .AddCookie("cookie", opt => { opt.LoginPath = "/Login"; }) .AddCookie("external") .AddSaml2(Saml2Defaults.Scheme, opt => { opt.SignInScheme = "external";

     opt.SPOptions.EntityId = new EntityId("https://localhost:5001/ShoppingCart");

     opt.SPOptions.ServiceCertificates.Add(new X509Certificate2("Sustainsys.Saml2.Tests.pfx"));

     opt.IdentityProviders.Add(new IdentityProvider(
         new EntityId("https://stubidp.sustainsys.com/Metadata"),
         opt.SPOptions)
     {
         LoadMetadata = true
     });
 });`

Thanks

mariovh87 commented 1 month ago

Ispecting with Saml Chrome Panel, Callback to 'https://localhost:5001/ShoppingCart/Saml2/Acs' its returning 303 SAMLChromeExport.json