26
Gen

JSON WEB TOKEN: un nuovo modo per autenticare le nostre sessioni in modo sicuro e scalabile

Json Web Token (JWT) è uno standard, abbastanza recente, uscito all’inizio del 2015 che  consente al server di  scrivere in un messaggio (payload) chi è l’utente loggato (e altre info di contorno), incapsulare questo messaggio all’interno di un token e darlo al client che lo utilizzerà da ora in poi per le successive chiamate al server, informandolo così di chi sta effettuando la chiamata. Questo consentirà al server di avere già le informazioni di autenticazione direttamente nel token stesso,  evitando così  dover passare dal database o di usare le sessioni per memorizzare le informazioni sull’autenticazione.

PERCHE’ USARE JWT? Facciamo un passo indietro:

Quando facciamo una login, siamo abituati a creare una sessione tra il server e il client e a memorizzare user_id all’interno della sessione, al fine di recuperare le informazioni di autenticazione nelle successive chiamate. Qui già sorge un piccolo problema: cosa succede se utilizziamo più server per bilanciare il carico del nostro sito? Se abbiamo creato la sessione quando eravamo sul server A e successivamente il bilanciatore di risorse ci porta sul server B la sessione sul server A che aveva i nostri dati di autenticazione  la perdiamo (in realtà per avere sessioni condivise su più server  le sessioni non si memorizzano più localmente ma si tendono a memorizzarle all’interno di uno spazio condiviso…su un database no-sql ad esempio).
Se invece stiamo  progettando un sistema api vorremmo utilizzare un token per far riferimento a una particolare sessione di autenticazione.  Quindi quando viene effettuata una chiamata all’api login, effettuo lato server un autenticazione, creo il  token, lo memorizzo nel database associandolo ad utente (magari con un timestamp di scadenza) e lo restituisco al client. Il client passerà questo token nelle successive chiamate, il server accede al db e verifica a quale utente è associato quel token. OK già va un po’ meglio…in realtà è peggio…stiamo creando un collo di bottiglia tra i vari server e il DB  poichè ad ogni richiesta api partirà una query al database per capire a quale utente è associato quel token, oltre che a creare un problema di sicurezza (il database potrebbe essere attaccato da qualche utente malintenzionato e recuperare tutti i nostri token di sessione)

Ma ecco così che entra in gioco Json Web Token.
L’idea che c’è alla base è che dopo l’autenticazione, il server prepara un token all’interno del quale racchiude un payload in cui viene dichiarato in maniera esplicita chi è l’utente loggato. Dentro il token, oltre il payload viene inserita la firma dal server(costituto dal payload stesso criptato con la sua chiave segreta in codifica hash 256). Il client riceve il token e se vuole sarà libero di leggere il payload contenuto ma non potrà modificarlo poichè se lo facesse il token sarà invalidato dal server. Il client dovrà comunicare al server il token ricevuto per tutte le successive chiamate in cui è richiesta l’autenticazione. Il server riceverà il token ed estrapolerà il payload  ma prima si assicurerà che il token sia stato firmato e autentificato con la sua chiave privata. Poichè il token contiene il payload con tutte le informazioni necessarie all’autenticazione (es. iduser), il server potrà evitare di passare ogni volta dal database per verificare a quale utente corrisponde quel token (ottimo per la scalabilità).

 

Entriamo un po’ più nel pratico.

COME VIENE COSTRUITO IL Json Web Token?

Potete fare subito delle prove e vedere come viene costruito usando questo tool:
http://jwt.io/#debugger

Il token è costituito da 3 parti:

HEADER

header jwt

è un oggetto json in cui sono racchiuse le informazioni principali dell’algoritmo utilizzato per per preparare la firma criptata e includerla nel token stesso. L’oggetto json viene codificato usando la funzione encodebase64 e come prima parte del nostro token abbiamo questo:

eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9

PAYLOAD

Qui è contenuto l’oggetto json che contiene le informazioni relative alla “sessione di autenticazione” che vogliamo inglobare all’interno del token. Ad esempio con:

stiamo dicendo che l’utente loggato si chiama John Doe, il suo ruolo è amministratore e l’id è 1234567890! Come vedete le informazioni di autenticazione sono inglobate nel messaggio stesso.

Il payload viene anche esso codificato con la funzione encodebase64 ottenendo la seconda parte del nostro token:
eyJzdWIiOiIxMjM0NTY3ODkwIiwibmFtZSI6IkpvaG4gRG9lIiwiYWRtaW4iOnRydWV9
Notate bene che possiamo sempre decodificare un messaggio in base64 con  la funzione decodebase64.

SIGNATURE

Qui c’è la parte più interessante, ovvero la firma con cui il server certifica che questo messaggio è stato scritto da lui e che non è stato modificato da nessun altro.

La firma come potete vedere non è altro che il risultato di una funzione hash 256 che prende in input la codifica base64  dell’header concatenandola con un punto alla codifica base64 del payload, il tutto codificato con la nostra “chiave segreta” che solo il server conoscerà!

Il risultato finale è la concatenazione di queste 3 parti appena viste:

Il server quindi restituirà questo token al client. Il client dovrà comunicare al server il token ricevuto per tutte le successive chiamate in cui è richiesta l’autenticazione. Il server riceverà il token ed estrapolerà il payload (in cui sono contenute le informazioni sull’utente loggato e che non risulta cmq essere criptato) ma prima si assicurerà che il token sia stato firmato e autentificato con la sua chiave privata. Poichè il token contiene il payload con tutte le informazioni necessarie all’autenticazione (es. iduser), il server potrà evitare di passare ogni volta dal database per verificare a quale utente corrisponde quel token (ottimo per la scalabilità). Non so l’hai notato ma ho ricopiato la parte di su ma scommetto che ora rileggendola sarà sicuramente più chiara :)

IL TUTTO E’ ASSOLUTAMENTE SICURO?

Assolutamente si…c’è però da fare un piccolo appunto. Esistono delle librerie che vi aiutano a implementare questo standard (potete trovare l’elenco completo qui per il vostro linguaggio preferito http://jwt.io/#libraries-io). L’autore fa solo alcune piccole avvertenze di come alcune librerie hanno implementato male lo standard e possono sorgere problemi di sicurezza (maggiori info qui: https://auth0.com/blog/2015/03/31/critical-vulnerabilities-in-json-web-token-libraries/). Ad oggi comunque la maggior parte delle librerie hanno fixxato il problema che comunque riguarda solo  se, invece di usare una funzione di hashcode per firmare i nostri messaggi, utilizziamo un sistema a chiavi asincrone (che porta ulteriori vantaggi…ad esempio possiamo assicurarci che il messaggio sia stato effettivamente inviato dal server o ricevuto da un determinato client).

APPROFONDIMENTI E RIFERIMENTI

 

 

 

 

 

3
Ago

L’architettura RestFULL è considerata nociva

Oggi mi sono imbattuto in questo interessate articolo che spiega un po’ tutti i problemi attuali dell’architettura restfull, che fino ad oggi ho sempre sostenuto tenendo alta la bandiera.

Leggendo le motivazioni, mi sono però ritrovato perfettamente in alcuni problemi che ad oggi questa architettura soffre. Gli elenco brevemente (maggiori dettagli li trovate nell’articolo):

  • Non esiste un formato di compressione. Infatti, anche se il json può risultare comunque leggibile all’occhio umano , non sempre è necessario che i dati scambiati debbano avere questa particolare caratteristica. Dopo tutto quando lanciamo la nostra applicazione in produzione non ne abbiamo assolutamente la necessità. Passare da jSON ad XML sicuramente è stato un passo in avanti per snellire la struttura dei messaggi scambiati ma possiamo sicuramente ottimizzare meglio  questo passaggio comprimendo i dati in binario. Ad esempio si può pensare di utilizzare un servizio di messaggistica binario come Protocol Buffers offerto da Google.
  • Non esistono dei contratti/schema che stabiliscono come gestire i messaggi da inviare/ricevere. Esistono comunque strumenti di supporto che ci aiutano a definire le specifiche di utilizzo delle nostre api come swagger.io
  • Non esistono specifiche standard per definire la ricerca, l’ordinamento e l’impaginazione delle nostre api ma solo linee guide sul quale vengono fatte tante proposte discordanti fra loro.
  • I web services restfull  sono  CRUD-oriented e non business o transaction-oriented. Questo ci costringe a mappare i termini del nostro domini in semplici operazioni di creazione/aggiornamento/cancellazione. Questo è estremamente semplificativo e non sufficiente a rappresentare il nostro dominio applicativo.
  • Gli errori di logiche di business tipicamente dovrebbero essere codificate in errori http 4xx. Ma questi non sono stati creati per mappare errori di dominio. Quindi ci ritroviamo ogni volta a fantasticare sui giusti codici di errore che più riteniamo opportuni: record duplicato ? 409… email errata ? facciamo 400… ma cosa  succede se il cliente non ha il saldo sufficiente per acquistare un prodotto ?. Per raggirare questo problema lancio sempre un errore 400 e nella risposta inserisco maggiori dettagli sull’errore con una struttura dati realizzata ad hoc: field, message e  error code.

 

In sostanza, il problema principale dell’architettura RestFULL e che non ci sono standard ma solo linee guide spesso discordati tra loro e la mancanza di standard significa che tutti possono chiamare i propri webservices REST-FULL.

Ad ogni modo questo articolo non vuole bannare l’uso dell’architettura restfull ma solo lanciare qualche riflessione a cielo aperto e magari a valutare alternative quando ci troviamo in particolari contesti. Ad esempio se le perfomance di banda sono un requisito fondamentale optiamo per soluzioni che non portano a costi di compressione/decompressione oppure se quando inviamo un messaggio non c’è bisogno di attendere  la risposta potremmo pensare di adottare una soluzione di  broker di messaggi come rabbitmq.

25
Mag

GIT: Come non perdersi tra branches e commits

git workflow

Avete cominciato ad usare git e ormai siete diventati bravi nel fare i giocolieri con le commit (se così ancora non fosse vi consiglio questa ottima guida in italiano su git) ma nonostante tutto  nel vostro flusso di lavoro con git ancora qualcosa non va e vi state perdendo dei mille rami che avete creato senza un’ apparente motivo logico.

Insomma, notante che forse ci vuole un po’ di “metodologia” e non sapete effettivamente rispondere alle domande: quando creare un ramo ? quando cancellarlo ? come gestire i fix ? come gestire le features ? apro una ramo per ogni feature ? etc.

Bene, vi annuncio che esistono delle linee guide che suggeriscono come gestire il flusso di lavoro con git ormai abbastanza consolidate.

In particolare vi segnalo questo articolo che spiega in modo semplice e dettagliato come non perdervi tra i vostri rami e tra le vostre commit. Lettura assolutamente consigliata:

http://nvie.com/posts/a-successful-git-branching-model/

 

 

 

25
Mag

Top 100 Best Software Engineering Books

Se siete in cerca del prossimo libro da leggere, ho trovato in rete questa meravigliosa “Top 100 Best Software Engineering Books”. Tutto quanto focalizzato nell’area “Software Engineering Body of Knowledge“. Nel doc c’è anche scritto come l’autore ha scelto i criteri per selezionare questa lista.

LINK DEL DOC -> Top-100-Best-Software-Engineering-Books-Ever

14
Apr

CHEPIZZA: un nuovo modo di ordinare la tua pizza a domicilio

 
logo chepizza
Da diversi anni che ormai porto avanti un mio  piccolo sogno nel cassetto: CHEPIZZA   http://www.chepizza.net 

Spero che quest’anno sia la volta buona di riuscire a lanciarlo sul mercato :)

Ormai è tutto pronto

21
Dic

Swipe Story: MUOVITI NELLA STORIA, APPROFONDISCI, GIOCA E SORRIDI

Durante in questo ultimo periodo, insieme all’azienda AI2.it, mi sono occupato di sviluppare un’applicazione mobile (con Unity3D, un famoso game-engine), chiamata Swipe Story che attraverso giochi, immagini e racconti multimediali, permette di offre  un’esperienza  più completa e coinvolgente nel raccontare una storia.

In realtà, Swipe Story, non è semplicemente un app ma piuttosto un ecosistema fatto di  giochi, racconti multimediali e meccanismi interattivi che possono essere  modellati e composti da un editore, da un autore o da un direttore di museo  per creare storie. Tutto questo a basso costo, poichè il sistema è ingegnerizzato e automatizzato al fine di consentire a chiunque di utilizzare questa tecnologia senza essere degli esperti informatici.

Se vi ho incuriosito abbastanza e volete saperne di più potete questo godervi questo video di presentazione di alcune storie realizzate: una storia per il museo Santa Scolastica, una storia di natale e ancora una storia disegnata da un bambino di 5 anni).

Infinte, potete trovare alcune di queste storie scaricabili su www.swipe-story.com

 

20
Dic

Ridimensiona le APP icons e i splashscreen per tutti i formati richiesti (android e ios)

Vi segnalo questi due interessanti tool  che  partendo da un icona e da uno splashscreen  vi consente di generare tutti i formati richiesti per un progetto cordova (attualmente lavora con iOS e ANDROID)

CORDOVA ICON: https://github.com/AlexDisler/cordova-icon

CORDOVA SPLASH: https://github.com/AlexDisler/cordova-splash

Interessante alternativa che può essere anche non utilizzato con cordova:

https://github.com/danielpovlsen/ios-icons-launch-images-generator

 

20
Dic

Quanto sei disposto ad investire?

Riflessione buttate li: Quando discuti di un progetto con un committente, puoi stare li ore, giorni e mesi (si fa per dire) per poi scoprire che alla fine il tuo preventivo viene rifiutato. Spesso non si conosco le cause ed importante capire il perché.

Per piccoli/medi progetti coordinati da committenti che non hanno mai masticato nulla di tecnologie, l’unico fattore di valutazione è il “prezzo”. La cosa diventa ancora più evidente quando ti capita di sentirsi chiedere “Ho bisogno di un preventivo entro 2 giorni”. Ma il punto che noi non siamo un’agenzia di assicurazioni, dove vince chi fa il prezzo più basso su pacchetti già belli preconfezionati. Perchè noi non vendiamo appunto “Pacchetti preconfezionati”. Il progetto va discusso, analizzato e vanno definiti sopratutto gli obiettivi che si vogliono raggiungere. Un’attività sicuramente che non può essere fatta in 2 giorni, tra l’altro a titolo gratuito (rischi del mestiere).

Ad ogni modo per far fronte a tutto questo il cliente va un po’ “coccolato/addestrato”, soprattuto per chi oggi cerca di avventurarsi in questo settore. Ed è sopratutto importante secondo me fargli capire quanto noi valiamo, quali sono i progetti su cui abbiamo già lavorato e qual è il nostro valore.

Dall’altra parte, noi “forgiatori di materia virtuale”, per avere un’idea dell’entità del progetto e capire se è il caso di investire del tempo per analizzare meglio il dominio, spesso cadiamo nella tentazione di porre la domanda tipica “Qual è il budget a disposizione ?”. Il problema che questa domanda è un po’ contorta proprio perchè il nostro committente molto probabilmente non ha idea di quali sono le figure necessarie, le attività da svolgere e il tempo da impiegare (e sicuramente non lo sappiamo noi visto che il dominio su cui lavorare non è ancora ben definito).

Ma se si prova a riformulare la domanda così “Quanto sei disposto ad investire!?” . Suona diversamente. Se si vuole realizzare un progetto, puoi realizzarlo e ampliarlo all’infinito. Tecnicamente puoi aggiungere infinite features. In più si possono applicare maggiori sforzi nell’analisi della user experience, curare maggioramente la grafica o ancora creare un sistemato più modellabile, più ingegnerizzabile, più volubile, più scalabile. Insomma si possono applicare strategie differenti e/o coinvolgere più esperti. Tutto questo dipendente da quanto sei disposto ad investire.

Tra l’altro possiamo dire che l’investimento porta a ricavi. Maggiore l’investimento maggiore saranno potenzialmente i ricavi ma maggiore saranno anche i rischi. Ecco perché se parli di investimento sei più portato a ponderare la giusta cifra.

Budget/investimento parole concettualmente molto simili ma che portano con se un suono differente.

10
Set

STATE DESIGN PATTERN: come evitare troppi if condizionati

Spesso ci troviamo a costruire una classe che cambia il suo comportamento in base a una combinazione di valori di certe variabili. In genere quindi costruiamo la logica attraverso dei semplici if o switch abbastanza rudimentali. Nella nostra classe siamo così spinti a introdurre un sacco di logica condizionale, che però si traduce in un risultato poco comprensibile e difficilmente manuntenibile.

Per affrontare in modo efficiente questo problema, i GoF (riferito ai 4 autori del del libro Design Patterns: Elements of Reusable Object-Oriented Softwaresuggeriscono l’uso del design patter a stati: consente ad un oggetto di modificare il suo comportamento quando il suo stato interno cambia.  

Cerchiamo subito di entrare nel dettaglio con un esempio di riferimento.

Supponiamo di avere un orologio che possiede due pulsanti: MODE E CHANGE (queste saranno le nostre azioni). Il tasto MODE permetterà di cambiare lo stato del nostro orologio in :

  • VISUALIZZAZIONE NORMALE
  • MODICHE DELLE ORE
  • MODIFICA DEI MINUTI

Quando premiamo il tasto CHANGE vogliamo che il nostro OROLOGIO subisca un comportamento diverso in base allo stato in cui si trova:

  • STATO “VISUALIZZAZIONE NORMALE -> AZIONE CHANGE -> SI ACCENDE LA LUCE
  • STATO “MODIFICHE DELLE ORE” -> AZIONE CHANGE -> INCREMENTO DI +1 L’ORA
  • STATO “MODIFICA DEI MINUTI” -> AZIONE CHANGE -> INCREMENTO DI +1 I MINUTI

Quindi il comportamento associato all’azione CHANGE cambia in baso allo stato in cui l’orologio si trova.

Se dovessi ragionare attraverso un insieme di condizioni logiche mi troverei a scrivere qualcosa di questo tipo:

function pressButtonChange(){
  if(clockstate == NORMAL_DISPLAY)
    activeLightScreen();
  else if(clockstate ==UPDATING_HOURS)
    hours++;
  else if(clockstate ==UPDATING_MINUTES)
    minutes++;
}

Come già detto il problema di questo codice è che si rende difficile la manutenzione, perchè la creazione di nuovi stati comporta la modifica di tutte le operazioni. Inoltre non si tiene una visione globale del codice, in modo da capire come agisce l’oggetto (l’orologio in questo caso), a seconda dello stato in cui si trova.

Vediamo quindi come poter implementare un’automa a stati finiti tramite il Pattern State.

Struttura del Pattern

gofState

Questo diagramma di classi rappresenta come è strutturato il pattern state:

  • Context
    • un oggetto che eseguirà determinazione operazioni quando si troverà in un particolare stato. In sostanza è l’oggetto reale a cui si potrà accedere dal client. Possederà un riferimento allo stato corrente.
  • State:
    • Questa è un’interfaccia o una classe astratta che definisce il comportamento comune associato a tutti i possibili stati
  • ConcreteState
    • Ogni stato viene rappresentata con una classe concreta. Rappresenta quindi  uno stato del Contesto e implementa l’interfaccia/classe astratta State. Ogni ConcreteState condivide uno stesso Context e quindi avrà un suo specifico riferimento in modo da poter poi cambiare lo stato a lui associato dopo che determinate operazioni sono state eseguite.

Applichiamo il pattern al nostro esempio

esempio design pattern state2

 

Vi lascio il codice di ogni classe. Per maggiori approfondimenti date uno sguardo ai riferimenti in calce.

public class Clock{
   private ClockState clockState;
   public int hr, min;
   public Clock() {
      clockState = new NormalDisplayState( this );
   }
   public void setState( ClockState cs ) {
      clockState = cs;
   }
   public void modeButton() {
      clockState.modeButton();
   }
   public void changeButton() {
    clockState.changeButton();
   }
   public void showTime() {
   System.out.println( "Current time is Hr : " + hr + " Min: "+ min );
   }
}
public abstract class ClockState {
  protected Clock clock ;
  public ClockState(Clock clock) {
    this.clock = clock;
  }
  public abstract void modeButton();
  public abstract void changeButton();
}
public class NormalDisplayState extends ClockState {
   public NormalDisplayState(Clock clock) {
     super( clock );
   }

   public void modeButton() {
      clock.setState( new UpdatingHrState( clock ) );
   }

   public void changeButton() {
     System.out.print( "LIGHT ON: " );
     clock.showTime();
   }
}
public class UpdatingHrState extends ClockState {
   public UpdatingHrState(Clock clock) {
     super( clock );
   }
   public void modeButton() {
     clock.setState( new UpdatingMinState( clock ) );
   }
   public void changeButton() {
     clock.hr++;
     if(clock.hr == 24)
        clock.hr = 0;
     clock.showTime();
   }
}
public class UpdatingMinState extends ClockState {
   public UpdatingMinState(Clock clock) {
     super( clock );
   }
   public void modeButton() {
     clock.setState( new NormalDisplayState( clock ) );
   }
    public void changeButton() {
      clock.min++;
      if(clock.min == 60)
         clock.min = 0;
      clock.showTime();
    }
}

 

CONCLUSIONI

Grazie al state design patter possiamo modellare il comportamento del nostro oggetto  in modo altamente manuntenibile. Ogni stato quindi rappresenta un insieme di condizioni (ovvero un insieme di valori di certe variabili che si possono verificare in un dato istante). Ogni stato cambia quindi il comportamento dell’oggetto quando questo si verifica.

Possiamo così avere una visione globale di come il nostro oggetto si comporta a seconda degli stati in cui si trova e possiamo aggiungere nuovi stati o cambiare il passaggio di uno stato all’altro senza dover necessariamente modificare la logica racchiusa negli altri stati.

 

RIFERIMENTI:

14
Apr

Sencha Touch 2: Sviluppare applicazioni mobile multipiattaforma

il “Club degli Sviluppatori” ha ormai raggiunto la tenera età di 1 anno. Per chi non conosce il club, siamo un gruppo di persone di Bari che si pongono l’obiettivo di  creare una rete di professionisti nel campo dello sviluppo del software.

I principi su cui si fonda questo gruppo sono semplici e di forte ispirazione ai principi dell’ Extreme Programming:
1. Confronto
2. scambio di Conoscenze
3. Coraggio
4. Chiarezza

Per tenere attivo il gruppo, ogni mese, un membro  propone un talk da tenere al prossimo incontro. In caso ci sono più proposte, parte il sondaggio e si vota all’interno del gruppo di linkedin.

Questa volta è toccato a me e ho preparato un talk su Sencha Touch: un framework per lo sviluppo di applicazioni mobile multipiattaforma ad alte prestazioni. In questo articolo vi farà un   riassunto degli argomenti che ho trattato e vi allegherò in vari punti le slide.

Read more