Questo post è un pò speciale visto che non tratta direttamente con tecnologia Windows Phone 7, ma considerato che per lavoro ho dovuto implementare un meccanismo di autenticazione basato su un provider Open ID (Google), mi è sembrato giusto, in pieno spirito di condivisione, mettere a disposizione della community il risultato di un paio di serate di spippolamento di codice. Veniamo subito alla questione. Se noi abbiamo un sito ASP.NET (in questo caso con paradigma WIndows Form, ma la cosa si applica pari pari a MVC 2/3) a cui vogliamo fornire un meccanismo di autenticazione, siamo costretti a doverci preoccupare di COME può fare il client a passare le credenziali al server in maniera sicura. Questo è vero soprattutto nei casi in cui si sceglie una Forms Authentication ed il sito non si trova su una intranet. Siamo costretti spesso a utilizzare una comunicazione HTTPS. Questo però comporta una serie di problematiche, tra le quali la necessità di avere ( e manutenere) un certificato lato server e di 'costringere' i client a installare tale certificato sul proprio browser. Dal punto di vista del client inoltre, vi è anche la questione di doversi 'inventare' un account per la nostra applicazione con l'onere di annoverare l'ennesima coppia di username e password nella pletora di accounts già in possesso del nostro utente. La soluzione proviene da un protocollo che ormai si è consolidato da tempo che si chiama Open ID la cui community ha pubblicato le specifiche presso http://openid.net/.
Open ID
Visto che un provider vale l'altro (da un punto di vista del protocollo ovviamente), abbiamo scelto di usare Google come Open ID Provider a cui affidare il compito di autenticare i nostri utenti. Come funziona tutto ciò. Se andiamo sul sito di Google dove parla di OpenID troveremo una immagine abbastanza illuminante che riproponiamo qui sotto

1) l'utente decide di autenticarsial nostro sito.
2) Il punto 2 riguarda il caso in cui dessimo all'utente la possibilità di scegliere con quale Provider autenticarsi. Non è il nostro caso perchè abbiamo deciso di utilizzare solo Google (nulla ci vietava cmq. di dare la possibilità di scegliere Amazon, piuttosto che Yahoo o altri)
3) A questo punto è compito della nostra applicazione andare a cercare l'end-point, cioè l'indirizzo URI esatto, dove il provider è in attesa di ricevere delle richieste di autenticazione. E' la fase di discovery che si effettua facendo una richiesta ad un indirizzo ben preciso e
4) il Provider ci risponderà con un file XRDS (una grammatica abbastanza semplice) in cui vi è indicato l'end-point che l'applicazione web dovrà interpellare per chiedere l'aiuto necessario a autenticare l'utente
5) Appena estrapolato l'end-point, ritorneremo al client una risposta con la quale
6) provocheremo un redirect dell'utente stesso verso la pagina di autenticazione vera e propria di Google. In questa risposta (che vedremo successivamente nel dettaglio) indicheremo anche la pagina alla quale il client dovrà andare dopo l'eventuale successo nell'autenticazione.
7) L'utente inserisce i sui dati come account di Google e se tutto è ok
8) viene reindirizzato da Google alla pagina di cui al punto 6) corredando la Response di una serie di informazioni quali username, language e altre informazioni varie (claims)
In questo esempio non faremo utilizzo di OAuth, il quale è un protocollo per mezzo del quale l'utente, oltre ad autenticarsi con Oid, ha l'opportunità anche di indicare all'applicazione Web a quali eventuali informazioni o servizi aggiuntivi può accedere. Nel caso specifico l'utente potrebbe autorizzare la nostra applicazione ad accedere ai suoi Google Docs o i suoi Google Spreadsheet. Anche OAuth è un protocollo open ormai consolidato le cui specifiche possono essere trovate qui.
Let's start
Facciamo l'esempio di una semplice applicazione ASP.Net che fa utilizzo di Google come Provider di Autenticazione Open ID. Vogliamo naturalmente fare in modo che all'interno del proprio sito si continui comunque ad utilizzare un eventuale Membership Provider e un Role Provider di nostra scelta. L'unico assunto che facciamo è che ovviamente il nostro utente dovrà dirci quale è il suo account (username) con il quale accede a Google. A questo punto possiamo decidere di utilizzare quello come username dell'utente anche per il nostro sito e crearlo nel nostro repository agganciato al membership provider. corrispondente. Vediamo il nostro sito come è strutturato:

Come si vede abbiamo una parte pubblica contenente la pagina di Login più un'altra pagina per l'inserimento (nel nostro repository) di utenti dell'applicazione e una parte riservata contenuta nella directory 'Reserved' che proteggeremo dagli user non autenticati tramite una particolare configurazione del Web.config . Diamo un'occhiata al nostro web.config.

Prima cosa da sottolineare: usiamo ancora il modello di autenticazione asp.net basato su Forms Authentication. Indichiamo che la pagina di Login è Login.aspx e che il cookie di autenticazione sarà targato con il nome MySecureOIDWS. Indichiamo quale è il provider per la Membership che nel nostro caso è un SQL Membership provider, proprio come il Role provider. Entrambi questi ultimi puntano, tramite la stringa di connessione CredentialDB ad un Database compliant con il Membership e il Role Provider. Per chi non lo sapesse per creare un database coerente con le regole dei provider di autenticazione basta digitare il comando "aspnet_regsql" dal command prompt di Visual Studio e seguire il relativo Wizard. Il database creato è lievemente modificato aggiungendo una tabella. Vediamo come:

La tabella si chiama Tbl_OIDAssociation. Questa tabella ha 3 campi che indicano la mail (username) utilizzata dall'utente come account di google, l'ID univoco di Google restituito dopo il logon corrispondente all'utente con quella mail (username) ed infine l'ID corrispondente allo user dell'applicazione Web (ID_RelyingPartyUser) che è la chiave (UserId) della tabella aspnet_Membership. Il concetto è questo. Noi creiamo un utente nella tabella aspnet_Membership con username uguale alla mail che lo user utilizzerà per autenticarsi a Google. Quando l'utente si autenticherà a Google quest'ultimo ci restituirà un ID specifico per quell'utente e la mail con la quale ha fatto login e noi allora creeremo un record di associazione (appunto) che colleghi l'utente della applicazione web con l'utente Google. Infine vediamo come aggiungere i tag giusti per impedire l'accesso agli utenti non autenticati nella parte 'Reserved' e lasciare l'accesso a tutti nella parte pubblica:
