Google+ Moments.insert - Unauthorized Error

2019-03-06 02:01发布

问题:

According to the docuemtntation for Moments.insert with the Google+ API autentication with the following scope is required

https://www.googleapis.com/auth/plus.login

I am authenticating with all of the possible PlusService scopes but i am still getting the following error

Google.Apis.Requests.RequestError Unauthorized [401] Errors [ Message[Unauthorized] Location[ - ] Reason[unauthorized] Domain[global]

 //Scopes for use with Google+ API
 // activating Google+ API in console
 // Documentation:  https://developers.google.com/+/api/oauth
 string[] scopes = new string[] {
    PlusService.Scope.PlusLogin,
    PlusService.Scope.UserinfoEmail,
    PlusService.Scope.UserinfoProfile
 };

 string _client_id = "2046123799103-d0vpdthl4ms0soutcrpe036ckqn7rfpn.apps.googleusercontent.com";
 string _client_secret = "NDmluNfTgUk6wgmy7cFo64RV";

 PlusService service = null;
 UserCredential credential = null;

 try {
    // here is where we Request the user to give us access, or use the Refresh Token that was previously stored in %AppData%
    credential = GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets {
        ClientId = _client_id, ClientSecret = _client_secret
    },
    scopes,
    Environment.UserName,
    CancellationToken.None,
    new FileDataStore("Daimto.GooglePlus.Auth.Store")).Result;
 } catch (Exception ex) {
    //If the user hits cancel you wont get access.
    if (ex.InnerException.Message.IndexOf("access_denied") != -1) {
        Console.WriteLine("User declined access");
        Console.ReadLine();
        return;
    } else {
        Console.WriteLine("Unknown Authentication Error:" + ex.Message);
        Console.ReadLine();
        return;
    }
 }

 // Now we create a Google service. All of our requests will be run though this.
 service = new PlusService(new BaseClientService.Initializer() {
    HttpClientInitializer = credential,
    ApplicationName = "Google Plus Sample",
 });


 Moment body = new Moment();
 body.Type = "http://schema.org/AddAction";

 ItemScope itemScope = new ItemScope();
 itemScope.Id = "target-id-1";
 itemScope.Type = "http://schema.org/AddAction";
 itemScope.Name = "The Google+ Platform";
 itemScope.Description = "A page that describes just how awesome Google+ is!";
 itemScope.Image = "https://developers.google.com/+/plugins/snippet/examples/thing.png";
 body.Object = itemScope;

 try {
    var l = service.Moments.Insert(body, "me", MomentsResource.InsertRequest.CollectionEnum.Vault);
    l.Execute();
 } catch (Exception ex) {
    int i = 1;
 }

I have tested authentication and it is working i am able to list activities and other things. Its only inserting moments that is giving me this error. I have also tried doing this in PHP and am getting the same error. What am I missing?

Update: I found something in the documentation for moments.insert

When authenticating for moments.insert, you must include the data-requestvisibleactions parameter to specify which types of App Activities your application will write.

I have not figured out yet how to set this data-requestvisibleactions.

回答1:

As you've noticed, you need to add the request_visible_actions parameter to the request. Most of the other OAuth libraries from Google have added a shortcut to do this, but it looks like the .NET library hasn't. For example, the PHP library has setRequestVisibleActions().

Internally, the convenience method GoogleWebAuthorizationBroker.AuthorizeAsync() calls AuthorizationCodeFlow.CreateAuthorizationCodeRequest() to generate the URL used in the call. You can subclass AuthorizationCodeFlow and AuthorizationCodeRequestUrl (which it returns) to add the parameter in question and then go through the flow more directly.

You can see an example of how to do this at https://github.com/gguuss/google-dotnet-demo/blob/master/AuthWithAppActivities/Program.cs

You can also use a Google+ Sign-In button to do the initial auth flow and pass the one-time code to the server, which can then proceed to turn this into a valid token. Since the Sign-In button has the data-requestvisibleactions attribute, this will take care of that part of the auth for you.