Support

Stel vragen op Stack Overflow en tag met 'itfoxtec-identity-saml2'.

Neem contact op met contact@foxids.com voor betaalde consultancy.

Pakket

Releases
NuGet ITfoxtec Identity SAML 2.0
NuGet ITfoxtec Identity SAML 2.0 MVC
NuGet ITfoxtec Identity SAML 2.0 MVC Core

Code en licentie

GitHub code en voorbeeld
Open-source licentie

ITfoxtec Identity SAML 2.0

Het open source ITfoxtec Identity Saml2 pakket voegt SAML-P ondersteuning toe voor zowel Identity Provider (IdP) als Relying Party (RP) bovenop de SAML 2.0 functionaliteit die in .NET is geïmplementeerd.

De bedrijfsnaam ITfoxtec is gewijzigd in FoxIDs maar de componenten behouden voorlopig de ITfoxtec naam als onderdeel van de componentnaam.

Ondersteunde .NET versies:
  • .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

Het ITfoxtec Identity Saml2 pakket implementeert de belangrijkste onderdelen van de SAML-P standaard en enkele optionele functies. Berichtondertekening en validatie en ook decryptie worden ondersteund. Het pakket ondersteunt SAML 2.0 login, logout, single logout en metadata. Zowel SP Initiated als IdP Initiated sign on wordt ondersteund.

Het ITfoxtec Identity Saml2 pakket is getest op conformiteit met Microsoft Entra ID (Azure AD), AD FS, Azure AD B2C, de Deense NemLog-in3 (MitID), de Deense Context Handler (in het Deens Fælleskommunal Adgangsstyring) en vele andere IdP's en RP's.

Zie de testvoorbeelden.

Neem contact op met Anders Revsgaard (anders@foxids.com) als je een voorbeeld nodig hebt voor een specifieke IdP zoals de Deense NemLog-in (MitID) of Context Handler.
Dit is een betaalde service waarbij je een kant-en-klaar voorbeeldpakket voor een IdP kunt kopen of een aangepast voorbeeld kunt aanvragen.

Je kunt de SAML 2.0 tool gebruiken om tokens te decoderen en zelfondertekende certificaten te maken met de certificaattool.

Ondersteunde bindings:

  • Redirect Binding
  • Post Binding
  • Artifact Binding

Bindings kunnen naar behoefte worden gebruikt voor:

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

SHA1/SHA256/SHA384/SHA512 wordt ondersteund voor berichtondertekening.

  • 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 en ASP.NET MVC Core worden ondersteund door de ITfoxtec Identity SAML 2.0 MVC en MVC Core pakketten die helpen om het ITfoxtec SAML 2.0 pakket te integreren in een MVC en MVC Core applicatie.

Code

De getoonde code is slechts een selectie van de voorbeeldcode in GitHub.

Het ITfoxtec Identity Saml2 pakket wordt geïntegreerd in een ASP.NET MVC Core Relying Party (RP) applicatie door configuratie in Startup en door een Auth Controller toe te voegen met de volgende vier methoden. De getoonde binding kan naar behoefte worden aangepast afhankelijk van de vereisten.

Daarnaast is het mogelijk om enkele optionele parameters in te stellen op de Saml2AuthnRequest en Saml2LogoutRequest. Op de Saml2AuthnRequest wordt bijvoorbeeld ForceAuthn ondersteund, waardoor de gebruiker gedwongen wordt om inloggegevens in te voeren, zelfs als er al een SSO context bestaat bij de Security Token Service (STS) / Identity Provider (IdP).


Voeg configuratie toe aan de ConfigureServices methode in Startup

Configuratie met IdP metadata.
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();   

Configuratie zonder metadata.
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();   

Login methode in de Auth Controller

[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();
}

AssertionConsumerService methode in de Auth Controller

Na een geslaagde of mislukte login ontvangt de ACS methode de response.
[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);
}

Logout methode in de Auth Controller

[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();
}

LoggedOut methode in de Auth Controller

Na een geslaagde of mislukte logout ontvangt de LoggedOut methode de response.
[Route("LoggedOut")]
public IActionResult LoggedOut()
{
    var httpRequest = Request.ToGenericHttpRequest(validate: true);
    httpRequest.Binding.Unbind(httpRequest, new Saml2LogoutResponse(config));

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

SingleLogout methode in de Auth Controller

Ontvangt een Single Logout verzoek en stuurt een response.
[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();
}

Uw privacy

We gebruiken cookies om uw ervaring op onze websites te verbeteren. Klik op de knop 'Alle cookies accepteren' om akkoord te gaan met het gebruik van cookies. Om niet-noodzakelijke cookies te weigeren, klikt u op 'Alleen noodzakelijke cookies'.

Bezoek onze privacyverklaring voor meer informatie