Dostęp do starszych interfejsów API GData (API arkusza kalkulacyjnego) przy użyciu OAuth 2 i konta usługi

Krótkie pytanie brzmi, czy jest to możliwe, a jeśli tak, to w jaki sposób?

Zarys

Mam aplikację. NET, która obecnie korzysta z konta usługi, aby uzyskać dostęp do informacji w domenie Google Apps za pomocą interfejsu API Dysku Google. Działa to dobrze przy użyciu google-api-dotnet-client library i kodu w tych samych liniach , Jak pokazano w przykładach tutaj - które są obecnie bardzo dobrym podstawowym przykładem tego, co robię.

Chcę to teraz rozszerzyć tak więc, jak również korzystanie z tych API dostarczonych przez" nową "bibliotekę google-api-dotnet-client, korzysta ze starszych bibliotek "GData", jak przewidziano za pośrednictwem starsza biblioteka Google-gdata , w szczególności API arkuszy kalkulacyjnych (i być może więcej w przyszłości).

Problem

Tutaj pojawia się trudność. Poprzednia biblioteka robi dokładnie to, co chcę, o czym świadczy drugi link w pierwszym akapicie powyżej - i fakt, że sam to robię. jednakże ... chociaż druga biblioteka została zaktualizowana do obsługi OAuth 2.0 oprócz OAuth 1.0 i innych starszych technik auth, nie pozwala-o ile mogę powiedzieć z rozległego Googling i trail-and - error-pozwalają na" konto usługi w imieniu wszystkich moich użytkowników " operacji, której potrzebuję.

Moje pytanie brzmi, czy brakuje mi czegoś (być może trudnego do znalezienia lub nieudokumentowanego czegoś), co pozwoliłoby mi robić to, co chcę. Jeśli tego nie zrobię, czy jest jakiś sposób, żebym mógł wymusić to zachowanie i sprawić, by te dwie biblioteki działały obok siebie?

Idealne rozwiązanie

Najlepiej byłoby, gdyby instancja Google.GData.Spreadsheets.SpreadsheetsService mogła wykorzystać instancję Google.Apis.Authentication.Auth2Authenticator<AssertionFlowClient>, której już używam... jakoś. Czy takie czary są możliwe? Przegapiłem to, co oczywiste?

Jeśli tego nie zrobię, z przyjemnością wykonam cały taniec OAuth2 "assertion flow client", jeśli będę musiał, w jakiś sposób, z którym starsza biblioteka sobie poradzi.

Pomocy?

Inne Myśli

Rozważałem - i na razie odrzucałem-możliwość rozpoczęcia od zera i napisania własnej biblioteki, aby tak się stało. Jest to z dwóch powodów:

  1. biblioteka gdata już istnieje i została opracowana przez wiele osób, prawdopodobnie mądrzejszych niż ja. Nie jestem tak arogancki, że wierzę, że stać mnie na więcej.
  2. nie jestem pewien, czy podejście OAuth2 z kontem usługi jest nawet obsługiwane / dozwolone w tych starszych interfejsach API.

An alternatywnym podejściem, którego miałem nadzieję uniknąć, ale być może będę musiał wycofać się w zależności od odpowiedzi tutaj będzie użycie 2-legged OAuth 1.0 Dla części tego. Wolałbym nie, ponieważ części aplikacji polegają na jednej starej metodzie auth, podczas gdy inne części robią to w nowy sposób, po prostu czuję się źle. I jest o wiele więcej do zrobienia...


Aktualizacje

Rozważałem możliwość podklasowania GDataRequestFactory i GDataRequest, aby móc tworzyć własne request factory i niech to weźmie instancję Google.Apis.Authentication.Auth2Authenticator<AssertionFlowClient> (w każdym razie instancję Google.Apis.Authentication.IAuthenticator), która może wkroczyć w celu uwierzytelnienia żądania tuż przed jego wywołaniem. Jednak... konstruktor GDataRequest jest wewnętrzny, co mnie zatrzymało.

Wygląda na to, że tak nie powinno być.
Author: Mark Embling, 2012-12-02

3 answers

Ze względu na innych ludzi natykających się na to pytanie (teraz, gdy rozwiązanie powiązane z akceptowaną odpowiedzią używa przestarzałego kodu), oto jak go rozwiązałem: {]}

Najpierw uruchom" nowe API " (użyj pakietu Google.Apis.Auth nuget), konfigurując ServiceAccountCredentialna przykładzie konta usługi Google :

//In the old api, this accessed the main api accounts' sheets, not anymore
//** Important ** share spreadsheets with the Service Account by inviting the "serviceAccountEmail" address to the sheet
string serviceAccountEmail = "[email protected]";

var certificate = new X509Certificate2(@"key.p12", "notasecret", X509KeyStorageFlags.Exportable);

ServiceAccountCredential credential = new ServiceAccountCredential(
   new ServiceAccountCredential.Initializer(serviceAccountEmail)
   {
       Scopes = new[] { "https://spreadsheets.google.com/feeds", "https://docs.google.com/feeds" }
   }.FromCertificate(certificate));

Powiedz poświadczającemu, aby zażądał Tokena dostępu:

credential.RequestAccessTokenAsync(System.Threading.CancellationToken.None).Wait();

Teraz nadszedł czas, aby przełączyć się z powrotem na" Stare API " (użyj pakietu Google.GData.Spreadsheets nuget). Start by konstruowanie SpreadsheetsService (podobne do przykładu Google ' a ):

SpreadsheetsService service = new SpreadsheetsService("MySpreadsheetIntegration-v1");
Aby użyć uwierzytelniania konta usługi, utworzymy instancję GDataRequestFactory i ustawimy niestandardowy nagłówek Authorization:
var requestFactory = new GDataRequestFactory("My App User Agent");
requestFactory.CustomHeaders.Add(string.Format("Authorization: Bearer {0}", credential.Token.AccessToken));

Na koniec ustaw właściwość SpreadsheetsService RequestFactory do nowej fabryki:

service.RequestFactory = requestFactory;

I śmiało, użyj SpreadsheetsService tak, jak uwierzytelniłbyś To każdą inną techniką. (Wskazówka: Udostępnij arkusze kalkulacyjne z kontem serwisu, zapraszając adres serviceAccountEmail do arkusz)

 20
Author: Matt K,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-10 01:54:18

Udało mi się to rozwiązać poprzez podklasowanie GDataRequestFactory i stworzenie własnej implementacji interfejsów zaimplementowanych przez GDataRequest. Implementacja ta otacza instancję GDataRequest utworzoną przez reflection i dodaje kod niezbędny do przeprowadzenia uwierzytelniania za pomocą instancji Iauthenticator (w moim przypadku Auth2Authenticator).

Napisałem na nim post na blogu i dodałem przykład jako Gist:

Zapraszam do korzystania z tego, jeśli ci to pomoże (licencja BSD).

 4
Author: Mark Embling,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-09 13:28:39

Hej po prostu natknąłem się na ten sam problem i stworzyłem inne rozwiązanie:

Czy ktoś kiedykolwiek miał możliwość zapisania parametrów z credentials-object bezpośrednio do Oauth2parameters-Object?

Zrobiłem to i działało ładnie:

public class OAuthTest
{  
    OAuth2Parameters param = new OAuth2Parameters();

    public OAuthTest()
    {
        Debug.WriteLine("Calling: AuthGoogleDataInterface()");
        bool init = AuthGoogleDataInterface();
        if (init)
        {
            GOAuth2RequestFactory requestFactory = new GOAuth2RequestFactory(null, "My App User Agent", this.param);
            //requestFactory.CustomHeaders.Add(string.Format("Authorization: Bearer {0}", credential.Token.AccessToken));
            var service = new SpreadsheetsService("MyService");
            service.RequestFactory = requestFactory;
            SpreadsheetQuery query = new 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
                Debug.WriteLine(entry.Title.Text);
            }
        }
        Debug.WriteLine(m_Init);
    }

    private bool AuthGoogleDataInterface()
    {
        bool b_success;
        try
        {
            Console.WriteLine("New User Credential");
            // New User Credential
            UserCredential credential;
            using (var stream = new FileStream("client_secrets.json", FileMode.Open, FileAccess.Read))
            {
                GoogleClientSecrets GCSecrets = GoogleClientSecrets.Load(stream);
                string[] ArrScope = new[] { "https://spreadsheets.google.com/feeds", "https://docs.google.com/feeds" };
                credential = GoogleWebAuthorizationBroker.AuthorizeAsync(
                    GCSecrets.Secrets,
                    ArrScope,
                    "user", CancellationToken.None,
                new FileDataStore("My.cal")).Result;
                // put the Information generated for the credentials object into the OAuth2Parameters-Object to access the Spreadsheets
                this.param.ClientId = GCSecrets.Secrets.ClientId; //CLIENT_ID;
                this.param.ClientSecret = GCSecrets.Secrets.ClientSecret; //CLIENT_SECRET;
                this.param.RedirectUri = "urn:ietf:wg:oauth:2.0:oob"; //REDIRECT_URI;
                this.param.Scope = ArrScope.ToString();
                this.param.AccessToken = credential.Token.AccessToken;
                this.param.RefreshToken = credential.Token.RefreshToken;
            }

            Debug.WriteLine("AuthGoogleDataInterface: Success");
            b_success = true;
        }
        catch (Exception e)
        {
            Debug.WriteLine(e.ToString());
            b_success = false;
        }
        return b_success;
    }
}
 3
Author: mhaenssgen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-06 06:03:37