Support

Posez vos questions sur Stack Overflow et taguez avec « itfoxtec-identity-saml2 ».

Contactez contact@foxids.com pour du conseil payant.

Package

Versions
NuGet ITfoxtec Identity SAML 2.0
NuGet ITfoxtec Identity SAML 2.0 MVC
NuGet ITfoxtec Identity SAML 2.0 MVC Core

Code et licence

Code et exemple GitHub
Licence open-source

ITfoxtec Identity SAML 2.0

Le package open-source ITfoxtec Identity Saml2 ajoute la prise en charge SAML-P pour Identity Provider (IdP) et Relying Party (RP) en complément de la fonctionnalité SAML 2.0 implémentée en .NET.

Le nom de la société ITfoxtec a changé pour FoxIDs mais les composants conservent pour l’instant le nom ITfoxtec dans le nom du composant.

Versions .NET prises en charge :
  • .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

Le package ITfoxtec Identity Saml2 implémente les parties les plus importantes du standard SAML-P ainsi que certaines fonctionnalités optionnelles. La signature et la validation des messages ainsi que le déchiffrement sont pris en charge. Le package supporte la connexion, la déconnexion, le single logout et les métadonnées SAML 2.0. Les connexions SP Initiated et IdP Initiated sont prises en charge.

Le package ITfoxtec Identity Saml2 est testé pour la conformité avec Microsoft Entra ID (Azure AD), AD FS, Azure AD B2C, le NemLog-in3 danois (MitID), le Context Handler danois (appelé en danois Fælleskommunal Adgangsstyring) et de nombreux autres IdP et RP.

Veuillez consulter les exemples de test.

Contactez Anders Revsgaard (anders@foxids.com) si vous avez besoin d’un exemple pour un IdP spécifique tel que le NemLog-in (MitID) danois ou Context Handler.
C’est un service payant où vous pouvez acheter un exemple prêt à l’emploi pour un IdP ou demander un exemple personnalisé.

Vous pouvez utiliser l’ outil SAML 2.0 pour décoder les jetons et créer des certificats auto-signés avec l’ outil de certificats.

Bindings pris en charge :

  • Redirect Binding
  • Post Binding
  • Artifact Binding

Les bindings peuvent être utilisés au besoin pour :

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

SHA1/SHA256/SHA384/SHA512 sont pris en charge pour la signature des messages.

  • 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 et ASP.NET MVC Core sont pris en charge par les packages ITfoxtec Identity SAML 2.0 MVC et MVC Core qui aident à intégrer le package ITfoxtec SAML 2.0 dans une application MVC ou MVC Core.

Code

Le code présenté n’est qu’une sélection du code d’exemple sur GitHub.

Le package ITfoxtec Identity Saml2 est intégré dans une application ASP.NET MVC Core Relying Party (RP) via la configuration dans Startup et l’ajout d’un Auth Controller avec les quatre méthodes suivantes. Le binding présenté peut être modifié selon les besoins.

Il est également possible de définir des paramètres optionnels sur Saml2AuthnRequest et Saml2LogoutRequest. Sur Saml2AuthnRequest, par exemple, ForceAuthn est pris en charge, ce qui force l’utilisateur à saisir ses identifiants même si un contexte SSO existe déjà sur le Security Token Service (STS) / Identity Provider (IdP).


Ajouter la configuration à la méthode ConfigureServices dans Startup

Configuration à l’aide des métadonnées 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();   

Configuration sans métadonnées.
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();   

Méthode de connexion dans le 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();
}

Méthode AssertionConsumerService dans le Auth Controller

Après une connexion réussie ou échouée, la méthode ACS reçoit la réponse.
[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);
}

Méthode de déconnexion dans le 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();
}

Méthode LoggedOut dans le Auth Controller

Après une déconnexion réussie ou échouée, la méthode logged out reçoit la réponse.
[Route("LoggedOut")]
public IActionResult LoggedOut()
{
    var httpRequest = Request.ToGenericHttpRequest(validate: true);
    httpRequest.Binding.Unbind(httpRequest, new Saml2LogoutResponse(config));

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

Méthode SingleLogout dans le Auth Controller

Reçoit une requête Single Logout et envoie une réponse.
[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();
}

Votre confidentialité

Nous utilisons des cookies pour améliorer votre expérience sur nos sites. Cliquez sur « Accepter tous les cookies » pour accepter l'utilisation des cookies. Pour refuser les cookies non essentiels, cliquez sur « Cookies nécessaires uniquement ».

Consultez notre politique de confidentialité pour en savoir plus