DotNetCodeIT / spid-dotnet-sdk

SPID authentication library for .NET
BSD 3-Clause "New" or "Revised" License
1 stars 3 forks source link

Developers.Italia.SPID.SAML

developers-italia-spid-saml MyGet Build Status

Questa libreria permette di interfacciare un'applicazione ASP.NET con un IdP (Identity Provider) abilitato a SPID (Sistema Pubblico di Identità Digitale).

Tramite questa libreria è possibile effettuare l'autenticazione di un Utente registrato presso un Identity Provider attivo e richiedere alcuni dati dell'Utente (Cittadino)

Prerequisiti


Certificati per firma digitale

Per eseguire delle chiamate ad un Identity Provider (IdP) è necessario avere a disposizione un certificato per la firma della richiesta.

Nell'ambiente di test è possibile creare dei certificati self-signed tramite OpenSSL.

Linux Download:

https://www.openssl.org/source/

Windows Download:

https://slproweb.com/products/Win32OpenSSL.html

Per creare i certificati basta eseguire:

> Openssl req -newkey rsa:2048 -keyout certificati\spid-developersitalia.key  -x509 -days 365 -out certificati\spid-developersitalia.crt

Una volta generato il certificato e la chiave privata esportiamo certificato e chiave in un unico file pfx:

> Openssl pkcs12 -export -out certificati\spid-developersitalia.pfx -inkey certificati\spid-developersitalia.key -in certificati\spid-developersitalia.crt

Controllo Certificato: https://www.sslshopper.com/certificate-decoder.html

Metadata Identity Provider (IdP)

Per la comunicazione verso un Identity Provider è necessario avere a disposizione i metadata che descrivono i servizi messi a disposizione dall' IdP. Le informazioni più importanti, oltre al certificato utilizzato dall' IdP, sono:

Potete trovare alcuni metadata di esempio qui: https://github.com/congiuluc/spid-dotnet-sdk/tree/master/src/Developers.Italia.SPID/SAML/Metadata/IdP/

Metadata Service Provider (SP)

Per il corretto scambio di informazioni tra IdP e SP è necessario che anche il SP invii all' IdP il metadata contenente le configurazioni dell'SP.

Oltre alle informazioni del certificato che verrà utilizzato per la firma, le principali informazioni da inserire sono:

Potete trovare un metadata di esempio qui: https://github.com/congiuluc/spid-dotnet-sdk/tree/master/src/Developers.Italia.SPID/SAML/Metadata/SP/

https://github.com/italia/spid-testenv-backoffice

ASP.NET Core 2 FIX

Ad oggi, solo per le applicazioni ASP.NET Core 2, è necessario aggiungere il feed a myget del componente System.Security.Cryptography.Xml 4.5.0 questo perchè, l'attuale versione System.Security.Cryptography.Xml non è supportata in .net core mentre la versione 4.5.0 supporta .NET STANDARD 2.0.

Per aggiungere il feed basta aprire il menù delle opzioni di Visual Studio (menu Tools > Options) e selezionare NuGet Package Manager > Package Source ed aggiungere il seguente feed myGet:

https://dotnet.myget.org/F/dotnet-core/api/v3/index.json

N.B.: Non appena sarà rilasciata la versione 4.5.0 non sarà più necessario aggiungere il feed.


Esempi di Utilizzo


Creazione Nuova Richiesta:

 Developers.Italia.SPID.SAML.AuthRequestOptions options = new Developers.Italia.SPID.SAML.AuthRequestOptions()
 {
    //Request Unique Identifier
    UUID = Guid.NewGuid().ToString(),
    //Service Provider Unique Identifier (url like https://www.dotnetcode.it can be ok)
    SPUID = "MyServiceProviderUniqueIdentifier",
    //SPID Authentication Level (1/2/3)
    SPIDLevel = Developers.Italia.SPID.SAML.SPIDLevel.SPIDL1,
    //Identity Provider Url For SAML Request
    Destination = "https://www.myserviceprovider.com/samlurl",
    //Service Provider Consumer Service Index - Normally Callback URL (refer to Service Provider Metadata)
    AssertionConsumerServiceIndex = 0,
    //Service Provider Consuming Service Index - Normally Requested User Data(refer to Service Provider Metadata)
    AttributeConsumingServiceIndex = 0
 };

 Developers.Italia.SPID.SAML.AuthRequest request = new Developers.Italia.SPID.SAML.AuthRequest(options);

 string rsaXmlKey = "<![CDATA[<RSAKeyValue><Modulus>rBPwxOB3QM+Rhz+/...</RSAKeyValue>";

 X509Certificate2 signinCert = new X509Certificate2("MyCertPath.pfx", "MyCertPassword", X509KeyStorageFlags.Exportable);

 string samlRequest = request.GetSignedAuthRequest(signinCert, rsaXmlKey);


Esempio Controller Invio:

public IActionResult SPID()
{
    Developers.Italia.SPID.SAML.AuthRequestOptions options = new Developers.Italia.SPID.SAML.AuthRequestOptions()
    {
        //Request Unique Identifier
        UUID = Guid.NewGuid().ToString(),
        //Service Provider Unique Identifier (url like https://www.dotnetcode.it can be ok)
        SPUID = "https://www.dotnetcode.it",
        //SPID Authentication Level (1/2/3)
        SPIDLevel = Developers.Italia.SPID.SAML.SPIDLevel.SPIDL1,
        //Identity Provider Url For SAML Request
        Destination = "https://spidposte.test.poste.it/jod-fs/ssoservicepost",
        //Service Provider Consumer Service Index - Normally Callback URL (refer to Service Provider Metadata)
        AssertionConsumerServiceIndex = 0,
        //Service Provider Consuming Service Index - Normally Requested User Data(refer to Service Provider Metadata)
        AttributeConsumingServiceIndex = 0
    };

    Developers.Italia.SPID.SAML.AuthRequest request = new Developers.Italia.SPID.SAML.AuthRequest(options);

    string rsaXmlKey = "<![CDATA[<RSAKeyValue><Modulus>rBPwxOB3QM+Rhz+/...</RSAKeyValue>";
    X509Certificate2 signinCert = new X509Certificate2("MyCertPath.pfx", "MyCertPassword", X509KeyStorageFlags.Exportable);

    string samlRequest = request.GetSignedAuthRequest(signinCert, rsaXmlKey);

    string returnUrl = "/";

    if (!string.IsNullOrEmpty(HttpContext.Request.Query["redirectUrl"]))
    {
        returnUrl = HttpContext.Request.Query["redirectUrl"];
    }

    ViewData["FormUrlAction"] = options.Destination;
    ViewData["SAMLRequest"] = System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(samlRequest));
    ViewData["RelayState"] = System.Convert.ToBase64String(System.Text.Encoding.UTF8.GetBytes(returnUrl));

    return View();
}


Esempio Controller Ricezione:

// POST: SpidSaml/ACS
[HttpPost]
public ActionResult ACS(IFormCollection collection)
{
    string samlResponse = "";
    string redirect = "";
    SAML.AuthResponse resp = new SAML.AuthResponse();
    try
    {
        samlResponse = Encoding.UTF8.GetString(Convert.FromBase64String(collection["SAMLResponse"]));
        redirect = Encoding.UTF8.GetString(Convert.FromBase64String(collection["RelayState"]));

        resp.Deserialize(samlResponse);

    }
    catch (Exception ex)
    {
        //TODO LOG
    }

    ViewData["SAMLResponse"] = resp;
    ViewData["RelayState"] = redirect;
    return View();
}
}



Demo:

https://github.com/congiuluc/spid-dotnet-sdk/tree/master/samples/ASPNET_CORE_2_0/SPID_ASPNET_CORE_2_0_NoIdentity


Prerequisito: Per eseguire la demo di ASP.NET Core 2 è necessario installare la verione 2 di .NET Core da https://www.microsoft.com/net/download
E' possibile utilizzare una demo funzionante, basta scaricare da GitHub la cartella Developers.Italia.SPID.Test.AspNetCore2 che si trova sotto la directory Test, aprire la finestra di comando ed eseguire i seguenti comandi:

Developers.Italia.SPID.Test.AspNetCore2> dotnet build
Developers.Italia.SPID.Test.AspNetCore2> dotnet run

Una volta finito basterà andare all'indirizzo https://localhost:44355 sul browser e provare l'autenticazione tramite Poste.IT.

Username demo: test.attiva@poste.it
Password demo: Password01

N.B.:Il certificato è self signed quindi bisogna bypassare i controlli del browser se presenti.




Documenti Utili:


Di seguito sono presenti alcuni link tecnici Utili:

Regole Tecniche:

http://spid-regole-tecniche.readthedocs.io/en/latest/index.html

Raccolta Documenti:

https://github.com/congiuluc/spid-dotnet-sdk/tree/master/docs/AgID

Avvisi SPID:

http://www.agid.gov.it/agenda-digitale/infrastrutture-architetture/spid/avvisi