0

我正在使用适用于 .NET 的 Google API。我正在关注示例项目Simple OAuth2,但我不断从 DotNetOpenAuth 获得协议异常。

这是我现在拥有的:

public static void Main( string[] args )
{
   // Register the authenticator.
   NativeApplicationClient provider = new NativeApplicationClient(
      GoogleAuthenticationServer.Description, gaAppId, gaSecret );
   OAuth2Authenticator<NativeApplicationClient> auth = new OAuth2Authenticator<NativeApplicationClient>(
      provider, GetAuthorization );

   AnalyticsService analyticsService =
      new AnalyticsService( new BaseClientService.Initializer {
         Authenticator = auth,
         ApplicationName = @"Test Application",
      } );
   DataResource.GaResource.GetRequest request = analyticsService.Data.Ga.Get(
      gaId, @"2013-09-04", @"2013-09-18", "ga:totalEvents" );
   GaData data = request.Execute();

   Console.ReadKey();
}

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

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

注意:我在这段代码中使用了 Analytics API,因为这正是我所需要的。使用示例中描述的 Tasks API 时,我遇到了同样的错误。

身份验证代码是由示例代码中定义的进程生成的刷新令牌。两种情况都会出现错误(请求新令牌,或重新使用旧令牌。)

由 DotNetOpenAuth 触发的 ProtocolException 存在,因为 accounts.google.com 返回错误:无效请求。

OAuth 请求如下所示:

Aplication/x-www-form-urlencoded; charset=utf-8
User-Agent: DotNetOpenAuth/4.3.1.13153
Host: accounts.google.com
Cache-Control: no-store,no-cache
Pragma: no-cache
Content-Length: 148
Connection: Keep-Alive

code=REDACTED&redirect_uri=urn%3Aietf%3Awg%3Aoauth%3A2.0%3Aoob&grant_type=authorization_code

这就是谷歌返回的内容:

HTTP/1.1 400 Bad Request
IRRELEVANT_HEADERS
{
  "error" : "invalid_request"
}

我对为什么会发生这种情况以及如何解决这个问题感到有点茫然。我找不到任何其他可用的 C# 示例。这似乎是与此线程中的错误不同的一种错误。你们有谁知道我该如何解决这个问题?

4

1 回答 1

0

我进一步研究了 peleyal 提供的示例,并设法找到了问题所在。问题是我实际上并没有存储刷新令牌,而是存储了身份验证令牌。我应该使用身份验证令牌来生成刷新令牌。

这是以简化方式提供的完整解决方案,以供将来参考。差异可以在 GetAuthorization 函数中找到,该函数现在可以正确保存刷新令牌并在刷新令牌尚不可用时打开浏览器窗口以请求授权。

private static refreshToken = null;

public static void Main( string[] args )
{
    // Register the authenticator.
    NativeApplicationClient provider = new NativeApplicationClient(
    GoogleAuthenticationServer.Description, gaAppId, gaSecret );
    OAuth2Authenticator<NativeApplicationClient> auth = new OAuth2Authenticator<NativeApplicationClient>(
        provider, GetAuthorization );

    AnalyticsService analyticsService = new AnalyticsService( new BaseClientService.Initializer {
        Authenticator = auth,
        ApplicationName = @"Test Application",
    } );
    DataResource.GaResource.GetRequest request = analyticsService.Data.Ga.Get( gaId, @"2013-09-04",
        @"2013-09-18", @"ga:totalEvents" );
    GaData data = request.Execute();

    Console.ReadKey();
}

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

    if( !string.IsNullOrEmpty( refreshToken ) ) {
        try {
            state.RefreshToken = refreshToken;
            arg.RefreshToken( state );
        } catch {
            refreshToken = null;
        }
    }

    // If the refresh token is empty, request a new one by opening
    // a browser window. Allows the user to paste its authorization token
    // and saves the refresh token.
    if( string.IsNullOrEmpty( refreshToken ) ) {
        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:
        state = arg.ProcessUserAuthorization( authCode, state );
        refreshToken = state.RefreshToken;
    }

    return state;
}
于 2013-09-25T10:46:38.643 回答