web-dev-qa-db-fra.com

Google.GData.Client.GDataRequestException - L'authentification échoue soudainement avec l'ancien code

Je commence soudainement à obtenir l'exception suivante lors de la tentative d'authentification et d'accès à une feuille de calcul sur Google Drive:

Exception non gérée: Google.GData.Client.GDataRequestException: L'exécution de la demande d'authentification est retournée de manière inattendue résultat: 404 à l'adresse Google.GData.Client.Utilities.getAuthException (jetons TokenCollection, réponse de Htt pWebResponse) sur Google.GData.Client.Utilities.QueryClientLoginToken (GDataCredentials gc, S tring serviceName, String nomapplication, Boolean fUseKeepAlive, IWebProxy prox yServer, Uri .__ clientLoginHandler) sur Google.GData.Client.GDataGAuthRequest.QueryAuthToken (GDataCredentials gc) sur Google.GData.Client.GDataGAuthRequest.EnsureCredentials () sur Google.GData.Client.GDataRequest.EnsureWebRequest () sur Google.GData.Client.GDataGAuthRequest.EnsureWebRequest () sur Google.GData.Client.GDataRequest.Execute () sur Google.GData.Client.GDataGAuthRequest.Execute (Int32 retryCounter) sur Google.GData.Client.GDataGAuthRequest.Execute () sur Google.GData.Client.Service.Query (Uri queryUri, DateTime ifModifiedSince, String etag, Int64 & contentLength) sur Google.GData.Client.Service.Query (FeedQuery feedQuery) sur Google.GData.Documents.DocumentsService.Query (DocumentsListQuery feedQuery) sur GoogleLogger.GoogleService.getLastXECLogRows (String folderName, String fileName, Int32 rows)

Ceci est dans le code qui a fonctionné pendant deux ans sans aucun problème. J'ai d'abord pensé que j'avais peut-être perdu des autorisations d'accès sur mon système de production, mais Google Drive se charge correctement dans mon navigateur Web. Essayé sur plusieurs autres systèmes et je reçois le même. 

Ont-ils changé quelque chose dans l'API Google aujourd'hui? Cela ne peut pas être une coïncidence!

15
Molecool

Google a retiré leur ancienne API d'authentification. OAuth 2.0 devrait être utilisé à la place.

J'ai passé trop de temps à comprendre comment utiliser les nouvelles API Auth avec les anciennes API GData, en récupérant des informations ici et là sur Internet. J'ai décidé de partager tous les détails avec des captures d'écran pour gagner du temps.

  1. Accédez à https://console.developers.google.com/project

  2. Appuyez sur le bouton Create Project

enter image description here

  1. Créer un projet. Tapez un nom.

enter image description here

  1. Allez à API & Auth> Credentials et cliquez sur le bouton Create new Client ID. Il créera automatiquement une clé JSON - ignorez-le.

enter image description here

  1. Hit Generate new P12 key

enter image description here

  1. Le téléchargement du fichier commencera automatiquement. Rappelez-vous le mot de passe, vous en aurez besoin pour ouvrir le fichier que vous venez de télécharger.

enter image description here

  1. Renommez le fichier téléchargé en Key.p12 et ajoutez-le à votre solution. Assurez-vous de définir Build Action et Copy to Output Directory en conséquence.

enter image description here

  1. Installez Google API Auth en utilisant Nuget. Tapez ce qui suit dans la console du gestionnaire de packages

    Install-Package Google.Apis.Auth
    

enter image description here

  1. Copiez l'adresse électronique du compte de service générée à l'étape 4.

enter image description here

  1. Accordez l’autorisation appropriée à cet utilisateur dans votre feuille de calcul Google.

  2. Utilisez le code suivant pour interroger la feuille de calcul. Remplacez l'adresse e-mail et l'adresse URL de la feuille de calcul Google dans le code ci-dessous.

    const string ServiceAccountEmail = "452351479-q41ce1720qd9l94s8847mhc0toao1fed@developer.gserviceaccount.com";
    
    var certificate = new X509Certificate2("Key.p12", "notasecret", X509KeyStorageFlags.Exportable);
    
    var serviceAccountCredentialInitializer = 
        new ServiceAccountCredential.Initializer(ServiceAccountEmail)
        {
            Scopes = new[] { "https://spreadsheets.google.com/feeds" }
        }.FromCertificate(certificate);
    
    var credential = new ServiceAccountCredential(serviceAccountCredentialInitializer);
    
    if (!credential.RequestAccessTokenAsync(System.Threading.CancellationToken.None).Result)
        throw new InvalidOperationException("Access token request failed.");
    
    var requestFactory = new GDataRequestFactory(null);
    requestFactory.CustomHeaders.Add("Authorization: Bearer " + credential.Token.AccessToken);
    
    var service = new SpreadsheetsService(null) { RequestFactory = requestFactory };
    
    var query = new ListQuery("https://spreadsheets.google.com/feeds/list/0ApZkobM61WIrdGRYshh345523VNsLWc/1/private/full");
    var feed = service.Query(query);
    
    var rows = feed.Entries
        .Cast<ListEntry>()
        .Select(arg =>
            new
            {
                Field0 = arg.Elements[0].Value,
                Field1 = arg.Elements[1].Value
            })
        .ToList();
    
33
Alex Aza

J'ai réussi à résoudre ce problème en utilisant cette solution avec un compte de service avec oAuth2.0 Accès aux anciennes API GData (API Spreadsheet) à l'aide de OAuth 2 et d'un compte de service

La solution: 1. Créez un projet et un compte de service Google dans https://console.developers.google.com/project

  1. Générez votre clé p12.
  2. Autoriser les API que vous souhaitez utiliser dans la console développeur (nous allons essentiellement utiliser l'ancienne API, vous pouvez donc ignorer cette étape, mais au cas où)
  3. Utilisez le code ci-dessous (.NET Framework 4.5!)
  4. N'oubliez pas non plus d'octroyer à votre feuille de calcul l'accès à "[email protected]" lorsque vous accordez des autorisations aux utilisateurs habituels en appuyant sur Partager.

Code:

using System.Security.Cryptography.X509Certificates;
using Google.GData.Client;
using Google.GData.Extensions;
using Google.GData.Spreadsheets;
using Google.Apis.Auth.OAuth2;

string keyFilePath = @"C:\key.p12";    // found in developer console
string serviceAccountEmail = "[email protected]";   // found in developer console
var certificate = new X509Certificate2(keyFilePath, "notasecret", X509KeyStorageFlags.Exportable);

ServiceAccountCredential credential = new ServiceAccountCredential(new ServiceAccountCredential.Initializer(serviceAccountEmail) //create credential using certificate
        {
            Scopes = new[] { "https://spreadsheets.google.com/feeds/" } //this scopr is for spreadsheets, check google scope FAQ for others
        }.FromCertificate(certificate));

credential.RequestAccessTokenAsync(System.Threading.CancellationToken.None).Wait(); //request token

var requestFactory = new GDataRequestFactory("Some Name"); 
requestFactory.CustomHeaders.Add(string.Format("Authorization: Bearer {0}", credential.Token.AccessToken));

SpreadsheetsService myService = new SpreadsheetsService("You App Name"); //create your old service
myService.RequestFactory = requestFactory; //add new request factory to your old service

SpreadsheetQuery query = new SpreadsheetQuery(); //do the job as you done it before
SpreadsheetFeed feed = myService.Query(query);
5
Many More

Bon, je l'ai compris. Instructions pas à pas comme suit - voir également le code fourni ci-dessous. Pour votre information, cela fonctionne en .Net 3.5 et contrairement à la solution proposée précédemment, il n’ya pas de nouvelles dépendances. Vous devriez être opérationnel en un rien de temps.

  1. Si vous n'avez pas encore créé vos informations d'identification OAuth 2.0 - je suppose que vous savez déjà comment les obtenir, mais ici:

    a) Connectez-vous à votre console de développeur Google: http://console.developers.google.com b) Créez un projet c) Créez vos informations d'identification - utilisez "l'application installée" d ) Ajoutez les API dont vous avez besoin - Je pense que Drive API est absolument nécessaire. J'ai également ajouté Drive SDK au cas où.

  2. Copiez le code ci-dessous dans VS et modifiez la première méthode Main () avec votre clé client et votre clé secrète.

  3. Exécutez l'application et copiez le nouveau jeton d'accès et le jeton d'actualisation. Placez celles-ci et vos informations d'identification restantes dans la deuxième méthode Main () ci-dessous.

  4. Vous devriez maintenant pouvoir exécuter la deuxième méthode Main () (inversez simplement le nom). À partir de maintenant, ce sera tout ce dont vous avez besoin - il n'est pas nécessaire de réexécuter la première méthode Main ().

BTW, la première méthode Main () ci-dessous a été trouvée ici: https://developers.google.com/google-apps/spreadsheets/authorize

J'ai cependant ajouté le type de jeton manquant ainsi que le type d'accès. Celles-ci sont nécessaires, utilisez le code ci-dessous:

using System;
using Google.GData.Client;
using Google.GData.Spreadsheets;
using Google.GData.Documents;
using System.Configuration;
using System.Collections.Specialized;

namespace GoogleSpreadsheet
{
  class GoogleOAutho2
  {

    private static String folderName = "crazy.ivan";


    static void Main(string[] args)
    {
      ////////////////////////////////////////////////////////////////////////////
      // STEP 1: Configure how to perform OAuth 2.0
      ////////////////////////////////////////////////////////////////////////////

      // TODO: Update the following information with that obtained from
      // https://code.google.com/apis/console. After registering
      // your application, these will be provided for you.

      string CLIENT_ID = "your_client_id";

      // This is the OAuth 2.0 Client Secret retrieved
      // above.  Be sure to store this value securely.  Leaking this
      // value would enable others to act on behalf of your application!
      string CLIENT_SECRET = "your_secret_key"

      // Space separated list of scopes for which to request access.
      string SCOPE = "https://www.googleapis.com/auth/drive https://spreadsheets.google.com/feeds https://docs.google.com/feeds";

      // This is the Redirect URI for installed applications.
      // If you are building a web application, you have to set your
      // Redirect URI at https://code.google.com/apis/console.
      string REDIRECT_URI = "urn:ietf:wg:oauth:2.0:oob";

      string TOKEN_TYPE = "refresh";

      ////////////////////////////////////////////////////////////////////////////
      // STEP 2: Set up the OAuth 2.0 object
      ////////////////////////////////////////////////////////////////////////////

      // OAuth2Parameters holds all the parameters related to OAuth 2.0.
      OAuth2Parameters parameters = new OAuth2Parameters();

      // Set your OAuth 2.0 Client Id (which you can register at
      // https://code.google.com/apis/console).
      parameters.ClientId = CLIENT_ID;

      // Set your OAuth 2.0 Client Secret, which can be obtained at
      // https://code.google.com/apis/console.
      parameters.ClientSecret = CLIENT_SECRET;

      // Set your Redirect URI, which can be registered at
      // https://code.google.com/apis/console.
      parameters.RedirectUri = REDIRECT_URI;

      ////////////////////////////////////////////////////////////////////////////
      // STEP 3: Get the Authorization URL
      ////////////////////////////////////////////////////////////////////////////

      // Set the scope for this particular service.
      parameters.Scope = SCOPE;

      parameters.AccessType = "offline"; // IMPORTANT and was missing in the original

      parameters.TokenType = TOKEN_TYPE; // IMPORTANT and was missing in the original


      // Get the authorization url.  The user of your application must visit
      // this url in order to authorize with Google.  If you are building a
      // browser-based application, you can redirect the user to the authorization
      // url.
      string authorizationUrl = OAuthUtil.CreateOAuth2AuthorizationUrl(parameters);
      Console.WriteLine(authorizationUrl);
      Console.WriteLine("Please visit the URL above to authorize your OAuth "
        + "request token.  Once that is complete, type in your access code to "
        + "continue...");
      parameters.AccessCode = Console.ReadLine();

      ////////////////////////////////////////////////////////////////////////////
      // STEP 4: Get the Access Token
      ////////////////////////////////////////////////////////////////////////////

      // Once the user authorizes with Google, the request token can be exchanged
      // for a long-lived access token.  If you are building a browser-based
      // application, you should parse the incoming request token from the url and
      // set it in OAuthParameters before calling GetAccessToken().
      OAuthUtil.GetAccessToken(parameters);
      string accessToken = parameters.AccessToken;
      string refreshToken = parameters.RefreshToken;
      Console.WriteLine("OAuth Access Token: " + accessToken + "\n");
      Console.WriteLine("OAuth Refresh Token: " + refreshToken + "\n");

      ////////////////////////////////////////////////////////////////////////////
      // STEP 5: Make an OAuth authorized request to Google
      ////////////////////////////////////////////////////////////////////////////

      // Initialize the variables needed to make the request
      GOAuth2RequestFactory requestFactory =
          new GOAuth2RequestFactory(null, "MySpreadsheetIntegration-v1", parameters);
      SpreadsheetsService service = new SpreadsheetsService("MySpreadsheetIntegration-v1");
      service.RequestFactory = requestFactory;

      // Make the request to Google
      // See other portions of this guide for code to put here...

      // Instantiate a SpreadsheetQuery object to retrieve spreadsheets.
      Google.GData.Spreadsheets.SpreadsheetQuery query = new Google.GData.Spreadsheets.SpreadsheetQuery();

      // Make a request to the API and get all spreadsheets.
      SpreadsheetFeed feed = service.Query(query);

      // Iterate through all of the spreadsheets returned
      foreach (SpreadsheetEntry entry in feed.Entries)
      {
        // Print the title of this spreadsheet to the screen
        Console.WriteLine(entry.Title.Text);
      }
      Console.ReadLine();

     }


    // once you copied your access and refresh tokens
    // then you can run this method directly from now on...
    static void MainX(string[] args)
    {
    GOAuth2RequestFactory requestFactory = RefreshAuthenticate();

         SpreadsheetsService service = new SpreadsheetsService("MySpreadsheetIntegration-v1");  
         service.RequestFactory = requestFactory;

      // Instantiate a SpreadsheetQuery object to retrieve spreadsheets.
      Google.GData.Spreadsheets.SpreadsheetQuery query = new Google.GData.Spreadsheets.SpreadsheetQuery();

      // Make a request to the API and get all spreadsheets.
      SpreadsheetFeed feed = service.Query(query);

      // Iterate through all of the spreadsheets returned
      foreach (SpreadsheetEntry entry in feed.Entries)
      {
        // Print the title of this spreadsheet to the screen
        Console.WriteLine(entry.Title.Text);
      }
      Console.ReadLine();



    public static GOAuth2RequestFactory RefreshAuthenticate() {
        OAuth2Parameters parameters = new OAuth2Parameters(){
            RefreshToken = "the_refresh_token_you_copied_from_the_CLI_running_the_first_method";
            AccessToken = "the_access_token_you_copied_from_the_CLI_running_the_first_method";
            ClientId = "your_client_id";
            ClientSecret = "your_dirty_little_secret";
            Scope = "https://www.googleapis.com/auth/drive https://spreadsheets.google.com/feeds",
            AccessType = "offline",
            TokenType = "refresh"
        };
        string authUrl = OAuthUtil.CreateOAuth2AuthorizationUrl(parameters);
        return new GOAuth2RequestFactory(null, "evilspeculator", parameters);
    }
  }
}

J'espère que cela fonctionne pour vous les gars - bonne chance!

4
Molecool

Andrew, je me demandais comment vous avez obtenu la dll google.apis.auth.oauth2. J'essaie d'implémenter votre solution et je ne trouve pas la bonne manière d'installer la bibliothèque. 

Je sens que je pourrai peut-être que cela fonctionne une fois que j'aurai cette partie.

0
surewould