L’autenticazione a due fattori, chiamata anche “strong authentication” o 2FA (Two-Factor Authentication), viene sempre più utilizzata in quanto permette di aumentare la sicurezza nell’effettuare determinate operazioni sensibili. In questo articolo vedremo come utilizzare la 2FA di google con le applicazioni scritte conLazarus/fpc.
Accenno sul funzionamento della 2FA di google
L’autenticazione a 2 fattori di Google si basa sull’utilizzo di una chiave condivisa.
Sinteticamente possiamo riassumere il processo come segue:
- l’applicazione che vuole utilizzare la 2FA di Google, deve generare una chiave segreta da abbinare all’utente; sarà compito dell’applicazione che stiamo scrivendo di memorizzare permanentemente questa chiave segreta da qualche parte: sarà necessaria nel processo di autenticazione.
- l’utente memorizza questa chiave segreta nell’app di autenticazione di Google Authenticator, la quale provvederà a generare un altro codice segreto – anche chiamato token – (di tipo numerico) ogni 30 secondi
- a parità di chiave segreta condivisa, anche la nostra applicazione potrà generare lo stesso codice segreto numerico nell’arco dei 30 secondi di validità; se i codici segreti numerici calcolati dalla nostra applicazione e da Google Authenticator coincidono, vuol dire che l’autenticazione è andata a buon fine
Il progetto di test
Il progetto di test è piuttosto semplice, lo trovate in allegato all’articolo. Descriverò brevemente i passi per costruirlo da zero:
- un
TEdit
con nome ed2faSeed dove verrà visualizzata la chiave segreta da condividere con l’app di Google Authenticator - un
TEdit
con nomeedToken2FA
dove inserire il codice che la Google Authenticator ci visualizza - un
TButton
“Genera seed 2FA” per generare la chiave segreta - un
TButton
“esegui validazione” per eseguire il test - una
TLabel
chiamatalbRisultato
per l’output del processo di autenticazione - la main unit deve avere in
uses
la unit onetimepass (fornita con i sorgenti fpc) che ci fornisce tutte le funzioni necessarie
Generare la chiave segreta
La generazione della chiave segreta è demandata alla funzione TOTPSharedSecret
contenuta nella unit onetimepass
Quindi il bottone “Genera seed 2FA” conterrà il seguente codice
procedure TForm1.Button2Click(Sender: TObject);
begin
ed2faSeed.Text := TOTPSharedSecret();
end;
Google Authenticator
Una volta generata la chiave segreta, dobbiamo inserirla nell’app di Android Google Authenticator.
Clicchiamo quindi sul bottone per aggiungere un nuovo account.
Nell’immagine sopra, il bottone “+” è evidenziato con una freccia rossa.
Si apre a questo punto un form per l’inserimento dei dati per la validazione.
I campi hanno il seguente significato:
- Account: descrizione mnemonica (non ha funzionalità specifiche)
- Key (o chiave): è il campo in cui inserire la chiave segreta condivisa
- Time based: gestisce l’algoritmo di calcolo del codice segreto in risposta (per ora non modificate questo valore).
Nel momento in cui avrete confermato il nuovo account, l’app genererà per voi ogni 30 secondi un codice segreto (o token) da fornire all’app che stiamo scrivendo (e che ha bisogno di effettuare la 2FA).
Prova su strada
A Questo punto non resta che provare il funzionamento dell’autenticazione.
Scriviamo il codice segreto (token) che stiamo visualizzando nell’app, nel TEdit
che abbiamo chiamato edToken2FA
e clicchiamo sul bottone “esegui validazione”. Verrà eseguito l’evento OnClick
del bottone che, come si puà vedere sotto è molto semplice: tutto è demandato alla funzione Validazione2FA.
procedure TForm1.Button1Click(Sender: Tobject);
var Seed2FA: string;
Token2FA: integer;
begin
Token2FA:=StrToInt(edToken2FA.Text);
Seed2FA:=ed2faSeed.Text;
if Validazione2FA(Seed2FA, Token2FA) then
lbRisutato.Caption:='VALIDAZIONE OK!'
else
lbRisutato.Caption:='ERRORE DI VALDAZIONE';
end;
A questo punto guardiamo il codice di Validazione2FA che, come si può notare è anche essa molto semplice e demanda il tutto alla funzione TOTPValidate
.
function TForm1.Validazione2FA(const aSeed: String; aCode: Integer): Boolean;
Var O : LongInt;
begin
Result:=TOTPValidate(aSeed,aCode,1,O);
end;
La funzione TOTPValidate
è contenuta nella unit onetimepass
ed è così dichiarata:
function TOTPValidate(const aSecret: AnsiString; const Token: LongInt; const WindowSize: LongInt; var Counter: LongInt): Boolean;
Dove:
aSecret
è la chiave segreta condivisa o seed (che abbiamo inserito in Google Authenticator)Token
è un intero che viene inserito manualmente dall’utente dopo averlo letto dall’appWindowSize
è la finestra temporale misurata in secondi, della deviazione massima consentitaCounter
(valore di output) è un contatore, che potrebbe essere utilizzato per implementare un un token basato su contatori (ma qui useremo quello basato sul tempo)
Conclusioni
Come abbiamo visto implementare una autenticazione 2FA con Lazarus / Free Pascal è un’operazione abbastanza banale. Questo grazie e soprattutto alla unit ontimepass
che ci viene fornita con l’ambiente di sviluppo.
Per chi non volesse aspettare, in fondo all’articolo trovate il progetto discusso in questo articolo.
Come sempre se dovessero esserci spunti per una discussione, il forum https://www.lazaruspascal.it/ è sempre a disposizione.
Buon lavoro a tutti.