Integrazione SPID: Come non rimanere incastrati.

Michael Disaro'
Nov 2 · 7 min read
Identità Digitale
Identità Digitale

SPID è il Servizio Pubblico di Identità Digitale offerto dallo stato italiano quando nel 2012, durante il governo Monti, ha deciso di darsi una “svecchiata” creando l’AgID (Agenzia per l’Italia Digitale) ed incaricandola di assicurare il coordinamento informatico dell’amministrazione statale.

Ma bando alle ciance, se siete qui è perché sapete bene cos’è lo SPID e dovete integrarlo nella vostra piattaforma sfruttando uno degli SDK creati dai “Developers Italia” disponibili su Github, e vi siete accorti che dovrete fare svariate ore di controlli incrociati dovuti a mancanza di documentazione per essere operativi.

Quindi lo scopo di questo post è fornirvi un Vademecum astratto dalla tecnologia per non rimanere intrappolati nel giro di link tra un sdk e l’altro.

CONCETTI

Service Provider (abbreviato SP): Siete voi! È il termine usato per identificare la vostra piattaforma.

Identity Provider (abbreviato IDP): È la piattaforma su cui gli utenti faranno la login e che vi passerà i dati dell’utente. Ad esempio: Poste, Sielte, RegisterIt…

Metadata: È un file XML che descrive quali sono gli endpoint da chiamare e quali sono i dati richiesti/disponibili. Avrete a che fare con 2 metadata uno vostro da creare a mano, firmare (usando xmlsectool) ed esporre pubblicamente nella wwwroot (gli IDP lo controlleranno), ed uno fornito dagli identity provider in cui troverete i loro endpoint a cui mandare la richiesta post (molti framework lo fanno ormai da soli ma è bene saperlo).

Certificato per Firma: È un certificato che creerete voi per eseguire la firma con xmlsectool del vostro “metadata” e della vostra “AuthnRequest” che inviere all’IDP via post.

Certificato SSL IDP: È il certificato SSL dell’identity provider. Alcuni SDK sfruttano canali di comunicazione che lo controllano e molto probabilmente dovrete inserire questo certificato come Trusted Root nel vostro sistema, pena il fallimento dell’handshake quando invierete la richiesta post. Una soluzione potrebbe essere di accettare qualsiasi certificato, ma vi esporreste ad un Man In The Middle attack.

SAML 2.0: È il protocollo di Single Sign On (SSO) usato dal sistema SPID. Se doveste trovare problemi tecnici potreste trovare una risposta nelle wiki o nei forum che parlano di SAML2 e/o di WSO2 che è la piattaforma su cui si basa il test env locale del punto successivo, e per l’appunto è SAML 2.0 compliant. Dimenticatevi OAuth2 perché potreste esserne fuorviati.

Test ENV 2: È l’ambiente di test, ne avete uno scaricabile per i test locali ed uno online per i test su ambiente demo. L’ambiente locale che dovete considerare è il “spid-testenv2” reperibile qui https://github.com/italia/spid-testenv2, molto importante saperlo perché molti SDK non lo citano nemmeno confidando che voi incrociate le informazioni dalla documentazione che è prolissa per alcune parti inutili e poco approfondita per altre! Solo andare dritti a questo test env vi risparmia già un bel po’ di tempo.

Smart Button: È un repository in via di sviluppo il cui scopo sarebbe quello di fornire il bottone per la login con SPID senza che dobbiate farlo voi. Io l’ho usato come spunto per crearmi un partial con Razor (anche se logicamente il mio è molto diverso ho potuto prendere le immagini e gli stili), potrebbe tornare utile pure a voi. Reperibile qui https://github.com/italia/spid-sp-access-button.

INIZIAMO

Premesso che non vi spiegherò come programmare l’integrazione, visto che dipende dalla vostra tecnologia, cercherò di spiegarvi come gli elementi succitati interagiscono tra di loro in maniera astratta.

Il punto di inizio per lo SPID è su: https://developers.italia.it/it/spid/.

Seguendo le indicazioni in quella pagina troverete un SDK per la vostra tecnologia con la relativa documentazione tecnica.

Iniziate dando una letta alle regole tecniche: https://docs.italia.it/italia/spid/spid-regole-tecniche/it/stabile/.

Consiglio inoltre di dare una letta alla pagina Wikipedia di SAML2 che potrebbe farvi capire al volo come funziona questo protocollo.

I punti che potrebbero esservi nebulosi (a seconda di quale guida seguite) potrebbero essere i seguenti.

Come compilo il mio metadata? C’è un generatore?

Sembra ci fosse un generatore, ho passato delle ore a cercarlo non tanto per creare il file quanto per essere sicuro il file generato fosse valido, ma alla fine ho preferito prenderne uno e adattarlo al mio caso.

Vi incollo qui la versione non firmata, così potete prendere spunto e firmarlo voi:

metadata.xml

Ovviamente dovrete cambiare diversi campie/o attributi come l’entityID e l’ID mettendo dati che vi identifichino come SP univoco. Su localhost non avrete problemi, ma il produzione sicuramente dovrete generare un GUID e sfruttare il vostro dominio per distinguervi.

ATTENZIONE: Serviranno tendenzialmente 3 metadata! Uno per sviluppo, uno per staging ed uno per produzione. L’entityID di produzione sarà molto probabilmente il vostro dominio.

Come firmo il metadata e le richieste?

Dovete generare un certificato X509 con openssl e usarlo per firmare il metadata con XmlSecTool. Su una macchina unix (mac o linux) o con WSL sotto Windows vi risulterà piuttosto semplice.

Assicuratevi di avere una versione di openssl che sia compatibile con Xmlsectool, io consiglio la 1.0.2g che ho testato personalmente. Usate il comando openssl version per saperlo ed in caso seguite il prossimo punto prima di questo e prima di imbattervi nell’errore segnalato.

Generate il certificato e esportatelo in formato binaro proteggendolo con password con i comandi:

openssl req -x509 -sha256 -days 365 -newkey rsa:2048 -keyout yourcert.key -out yourcert.crtopenssl pkcs12 -export -in yourcert.crt -inkey yourcert.key -out yourcert.pfx

Il primo comando vi chiederà una password per criptare la chiave e gli attributi del certificato (occhio alla durata -days 365, probabilmente la vorrete più lunga).

Il secondo comando vi chiedere la password per decryptare la chiave e vi chiederà una password per proteggere il certificato *.pfx in formato pkcs12 unico. Questo è importante per renderlo illeggibile per esempio al comando cat.

Per firmare il metadata scaricate Xmlsectool con il repository https://github.com/italia/spid-metadata-signer e seguite la doc. In linea di massima si tratta di lanciare un comando simile a questo (cambiano eventuali path di script, metadata e cert):

xmlsectool.sh --sign --referenceIdAttributeName ID --inFile "metadata.xml" --outFile "metadata-firmato.xml" --digest SHA-256 --signatureAlgorithm http://www.w3.org/2001/04/xmldsig-more#rsa-sha256 --key "yourcert.key" --keyPassword "yourkeypassword" --certificate "yourcert.crt

PS: Xmlsectool ha bisogno di JDK per funzionare quindi magari un sudo apt-get install default-jdk può essere utile.

Una volta firmato il metadata sarà simile a:

Signed metadata.xml

Xmlsectool mi da un errore “java.lang.arrayindexoutofboundsexception: index 1 out of bounds for length 1”, come lo risolvo?

Errore parecchio fetente da scoprire, fortunatamente un utente, Daniele Cherchi, ha scritto in un post nel forum di SPID che risulta questo errore a causa di una incompatibilità tra la versione di OpenSSL e quella di Xmlsectool: https://forum.italia.it/t/spid-metadata-signer/132. Ringraziamolo tutti.

Molto probabilmente avete una versione di OpenSSL 1.1.X o simile, quella più aggiornata. Questa crea dei certificati che purtroppo sono incompatibili per qualche motivo con il tool. Dovrete installare da sorgente la versione 1.0.2g per farli funzionare, e visto che è vecchia vi consiglio di farlo come “versione parallela” o su Virtual Machine.

Ecco la procedura per Ubuntu (io uso WSL su Windows):

sudo apt-get update
sudo apt-get install build-essential checkinstall zlib1g-dev -y
mkdir ossltmp && cd ossltmp
wget https://www.openssl.org/source/old/1.0.2/openssl-1.0.2g.tar.gz
tar -xvzf openssl-1.0.2g.tar.gz
cd openssl-1.0.2g
./config --prefix=/usr/local/ssl --openssldir=/usr/local/ssl shared zlib
make
make test
make install

Questo dovrebbe essere sufficiente per il nostro scopo, l’openssl della macchina sta in /usr/bin/openssl (versione 1.1.x) mentre la versione vecchia sta in /usr/local/ssl/bin/openssl (versione 1.0.2g), potete approfondire al link https://www.howtoforge.com/tutorial/how-to-install-openssl-from-source-on-linux/ in caso di necessità.

Ora potete creare un certificato seguendo il punto precedente usando il comando /usr/local/ssl/bin/openssl che userà la versione 1.0.2g compatibile con xmlsectool.

Come faccio ad eseguire i test in locale?

I test in locale li fate sfruttando il test-env2 citato sopra.

Fate il clone del repo e installate Python 2.7+. Io ho svariate versioni nella WSL ma con la 2.7 riesco ad avviare il test-env senza problemi.

Vi consiglio di fare l’avvio MANUALE, è quello più semplice da configurare e in locale vi risparmierà tempo.

Leggete la doc alla voce “Configurazione” per capire come configurarlo, in linea di massima dovrete entrare nella cartella conf, creare un certificato ed una chiave per permettere al IDP di test di firmare le chiamate, creare un file config.yaml che setta le varie properties, una file users.json che contiene gli utenti che possono fare login nel IDP di test e mettere una copia del vostro metadata firmato (simulando così l’accreditamento).

Il file config.yaml sarà simile a questo:

coonfig.yaml

Il file users.json:

users.json

ATTENZIONE!!! Nel file users.json potete mettere i dati in che formato volete ma il realtà la risposta di SPID rispetterà strettamente un formato prestabilito che potete trovare qui: https://docs.italia.it/italia/spid/spid-regole-tecniche/it/stabile/attributi.html.

Come uso il test env online?

Il test env online lo trovate al link: https://idp.spid.gov.it/.

È un’installazione di quello di test, ottimo per fare le prove su ambienti di staging. L’unico problema è che non avrete la cartella conf da maneggiare.

Per accreditare il vostro metadata dovrete andare alla pagina: https://idp.spid.gov.it/admin/databasesprecord/.

Dovrete inserire il vostro metadata con copia e incolla, e fornire il vostro entityID che trovate in cima al vostro metadata in un attributo:

entityID=”https://yourhost/spid"

Dopo di che potrete controllare alla pagina https://idp.spid.gov.it/ di essere presenti. In quel momento potrete andare alla pagina https://idp.spid.gov.it/metadata e vedere quali endpoint configurare per le chiamate post ed inviare la AuthnRequest firmata.

La postback dell’IDP non riesce ad accedere alla session, come faccio?

La richiesta post fatta dal IDP nei confronti del vostro SP ovviamente è una post cross domain.

Molto probabilmente sfrutterete la session ed i cookie per tener traccia dei dati per validare la postback (identity provider scelto dall’utente, request id, ecc).

Per sicurezza se i cookie hanno policy samesite strict la postback non potrà tirarli su perché arrivata da altro dominio (https://www.owasp.org/index.php/SameSite).

Il che significa che non potrete né leggere i valori nei cookie, né nella eventuale session.

Per ora ho risolto mettendo la policy samesite dei cookie a lax ma non è che mi piaccia troppo come soluzione. Se me ne viene in mente una per mantenere lo strict ve la riporterò in aggiornamento, ma potrebbe essere qualcosa come farsi un helper per settare e tirare su cookie a piacimento tra le richieste.

CONCLUSIONI

Spero questo post risparmi almeno a voi svariate ore di ricerche su google, github e domande su Slack.

Dovreste aver abbastanza chiaro il giro generale e saper dove mettere mano per far funzionare l’integrazione.

Se avete altri dubbi contattatemi, se li ho affrontati e me ne son dimenticato integrerò questo post.

Per l’accreditazione di produzione seguite gli ultimi step presenti in questa pagina: https://www.spid.gov.it/come-diventare-fornitore-di-servizi-pubblici-e-privati-con-spid.

Più avanti renderò pubblico la mia Razor Library .NET Standard 2.0 e farò un altro post.

Ciao a tutti.

Appunti di uno smanettone

    Michael Disaro'

    Written by

    Classe 1983. Passioni: moto, musica, fotografia e tecnologia. https://michaelsoft.it

    Appunti di uno smanettone

    Appunti in italiano sul mondo della tecnologia e dello sviluppo software. Guide, consigli per gli acquisti, idee e pensieri da un nerd per dei nerd.

    Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
    Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
    Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade