2011-09-17 27 views
23

Tôi đang cố gắng sử dụng API Google+ để truy cập thông tin cho người dùng được xác thực. Tôi đã sao chép một số mã từ một trong các mẫu, hoạt động tốt (dưới đây), tuy nhiên tôi gặp sự cố khi làm cho nó hoạt động theo cách tôi có thể sử dụng lại mã thông báo trên các lần khởi chạy ứng dụng.API Google+: Làm cách nào để tôi có thể sử dụng RefreshTokens để tránh yêu cầu quyền truy cập mỗi khi ứng dụng của tôi khởi chạy?

Tôi đã thử chụp thuộc tính "RefreshToken" và sử dụng provider.RefreshToken() (trong số những thứ khác) và luôn nhận được phản hồi 400 Bad Request.

Có ai biết cách thực hiện tác phẩm này hay không, hoặc biết nơi tôi có thể tìm thấy một số mẫu? Các Google Code site dường như không che :-(này

class Program 
{ 
    private const string Scope = "https://www.googleapis.com/auth/plus.me"; 

    static void Main(string[] args) 
    { 
     var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description); 
     provider.ClientIdentifier = "BLAH"; 
     provider.ClientSecret = "BLAH"; 
     var auth = new OAuth2Authenticator<NativeApplicationClient>(provider, GetAuthentication); 

     var plus = new PlusService(auth); 
     plus.Key = "BLAH"; 
     var me = plus.People.Get("me").Fetch(); 
     Console.WriteLine(me.DisplayName); 
    } 

    private static IAuthorizationState GetAuthentication(NativeApplicationClient arg) 
    { 
     // Get the auth URL: 
     IAuthorizationState state = new AuthorizationState(new[] { Scope }); 
     state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl); 
     Uri authUri = arg.RequestUserAuthorization(state); 

     // Request authorization from the user (by opening a browser window): 
     Process.Start(authUri.ToString()); 
     Console.Write(" Authorization Code: "); 
     string authCode = Console.ReadLine(); 
     Console.WriteLine(); 

     // Retrieve the access token by using the authorization code: 
     return arg.ProcessUserAuthorization(authCode, state); 
    } 
} 
+0

bạn có nhìn thấy các lỗi ngay cả khi mã thông báo làm mới được sử dụng trước ngày hết hạn? Nếu có, bạn có thể sử dụng cùng một mã thông báo làm mới nhiều lần không? –

+0

Tôi không thực sự biết làm thế nào tôi phải sử dụng nó - Tôi đã chỉ ngẫu nhiên lấy mã thông báo Refresh từ yêu cầu và sau đó sử dụng phương thức RefreshToken. Tôi thực sự không thể tìm thấy bất kỳ tài liệu nào về cách nó hoạt động, vì vậy có thể tôi đã sử dụng nó không chính xác. Đó là những gì tôi đang cố gắng tìm ra :-( –

+0

@ DannyTuppeny Bạn đã giải quyết điều này chưa? Nếu không, bạn đã xem câu trả lời của tôi chưa? Tôi đã gặp vấn đề tương tự như bạn, và không tìm thấy tài liệu tốt bằng cách googling, nhưng tôi – poplitea

Trả lời

20

Đây là một ví dụ. Đảm bảo rằng bạn thêm một cài đặt chuỗi có tên là RefreshToken và tham chiếu System.Security hoặc tìm cách khác để lưu trữ mã thông báo làm mới một cách an toàn.

private static byte[] aditionalEntropy = { 1, 2, 3, 4, 5 }; 

    private static IAuthorizationState GetAuthorization(NativeApplicationClient arg) 
    { 
     // Get the auth URL: 
     IAuthorizationState state = new AuthorizationState(new[] { PlusService.Scopes.PlusMe.GetStringValue() }); 
     state.Callback = new Uri(NativeApplicationClient.OutOfBandCallbackUrl); 

     string refreshToken = LoadRefreshToken(); 
     if (!String.IsNullOrWhiteSpace(refreshToken)) 
     { 
      state.RefreshToken = refreshToken; 

      if (arg.RefreshToken(state)) 
       return state; 
     } 

     Uri authUri = arg.RequestUserAuthorization(state); 

     // Request authorization from the user (by opening a browser window): 
     Process.Start(authUri.ToString()); 
     Console.Write(" Authorization Code: "); 
     string authCode = Console.ReadLine(); 
     Console.WriteLine(); 

     // Retrieve the access token by using the authorization code: 
     var result = arg.ProcessUserAuthorization(authCode, state); 

     StoreRefreshToken(state); 
     return result; 
    } 

    private static string LoadRefreshToken() 
    { 
     return Encoding.Unicode.GetString(ProtectedData.Unprotect(Convert.FromBase64String(Properties.Settings.Default.RefreshToken), aditionalEntropy, DataProtectionScope.CurrentUser)); 
    } 

    private static void StoreRefreshToken(IAuthorizationState state) 
    { 
     Properties.Settings.Default.RefreshToken = Convert.ToBase64String(ProtectedData.Protect(Encoding.Unicode.GetBytes(state.RefreshToken), aditionalEntropy, DataProtectionScope.CurrentUser)); 
     Properties.Settings.Default.Save(); 
    } 
+0

Cảm ơn, điều này đã giúp ích rất nhiều. Tôi cũng đã sử dụng lớp Google StoredStateClient từ ví dụ trong liên kết đó, vì vậy tôi có thể truy xuất thông tin người dùng với cùng một phản hồi "ủy quyền". https://developers.google.com/drive/credentials – IPValverde

11

Ý tưởng chung là như sau:

  1. Bạn chuyển hướng người dùng đến Authorization Endpoint của Google

  2. Bạn có được một. Mã ủy quyền ngắn hạn.

  3. Bạn ngay lập tức trao đổi Mã ủy quyền cho Mã thông báo truy cập tồn tại lâu dài bằng cách sử dụng Google Điểm cuối mã thông báo. Mã truy cập đi kèm với ngày hết hạn và Mã thông báo làm mới.

  4. Bạn yêu cầu API của Google bằng Mã thông báo truy cập.

Bạn có thể sử dụng lại Mã truy cập cho bao nhiêu yêu cầu tùy thích cho đến khi hết hạn. Sau đó, bạn có thể sử dụng Mã thông báo làm mới để yêu cầu Mã thông báo truy cập mới (đi kèm với ngày hết hạn mới và Mã thông báo làm mới mới).

Xem thêm:

+0

Xem http://stackoverflow.com/questions/ 7454930/google-api-how-can-i-use-refreshtokens-to-avoid-request-access-every-time-my/7489566 # 7489566 –

2

Các OAuth 2.0 đặc tả vẫn chưa kết thúc, và có một sự hiểu biết sơ triển khai đặc tả trên mạng qua các khách hàng khác nhau và các dịch vụ khiến các lỗi này xuất hiện. Có thể bạn đang làm mọi thứ đúng, nhưng phiên bản DotNetOpenAuth bạn đang sử dụng triển khai bản thảo OAuth 2.0 khác với Google hiện đang triển khai. Không một phần nào là "đúng", vì thông số kỹ thuật chưa được hoàn thành, nhưng nó làm cho khả năng tương thích của một cơn ác mộng.

Bạn có thể kiểm tra phiên bản DotNetOpenAuth bạn đang sử dụng là phiên bản mới nhất (trong trường hợp giúp, có thể), nhưng cuối cùng bạn có thể cần phải ngồi chặt cho đến khi các thông số được hoàn thành và mọi người thực hiện chúng một cách chính xác hoặc tự mình đọc tài liệu của Google (có thể mô tả phiên bản OAuth 2.0 của họ) và triển khai phiên bản cụ thể nhắm mục tiêu phiên bản nháp của họ.

2

Tôi khuyên bạn nên xem dự án "SampleHelper" trong giải pháp mẫu của Google.Ứng dụng khách API NET:

Tập tin này cho thấy cả hai làm thế nào để sử dụng Windows bảo vệ dữ liệu để lưu trữ một mã thông báo Refresh, và nó cũng cho thấy làm thế nào để sử dụng một máy chủ Loopback địa phương và kỹ thuật khác nhau để nắm bắt Mã truy cập thay vì để người dùng nhập mã theo cách thủ công.

Một trong những mẫu trong thư viện mà sử dụng phương pháp này cho phép có thể được tìm thấy dưới đây:

3

Tôi cũng đã có vấn đề với việc "ẩn" xác thực để làm việc (ví dụ mua xác thực bằng mã thông báo làm mới) và nhận phản hồi HTTP 400 Bad request bằng mã tương tự mã của OP. Tuy nhiên, Tôi đã làm việc với đường dây client.ClientCredentialApplicator = ClientCredentialApplicator.PostParameter(this.clientSecret); trong phương thức Authenticate. Đây là cần thiết để lấy mã hoạt động - tôi nghĩ dòng này buộc clientSecret được gửi dưới dạng tham số POST tới máy chủ (thay vì tham số Auth-HTTP cơ bản).

Giải pháp này giả định rằng bạn đã có ID khách hàng, bí mật của khách hàng và mã thông báo làm mới. Lưu ý rằng bạn không cần phải nhập mã thông báo truy cập trong mã. (Mã truy cập ngắn được mua lại "dưới mui xe" từ máy chủ Google khi gửi mã thông báo làm mới lâu dài với dòng client.RefreshAuthorization(state);. Mã thông báo truy cập này được lưu trữ như một phần của auth -variable, từ đó nó được sử dụng để cho phép các API cuộc gọi "under the hood")

Một ví dụ mã mà làm việc cho tôi với API v3 Google để truy cập vào Google Calendar của tôi:.

class SomeClass 
{ 

    private string clientID   = "XXXXXXXXX.apps.googleusercontent.com"; 
    private string clientSecret  = "MY_CLIENT_SECRET"; 
    private string refreshToken  = "MY_REFRESH_TOKEN"; 
    private string primaryCal  = "MY_GMAIL_ADDRESS"; 

    private void button2_Click_1(object sender, EventArgs e) 
    { 
     try 
     { 
      NativeApplicationClient client = new NativeApplicationClient(GoogleAuthenticationServer.Description, this.clientID, this.clientSecret); 
      OAuth2Authenticator<NativeApplicationClient> auth = new OAuth2Authenticator<NativeApplicationClient>(client, Authenticate); 

      // Authenticated and ready for API calls... 

      // EITHER Calendar API calls (tested): 
      CalendarService cal = new CalendarService(auth); 
      EventsResource.ListRequest listrequest = cal.Events.List(this.primaryCal); 
      Google.Apis.Calendar.v3.Data.Events events = listrequest.Fetch(); 
      // iterate the events and show them here. 

      // OR Plus API calls (not tested) - copied from OP's code: 
      var plus = new PlusService(auth); 
      plus.Key = "BLAH"; // don't know what this line does. 
      var me = plus.People.Get("me").Fetch(); 
      Console.WriteLine(me.DisplayName); 

      // OR some other API calls... 
     } 
     catch (Exception ex) 
     { 
      Console.WriteLine("Error while communicating with Google servers. Try again(?). The error was:\r\n" + ex.Message + "\r\n\r\nInner exception:\r\n" + ex.InnerException.Message); 
     } 
    } 

    private IAuthorizationState Authenticate(NativeApplicationClient client) 
    { 
     IAuthorizationState state = new AuthorizationState(new string[] { }) { RefreshToken = this.refreshToken }; 

     // IMPORTANT - does not work without: 
     client.ClientCredentialApplicator = ClientCredentialApplicator.PostParameter(this.clientSecret); 

     client.RefreshAuthorization(state); 
     return state; 
    } 
} 
+0

Tôi không thể thực hiện việc này để biên dịch - phiên bản của API DLL tôi vừa tải xuống không có ClientCre dentialApplicator trên NativeWebApplication (không phải là tôi thậm chí có khả năng tìm thấy một khóa bí mật trong giao diện điều khiển API nữa ?!) –

+0

Bạn phải có 'bằng cách sử dụng DotNetOpenAuth.OAuth2;' trong lớp của bạn, cũng như đã tải xuống DotNetOpenAuth từ đây: http: //www.dotnetopenauth.net/. 'Khóa bí mật 'được gọi là" Bí mật của khách hàng "(Nếu nó không có ở đó, có thể bạn cần thêm khách hàng của mình vào giao diện điều khiển API một lần nữa?) – poplitea

+0

Tôi thực sự đã làm việc này bằng cách sử dụng câu trả lời của Lars Truijens; nó làm việc hoàn hảo lần đầu tiên :-) –

Các vấn đề liên quan