Uno dei diversi aspetti che girano attorno al tema Autenticazione nelle SPA è quello relativo alla gestione del Page Reload, ovvero mantenere viva la “sessione autenticata”, anche a seguito di un reload della pagina. Un breve cenno su come è stata gestita l’autenticazione. Questi gli step:

 

  1. Servizio angular di autenticazione chiamato dalle varie form di login (#1)
  2. il metodo login chiama un servizio API con accesso NON autenticato che verifica Username/Password. Per gestire i temi di sicurezza sarebbe preferibile utilizzare un protocollo HTTPS. (#2)
  3. Se i dati passano il controllo il servizio restituisce un token criptato, che contiene informazioni sull’account e sul periodo di validata del token stesso (#3)
  4. il token viene salvato nella localStorage (#4)
  5. nella callback della login viene chiamato un servizio API con accesso autenticato per recuperare/completare le informazioni sull’utente (#5)
  6. la chiamata (in realtà ogni chiamata) passa attraverso un interceptor che setta l’header per la gestione della chiamata autenticata, se presente il token di autenticazione (#6)
  7. il servizio API, se il token è valido, restituisce i dati richiesti, altrimenti restituisce una risposta 401 (risorsa Non Autorizzata) ed il token viene rimosso dalla localStorage (#7)
  8. se la richiesta dà esito ok, i dati dell’utente sono recuperati e si aggiorna l’oggetto “user” del servizio di autenticazione, che è controllato nell’applicazione ovunque serva gestire logiche legate alla sessione autenticata (#8)

 

Se si fa un reload della pagina (o si chiude il browser e lo si riapre dopo qualche giorno sull’applicazione), in fase di inizializzazione del servizio di autenticazione si ricerca la presenza del token di autenticazione e, se presente, si chiama il servizio per il recupero delle informazioni dell’utente, ricollegandosi al punto 6 dell’elenco precedente. Un estratto saliente del servizio è questa:

.factory('AuthService', [
    '...',
    function (...) {
        //-------- private methods -------
        var _getUserInfo = function () {
            _authService.getUserInfo().then(
                function (successData) {
                    _authService.user = successData;
                },
                function (errorData) {
                    // do something...
                })
        }
        var _authService = {
            //-------- public properties-------
            user: ...,
            //-------- public methods-------
            getUserInfo: function () {
                DiscUtil.validateInput('UserService.userInfo', {}, arguments);
                // create deferring result
                var deferred = $q.defer();
                // Retrieve Async data CurrentUser        
                $http.get(DisciturSettings.apiUrl + 'Account/UserInfo')
                    .success(function (result, status) {...})
                    .error(function (error, status) {...});
                return deferred.promise;
            }
        }

        //-------- Singleton Initialization -------
        // get security token from local storage
        var _token = localStorage.getItem(DisciturSettings.authToken);
        if (_token) {
            _getUserInfo();
        }

        return _authService;
    }
])

Il codice completo è su github: https://github.com/williamverdolini/discitur-web/blob/sprint3/app/modules/user/UserService.js

La gestione è lineare e chiara dal mio punto di vista. L’unico aspetto che non sono riuscito a chiarirmi in rete è quello relativo alla gestione delle callback del servizio $http del core angular. La cosa che ho riscontrato è che sebbene il servizio REST restituisca uno status 401, il servizio $http chiama la success callback…mentre mi sarei aspettato avesse richiamato la error callback. La documentazione ufficiale mi pare mi dia ragione…ma non ho trovato grossi riscontri a questa segnalazione in rete…qualcuno mi può illuminare?

Update

Il problema delle callback stava diventando sempre più frequente ed ho quindi dovuto affrontarlo interrompendo il resto. Ho fatto molte ricerche per verificare se altri avessero avuto problemi simili e la prima tappa da fare in questo genere di problemi è Stackoverflow.

Sono stato doppiamente sfortunato, perchè ho sì trovato un post che esprimeva il mio stesso identico problema, peccato che le soluzioni proposte non c’entravano niente con la mia…effetto? Quasi una settimana di approfondimenti (“inutili”) sul funzionamento di IIS, dello standard HTTP, di .Net WebApi.

Il problema era sull’uso sbagliato che facevo in un intercpetor Angular.js.

Le tecniche di Problem Solving meriterebbero un articolo a parte (o forse libri…), ma la cosa che ho imparato da quest’esperienza è quella di rimanere lucidi e critici su cosa sta realmente avvenendo nel sistema senza lasciarsi distrarre (troppo) da post o forum. Non è facile…soprattutto per uno “Stackoverflow-addicted” come me.

Aprire e debuggare Angular.js è abbastanza formativo, ma fa venire il mal di mare…perciò ho aggiunto il mio piccolo contributo alla comunità di Stackoverflow.

Comments