Wsparcie

Zadaj pytania na Stack Overflow i oznacz tagiem 'itfoxtec-identity-saml2'.

Skontaktuj się z contact@foxids.com w sprawie płatnych konsultacji.

Pakiet

Wydania
NuGet ITfoxtec Identity SAML 2.0
NuGet ITfoxtec Identity SAML 2.0 MVC
NuGet ITfoxtec Identity SAML 2.0 MVC Core

Kod i licencja

Kod i przykład na GitHub
Licencja open-source

ITfoxtec Identity SAML 2.0

Open-sourceowy pakiet ITfoxtec Identity Saml2 dodaje wsparcie SAML-P zarówno dla Identity Provider (IdP), jak i Relying Party (RP) ponad funkcjonalność SAML 2.0 zaimplementowaną w .NET.

Nazwa firmy ITfoxtec została zmieniona na FoxIDs ale komponenty na razie zachowają nazwę ITfoxtec jako część nazwy komponentu.

Obsługiwane wersje .NET:
  • .NET 10.0
  • .NET 9.0
  • .NET 8.0
  • .NET 7.0
  • .NET 6.0
  • .NET Standard 2.1
  • .NET Framework 4.6.2 and 4.8

Pakiet ITfoxtec Identity Saml2 implementuje najważniejsze części standardu SAML-P oraz część funkcji opcjonalnych. Obsługiwane są podpisywanie i walidacja komunikatów oraz deszyfrowanie. Pakiet obsługuje logowanie, wylogowanie, single logout i metadane SAML 2.0. Wspierane są zarówno logowania inicjowane przez SP, jak i przez IdP.

Pakiet ITfoxtec Identity Saml2 jest testowany pod kątem zgodności z Microsoft Entra ID (Azure AD), AD FS, Azure AD B2C, duńskim NemLog-in3 (MitID), duńskim Context Handler (po duńsku Fælleskommunal Adgangsstyring) oraz wieloma innymi IdP i RP.

Proszę zobaczyć przykłady testowe.

Skontaktuj się z Anders Revsgaard (anders@foxids.com) jeśli potrzebujesz przykładu dla konkretnego IdP, takiego jak duński NemLog-in (MitID) lub Context Handler.
To usługa płatna, w której możesz kupić gotowy pakiet przykładowy dla IdP lub zamówić spersonalizowany przykład.

Możesz użyć narzędzia SAML 2.0 do dekodowania tokenów i tworzenia certyfikatów samopodpisanych za pomocą narzędzia certyfikatów.

Obsługiwane powiązania:

  • Redirect Binding
  • Post Binding
  • Artifact Binding

Powiązania mogą być używane w razie potrzeby do:

  • Authn Request
  • Authn Response (SAML 2.0 Response)
  • Logout Request
  • Logout Response

SHA1/SHA256/SHA384/SHA512 jest obsługiwane do podpisywania komunikatów.

  • SHA1: http://www.w3.org/2000/09/xmldsig#rsa-sha1
  • SHA256: http://www.w3.org/2001/04/xmldsig-more#rsa-sha256
  • SHA384: http://www.w3.org/2001/04/xmldsig-more#rsa-sha384
  • SHA512: http://www.w3.org/2001/04/xmldsig-more#rsa-sha512

ASP.NET MVC i ASP.NET MVC Core są obsługiwane przez pakiety ITfoxtec Identity SAML 2.0 MVC i MVC Core, które pomagają zintegrować pakiet ITfoxtec SAML 2.0 z aplikacją MVC lub MVC Core.

Kod

Pokazany kod to tylko wybrana część przykładowego kodu z GitHub.

Pakiet ITfoxtec Identity Saml2 jest zintegrowany z aplikacją ASP.NET MVC Core Relying Party (RP) przez konfigurację w Startup i dodanie kontrolera Auth z następującymi czterema metodami. Pokazane powiązanie można zmienić w zależności od wymagań.

Możliwe jest również ustawienie opcjonalnych parametrów w Saml2AuthnRequest i Saml2LogoutRequest. W Saml2AuthnRequest np. wspierany jest ForceAuthn, który wymusza ponowne wprowadzenie danych logowania, nawet jeśli istnieje kontekst SSO w Security Token Service (STS) / Identity Provider (IdP).


Dodaj konfigurację do metody ConfigureServices w Startup

Konfiguracja przy użyciu metadanych IdP.
services.Configure<Saml2Configuration>(Configuration.GetSection("Saml2"));
services.Configure<Saml2Configuration>(saml2Configuration =>
{
    saml2Configuration.SigningCertificate = CertificateUtil.Load(AppEnvironment.MapToPhysicalFilePath(
        Configuration["Saml2:SigningCertificateFile"]), Configuration["Saml2:SigningCertificatePassword"]);
    saml2Configuration.AllowedAudienceUris.Add(saml2Configuration.Issuer);

    var entityDescriptor = new EntityDescriptor();
    entityDescriptor.ReadIdPSsoDescriptorFromUrl(new Uri(Configuration["Saml2:IdPMetadata"]));
    if (entityDescriptor.IdPSsoDescriptor != null)
    {
        saml2Configuration.SingleSignOnDestination = entityDescriptor.IdPSsoDescriptor.SingleSignOnServices.First().Location;
        saml2Configuration.SingleLogoutDestination = entityDescriptor.IdPSsoDescriptor.SingleLogoutServices.First().Location;
        saml2Configuration.SignatureValidationCertificates.AddRange(entityDescriptor.IdPSsoDescriptor.SigningCertificates);
    }
    else
    {
        throw new Exception("IdPSsoDescriptor not loaded from metadata.");
    }
});
services.AddSaml2();   

Konfiguracja bez metadanych.
services.Configure<Saml2Configuration>(Configuration.GetSection("Saml2"));
services.Configure<Saml2Configuration>(saml2Configuration =>
{
    saml2Configuration.SigningCertificate = CertificateUtil.Load(AppEnvironment.MapToPhysicalFilePath(
        Configuration["Saml2:SigningCertificateFile"]), Configuration["Saml2:SigningCertificatePassword"]);
    saml2Configuration.AllowedAudienceUris.Add(saml2Configuration.Issuer);

    saml2Configuration.SignatureValidationCertificates.Add(CertificateUtil.Load(AppEnvironment.MapToPhysicalFilePath(
        Configuration["Saml2:SignatureValidationCertificateFile"])));
});
services.AddSaml2();   

Metoda Login w kontrolerze Auth

[Route("Login")]
public IActionResult Login(string returnUrl = null)
{
    var binding = new Saml2RedirectBinding();
    binding.SetRelayStateQuery(new Dictionary<string, string> 
        { { relayStateReturnUrl, returnUrl ?? Url.Content("~/") } });

    return binding.Bind(new Saml2AuthnRequest(config)).ToActionResult();
}

Metoda AssertionConsumerService w kontrolerze Auth

Po udanym lub nieudanym logowaniu metoda ACS odbiera odpowiedź.
[Route("AssertionConsumerService")]
public async Task<IActionResult> AssertionConsumerService()
{       
    var httpRequest = Request.ToGenericHttpRequest(validate: true);
    var saml2AuthnResponse = new Saml2AuthnResponse(config);

    httpRequest.Binding.Unbind(httpRequest, saml2AuthnResponse);
    await saml2AuthnResponse.CreateSession(HttpContext, 
        ClaimsTransform: (claimsPrincipal) => ClaimsTransform.Transform(claimsPrincipal));

    var returnUrl = httpRequest.Binding.GetRelayStateQuery()[relayStateReturnUrl];
    return Redirect(string.IsNullOrWhiteSpace(returnUrl) ? Url.Content("~/") : returnUrl);
}

Metoda Logout w kontrolerze Auth

[HttpPost("Logout")]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Logout()
{
    if (!User.Identity.IsAuthenticated)
    {
        return Redirect(Url.Content("~/"));
    }

    var binding = new Saml2PostBinding();
    var saml2LogoutRequest = await new Saml2LogoutRequest(config, User).DeleteSession(HttpContext);
    return binding.Bind(saml2LogoutRequest).ToActionResult();
}

Metoda LoggedOut w kontrolerze Auth

Po udanym lub nieudanym wylogowaniu metoda logged out odbiera odpowiedź.
[Route("LoggedOut")]
public IActionResult LoggedOut()
{
    var httpRequest = Request.ToGenericHttpRequest(validate: true);
    httpRequest.Binding.Unbind(httpRequest, new Saml2LogoutResponse(config));

    return Redirect(Url.Content("~/"));
}

Metoda SingleLogout w kontrolerze Auth

Odbiera żądanie Single Logout i wysyła odpowiedź.
[Route("SingleLogout")]
public async Task<IActionResult> SingleLogout()
{
    Saml2StatusCodes status;
    var httpRequest = Request.ToGenericHttpRequest(validate: true);
    var logoutRequest = new Saml2LogoutRequest(config, User);
    try
    {
        httpRequest.Binding.Unbind(httpRequest, logoutRequest);
        status = Saml2StatusCodes.Success;
        await logoutRequest.DeleteSession(HttpContext);
    }
    catch (Exception exc)
    {
        // log exception
        Debug.WriteLine("SingleLogout error: " + exc.ToString());
        status = Saml2StatusCodes.RequestDenied;
    }

    var responseBinding = new Saml2PostBinding();
    responseBinding.RelayState = httpRequest.Binding.RelayState;
    var saml2LogoutResponse = new Saml2LogoutResponse(config)
    {
        InResponseToAsString = logoutRequest.IdAsString,
        Status = status,
    };
    return responseBinding.Bind(saml2LogoutResponse).ToActionResult();
}

Twoja prywatność

Używamy plików cookie, aby poprawić korzystanie z naszych stron internetowych. Kliknij przycisk „Akceptuj wszystkie pliki cookie”, aby wyrazić zgodę na ich użycie. Aby zrezygnować z nieistotnych plików cookie, kliknij „Tylko niezbędne pliki cookie”.

Odwiedź naszą politykę prywatności, aby dowiedzieć się więcej