2017-05-26 33 views
-2

我正在使用ember-simple-auth & ember-simple-auth-token在Ember上維護會話。我不想使用刷新令牌方法,而是想從每個服務請求的響應頭中接收新的jwt令牌。如何從ember-simple-auth會話的響應頭中更新JWT令牌

我每次收到服務器的響應時,如何通過更新會話中的jwt令牌來保持會話活動?

+0

我正在接收JWT令牌,作爲來自後端服務的每個響應頭的一部分。我們的想法是,在認證期間最初設置的到期時間爲30分鐘,然後在每次與退出交互時嘗試捕獲新令牌並使用適配器 - > handelResponse方法在會話中更新它。簡而言之,我所要做的只是滑動會話。 –

+0

我面臨的問題是Ember-simple-auth在session.data.authenticated中存儲了令牌和失效時間,在文檔中這被稱爲只讀。如果我不允許更新令牌,我怎麼能保持會話活着? –

回答

1

這可以完成,但需要延長ember-simple-authember-simple-auth-token。不建議使用您的方法,訪問令牌和刷新令牌絕對是首選方法。由於您的資源服務器不需要進行身份驗證,只需授權和驗證令牌,它的規模也會更好。它還增加了一些開銷,爲每個請求生成一個新的令牌。雖然我不建議這樣做當然,這裏是它如何可以做到:

正如你已經發現,你不能直接更新會話,但如果你深入到源代碼,你會發現,ember-simple-auth使用一個event來更新它。但是,如果您覆蓋/定製authenticator,此事件將僅適用。可能ember-simple-auth-tokenauthenticators/jwt.js。如果你看看他們的身份證明,你可以看到一個如何update the session的例子。

因此,我建議創建自己的定製JWT令牌認證器,它可以擴展ember-simple-auth-token的。它可能會添加一個方法來更新session或更好地處理包含新訪問令牌的原始請求標頭。

完成後,您可以選擇。您可以覆蓋自己的adapter並從那裏自己調用該函數,或者更好的選擇是覆蓋ember-simple-auth的mixin。

如果覆蓋ember-simple-authdata-adapter-mixin,這似乎是最好的起點:handleResponse。如果您覆蓋該功能,您應該可以訪問原始API響應,您可以從中調用您的更新會話功能。

正如你所看到的,這不是一個微不足道的變化。這絕對是與這些圖書館最初設計的目標背道而馳的,但如果你投入了大量的工作,這應該是可能的。

更新爲OP的評論
其實我之前實現這兩方面的要求:「1)有會話超時後預先配置的空閒時間2)允許某一組用戶代理在和開關的情況下。即時登錄用戶「。事實證明,使用刷新令牌模型實現起來其實很簡單。

要支持#1,刷新令牌過期應設置爲註銷前空閒時間的長度。例如如果刷新令牌設置爲在30分鐘內過期並且訪問令牌在5分鐘內過期。客戶端每隔5分鐘就會自動獲取新的訪問令牌(以及可選的刷新令牌),這是基於靈活性的。但是,如果用戶離開頁面超過30分鐘,則刷新令牌將過期,並且需要重新進行身份驗證。

對於#2,不幸的是,它確實需要一些重要的ember-simple-auth-token工作,但它相對容易,而且我已經實施了一些。基本上你創建了一個自定義的認證器,它有一個附加功能來交換和訪問具有更新的上下文/狀態的新的令牌。見下面我的實現:

ember-simple-auth-token重寫認證:

/** 
    Provides a public method to call to exchange an access token for an 
    updated access token with updated data encoded in it. This method 
    essentially asks the backend to update an access token with different 
    values. This is, at the moment, is only used to switch the company root 
    attribute in the token (AKA switch companies for admins). 

    @param {string} token - The valid access token 
    @param {object} [headers] - An optional object which can add additional 
    headers to the request 

    @param {object} additionalData - An object which contains the data which should be updated on the token. It should look something like this: 
    ``` 
    { 
     company_root_id: '<UUID of a valid company root>' 
    } 
    ``` 
    @return {Promise} A promise which is the request. It will either resolve 
    with the updated session data or reject with the error. 
    */ 
exchangeAccessToken(token, headers, additionalData) { 
    const data = this.makeRefreshData(token); 
    Ember.merge(data, additionalData); 

    return new Ember.RSVP.Promise((resolve, reject) => { 
     this.makeRequest(this.serverTokenRefreshEndpoint, data, headers).then(response => { 
      Ember.run(() => { 
       try { 
        const sessionData = this.handleAuthResponse(response); 

        this.trigger('sessionDataUpdated', sessionData); 
        resolve(sessionData); 
       } catch(error) { 
        reject(error); 
       } 
      }); 
     }, (xhr, status, error) => { 
      Ember.Logger.warn(`Access token could not be refreshed - server responded with ${error}.`); 
      reject(); 
     }); 
    }); 
} 

行動觸發代幣兌換:

switchCompany(companyId) { 
    let session = this.get('_session.session'); 

    if(!this.get('isAdministrator')) { 
     throw new Error('Logged in user is not an administrator, they cannot switch companies.'); 
    } 

    let token = session.get('authenticated.access_token'); 
    let appInstance = Ember.getOwner(this); 
    let authorizerName = session.get('authenticator'); 
    let authorizer = appInstance.lookup(authorizerName); 
    if(!authorizer) { 
     throw new Error(`Authorizer (${authorizerName}) does not exist`); 
    } 
    if(typeof authorizer.exchangeAccessToken !== 'function') { 
     throw new Error(`Authorizer (${authorizerName}) does not have an \`exchangeAccessToken\` method.`); 
    } 
    return authorizer.exchangeAccessToken(token, null, { 
     company_root_id: companyId 
    }); 
} 

後端會顯然需要擴展到接受刷新令牌附加參數端點,允許用戶切換角色,如果授權。

+0

嗨邁克爾, 謝謝你寶貴的建議。我對刷新令牌的想法基於兩個要求:1)在預先配置的空閒時間後會話超時。 2)允許特定的用戶集合進行代理並在運行中切換登錄用戶的上下文。正如你所建議的,我正在評估其他方法來完成這些任務,並且不必重寫ember-simple-auth的基本實現。如果這些方法失敗了,那麼將嘗試擴展身份驗證器和mixin作爲最後的手段。 –

+0

@PrajwalBoloor,我更新了我的答案,以展示如何使用刷新令牌模型完成您的需求。 –