2014-10-09 107 views
4

我們使用谷歌聯繫人API與OAuth2用戶:谷歌聯繫人API - 無法刷新訪問令牌

credential = new GoogleCredential.Builder().setTransport(new NetHttpTransport()) 
     .setJsonFactory(new JacksonFactory()) 
     .setClientSecrets(OAuth2ClientId(), OAuth2ClientSecret()) 
     .addRefreshListener(new CredentialRefreshListener() {...}); 

myService = new ContactsService("My-App"); 
myService.setOAuth2Credentials(credential); 

而且相當經常收到「401未授權」的響應,該庫的GData無法處理。 WWW-Authenticate標題丟失時,AuthenticationException將拋出NPE。

Caused by: java.lang.NullPointerException: No authentication header information 
     at com.google.gdata.util.AuthenticationException.initFromAuthHeader(AuthenticationException.java:96) ~[gdata-core-1.0-1.47.1.jar:na] 
     at com.google.gdata.util.AuthenticationException.<init>(AuthenticationException.java:67) ~[gdata-core-1.0-1.47.1.jar:na] 
     at com.google.gdata.client.http.HttpGDataRequest.handleErrorResponse(HttpGDataRequest.java:608) ~[gdata-core-1.0-1.47.1.jar:na] 
     at com.google.gdata.client.http.GoogleGDataRequest.handleErrorResponse(GoogleGDataRequest.java:564) ~[gdata-core-1.0-1.47.1.jar:na] 
     at com.google.gdata.client.http.HttpGDataRequest.checkResponse(HttpGDataRequest.java:560) ~[gdata-core-1.0-1.47.1.jar:na] 
     at com.google.gdata.client.http.HttpGDataRequest.execute(HttpGDataRequest.java:538) ~[gdata-core-1.0-1.47.1.jar:na] 
     at com.google.gdata.client.http.GoogleGDataRequest.execute(GoogleGDataRequest.java:536) ~[gdata-core-1.0-1.47.1.jar:na] 
     at com.google.gdata.client.Service.getFeed(Service.java:1135) ~[gdata-core-1.0-1.47.1.jar:1.47.1] 
     at com.google.gdata.client.Service.getFeed(Service.java:1077) ~[gdata-core-1.0-1.47.1.jar:1.47.1] 
     at com.google.gdata.client.GoogleService.getFeed(GoogleService.java:676) ~[gdata-core-1.0-1.47.1.jar:1.47.1] 
     at com.google.gdata.client.Service.query(Service.java:1237) ~[gdata-core-1.0-1.47.1.jar:1.47.1] 
     at com.google.gdata.client.Service.query(Service.java:1178) ~[gdata-core-1.0-1.47.1.jar:1.47.1] 

我們設法添加了一個包裝器,該包裝器會在此NPE上嘗試令牌刷新。它有助於但後來還是有很多情況下,當清涼的失敗:

credential.refreshToken() == false 

當我們運行中我們看到,executeRefreshToken()是沒有例外執行的,而是返回tokenResponse==null調試refreshToken()。結果refreshToken()返回false並沒有理由被傳遞給聽衆

try { 
    TokenResponse tokenResponse = executeRefreshToken(); 
    if (tokenResponse != null) { 
     setFromTokenResponse(tokenResponse); 
     for (CredentialRefreshListener refreshListener : refreshListeners) { 
     refreshListener.onTokenResponse(this, tokenResponse); 
     } 
     return true; 
    } 
    } catch (TokenResponseException e) { 
    boolean statusCode4xx = 400 <= e.getStatusCode() && e.getStatusCode() < 500; 
    // check if it is a normal error response 
    if (e.getDetails() != null && statusCode4xx) { 
     // We were unable to get a new access token (e.g. it may have been revoked), we must now 
     // indicate that our current token is invalid. 
     setAccessToken(null); 
     setExpiresInSeconds(null); 
    } 
    for (CredentialRefreshListener refreshListener : refreshListeners) { 
     refreshListener.onTokenErrorResponse(this, e.getDetails()); 
    } 
    if (statusCode4xx) { 
     throw e; 
    } 
    } 
    return false; 

我們的令牌始終是多個範圍:https://www.googleapis.com/auth/userinfo.email https://www.google.com/m8/feeds https://www.googleapis.com/auth/calendar https://mail.google.com/ https://www.googleapis.com/auth/tasks

+0

澄清,有時刷新工程,但有時它不?一旦刷新停止工作,它是否再次工作? AKA,這是暫時的還是永久的? – 2014-10-13 21:02:30

+0

好的,我們一直在嘗試更多。聯繫人與日曆和任務的行爲似乎有點不同。它看起來像日曆和任務憑證。refreshToken()可能會失敗,沒有理由,但如果你等待,再試一次,它可能實際上刷新令牌。對於聯繫人來說,它是NPE「沒有驗證頭信息」,但是如果在某些情況下再次嘗試,它最終會刷新令牌,而在其他情況下它總是失敗。 – Alexey 2014-10-14 21:48:25

+0

我正在複製問題。我當然看到NPE被拋出,但仍在努力使刷新失敗。 – 2014-10-16 15:07:21

回答

7

目前在Contacts API,其中某些HTTP User-Agent字符串,導致錯誤401響應返回爲HTML頁面而不是XML響應,並且缺少AuthenticationException類依賴的標頭WWW-AuthenticateGContacts-Java是這些特殊用戶代理字符串之一。一種解決方法是創建之後更改客戶端的用戶代理:

ContactsService service = new ContactsService(applicationName); 
service.getRequestFactory().setHeader("User-Agent", applicationName); 

這應該消除NPE,並允許客戶端庫自動檢測過期的令牌,並自動刷新它們。

+0

謝謝埃裏克。我會試一試。並且會爲Gmail令牌問題提出另一個問題。 – Alexey 2014-10-21 23:19:03

+0

Eric,它好像修復了聯繫人API(GData)的問題,但現在我也看到我們得到了這些新的錯誤: 的GData insufficientPermissions 沒有足夠的權限 任何想法,爲什麼?它是不是自動處理的過期令牌的另一個標誌? – Alexey 2014-10-27 06:14:56

+1

新錯誤==新堆棧溢出問題:) – 2014-10-27 13:44:46