2014-12-31 23 views
5

L'istruzione nel titolo è corretta? Sto basando la domanda sul lavoro svolto da Taiseer Joudeh (grazie per il vostro lavoro su questo argomento, btw) allo http://bitoftech.net/2014/07/16/enable-oauth-refresh-tokens-angularjs-app-using-asp-net-web-api-2-owin/.I token di aggiornamento in oauth2 non devono essere sostituiti quando si riceve un nuovo token di accesso

Se ho ben capito il comportamento di aggiornamento gettoni correttamente, quando un token di accesso scade, si dovrebbe chiamare l'endpoint segno del nostro server di autenticazione con qualcosa di simile

'grant_type=refresh_token&refresh_token=' + token 

e noi ci metteremo un nuovo token di accesso. Quella richiesta avrà un token di aggiornamento come parte del payload, ma il token di aggiornamento non dovrebbe essere lo stesso che abbiamo appena usato? O per lo meno, dovrebbe avere la stessa scadenza? Se no, allora davvero, la durata del refresh è infinita.

Ecco i test di frisby.js che mi aspetto di passare, ma utilizzando l'implementazione di Taiseer per Web Api 2, l'aspettativa finale non riesce. Riceviamo un nuovo token di aggiornamento con una nuova scadenza su quel token.

'use strict'; 

var frisby = require('frisby'); 
var config = require('../test-config.json'); 

var args = config[process.env.test || 'local']; 
var host = args.host, 
    clientId = args.clientId, 
    usr = args.user1, 
    pwd = args.password1; 

frisby.create('Try and fail to get a protected resource') 
    .get(host + '/api/test') 
    .expectStatus(401) 
    .expectHeaderContains('WWW-Authenticate', 'bearer') 
    .toss(); 

frisby.create('Log in and get a protected resource') 
    .post(host + '/token', { 
     grant_type: 'password', 
     username: usr, 
     password: pwd, 
     client_id: clientId 
    }) 
    .expectJSONTypes({ 
     access_token: String, 
     token_type: String, 
     expires_in: Number, 
     userName: String, 
     refresh_token: String, 
     'as:client_id': String, 
     '.issued': String, 
     '.expires': String 
    }) 
    .expectJSON({ 
     token_type: 'bearer', 
     userName: '[email protected]' 
    }) 
    .afterJSON(function (json) { 
     frisby.create('and now get protected resource with attached bearer token') 
      .get(host + '/api/test', { 
       headers: { 'Authorization': 'Bearer ' + json.access_token } 
      }) 
      .expectStatus(200) 
      .toss(); 
     frisby.create('and try to get a new access token with our refresh token') 
      .post(host + '/token', { 
       grant_type: 'refresh_token', 
       refresh_token: json.refresh_token, 
       client_id: clientId 
      }) 
      .afterJSON(function (json2) { 
       //we should receive a new access token 
       expect(json.access_token).not.toEqual(json2.access_token); 
       //but shouldn't the refresh token remain the same until *it* expires? 
       expect(json.refresh_token).toEqual(json2.refresh_token); 
      }) 
      .toss(); 
    }) 
    .toss(); 

risposta

5

Stai corretta al 100%, l'attuale implementazione di token di aggiornamento ha scorrevole di scadenza per il token di aggiornamento, perché con ogni uso per grant_type = refresh_token stiamo emissione di nuove token di accesso e aggiornare identificatore di token, e questo era perfetto per il mio caso perché voglio che l'utente sia loggato per sempre fintanto che sta usando l'applicazione, se non ha usato l'applicazione per un periodo maggiore della data di scadenza per il token di aggiornamento allora riceverà 401 quando prova a ottenere un nuovo token di accesso utilizzando il token di aggiornamento.

Per modificare questo comportamento è necessario emettere un identificatore di token di aggiornamento singolo e restituire lo stesso identificatore quando l'utente richiede un nuovo token di accesso utilizzando il token di aggiornamento. E puoi farlo personalizzando la logica di business in questo metodo e anche questo.

+1

Grazie, Taiseer. Questa roba non è facile, in particolare quando il framework Katana sta facendo tanto "magia" per noi. Probabilmente è ancora meglio che scriverci da soli. Ho spinto il mio lavoro in corso al mio repo - il fornitore di aggiornamento è qui: https://github.com/finleysg/stats-api/blob/master/StatsApi/Providers/RefreshTokenProvider.cs. Senza dubbio ancora ingenuo e scorretto, ma i miei test di frisby stanno passando. Ti preoccupi di Logout? Ho una semplice implementazione nel controller account che cancella tutti i token di aggiornamento per un utente sull'azione di logout. – Stuart

+0

@Taiseer Joudeh se l'utente non ha utilizzato l'applicazione per un periodo maggiore della data di scadenza per il token di aggiornamento, riceverà 401 quando tenta di ottenere un nuovo token di accesso utilizzando il token di aggiornamento. Per modificare questo comportamento è necessario emettere solo un identificatore di token di aggiornamento singolo e restituire lo stesso identificatore quando l'utente richiede un nuovo token di accesso utilizzando il token di aggiornamento. Come posso farlo? Voglio anche che l'utente abbia effettuato l'accesso per sempre. Puoi mostrare alcuni esempi per questo in sicurezza di primavera oauth2. – KJEjava48