Sharing Moments in GooglePlus from C# - c#

Are there any libraries out there for C# that wrap the process of sharing moments to a user's Google+ account (or to their stream)? I'm looking for something that simply take your ClientId and ClientSecret, and maybe your apiKey along with the user's id to send some text that the user has decided to share with his/her friends.
If not, but you have an example of creating a WebRequest to accomplish the same thing, that would be much appreciated too!
I've reviewed this landing page: https://developers.google.com/+/quickstart/csharp
But I'm trying to integrate into an existing MVC5 application that already has the Auth for GooglePlus taken care of.

The correct client to be using for Google APIs is the Google .NET API Client library, available via NuGet. Additional libraries for specific APIs are required if you use more than the core library. For Plus, you need the Google.Apis.Plus.v1 package.
After you have added it to your projects and have configured an API client, writing app activities is as easy as:
/// <summary>The app activity type for ADD.</summary>
private const string ADD_ACTIVITY_TYPE = #"http://schemas.google.com/AddActivity";
// Construct your Plus Service, I'll assume a helper for here.
PlusService plusService = GetPlusService(credentials);
Moment addMoment = new Moment();
ItemScope target = new ItemScope()
{
Url = ContentUrl
};
addMoment.Type = ADD_ACTIVITY_TYPE;
addMoment.Target = target;
Moment response = null;
try
{
response = plusService.Moments.Insert(addMoment, "me",
MomentsResource.InsertRequest.CollectionEnum.Vault).Execute();
}
catch (System.AggregateException)
{
/* Occurs when the server can't be seen by Google. */
}
catch (Google.GoogleApiException)
{
/* Occurs when the server can't be seen by Google. */
}
How to authenticate a user and authorize your client for access to Google APIs in MVC can be found on this blog: ASP.NET MVC with OpenID and OAuth.
A final note, app activities require you to specify an app activities pseudo-scope (request_visible_actions) which is easier with the Sign-In button than via the framework. If you are getting 401 errors, this is the most likely culprit.

Related

PayPal oauth2 authorization and .net core

So I'm trying to set up PayPal sign-in within my .net core application. I'm using this 3rd party library to do so: https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers
I'm building my application upon Umbraco CMS, and within the appropriate section I use the following:
builder.AddMemberExternalLogins(logins =>
{
logins.AddMemberLogin(
memberAuthenticationBuilder =>
{
memberAuthenticationBuilder.AddPaypal(
memberAuthenticationBuilder.SchemeForMembers(PayPalMemberExternalLoginProviderOptions.SchemeName),
options =>
{
options.ClientId = clientId;
options.ClientSecret = clientSecret;
});
});
});
Out of the box, this does not work. From reading around it seems that it seems the authorization endpoints are using the live values, and these are not appropriate for testing with Paypal's sandbox endpoints.
After reading the following thread: https://github.com/aspnet-contrib/AspNet.Security.OAuth.Providers/issues/198 I can see that this user had to update the endpoints manually to use different values:
.AddPaypal(options =>
{
options.ClientId = Startup.Configuration["Authentication:Paypal:ClientId"];
options.ClientSecret = Startup.Configuration["Authentication:Paypal:ClientSecret"];
options.AuthorizationEndpoint = "https://www.sandbox.paypal.com/webapps/auth/protocol/openidconnect/v1/authorize";
options.TokenEndpoint = "https://api.sandbox.paypal.com/v1/identity/openidconnect/tokenservice";
options.UserInformationEndpoint = "https://api.sandbox.paypal.com/v1/identity/openidconnect/userinfo?schema=openid";
})
Now once updating these values, the authorization seems to work. But I've found it to be very unreliable. On my personal dev machine it seems to allow me to authorize, but when testing with another colleague, he finds he is constantly logged out and sometimes it doesn't authorize at all.
When I look at the previous thread I can see that this was written in 2017, and I'm wondering if the endpoints have been updated or the process has been changed entirely by Paypal, but I can't find any documentation on this.
Basically I'm looking for the simplest way to integrate Paypal sign-in on my application. When I read Paypal's documentation (https://developer.paypal.com/docs/log-in-with-paypal/integrate/) I only see mention of refreshing the token, I don't see anything about an authorization endpoint or user information endpoint.
I'm getting quite confused and I'm wondering if anyone has successfully managed to set up a Paypal sign-in with a .net core application in 2022 and whether they have any sample code.
Any pointers would be greatly appreciated. Thanks.
That does seem like an old integration. I would advise following https://developer.paypal.com/docs/log-in-with-paypal/integrate/ from scratch, which can be implemented in any language for the eventual server-side calls. The initial client-side authorization is done in either the JS popup or using a redirect (JS is better)
After exchanging the resulting authorization_code for a refresh token, that token can then be used to obtain information about the user's account (or do API operations involving it), according to the scopes that were authorized.

What is the proper way to work with the OneDrive API?

I want to interact with OneDrive in my WinForms application. Sadly, the Azure quick start samples do not include WinForms, just UWD.
The flow on what I have to do is consistent, namely given my Client ID, I have to obtain an Authentication Code. Given the authentication code, I can then obtain an Access Code, which will allow me to interact in a RESTful way with the OneDrive API. My plan is to have the authentication piece go in a .Net Framework Library and the file IO calls will go in another library that has no user interface access, as it will go in a Windows Service. I would pass the Access Token to the service.
AADSTS50059: No tenant-identifying information found in either the request or implied by any provided credentials.
This error corresponds to the following code fragment that I lifted from the sample .Net Core daemon quick start code.
Note: I was playing around with Scopes as I kept receiving scope errors and I saw one article, whose link I should have kept, which stated to use the API and default scope.
public bool GetRestAuthenticationToken(out string tokenAuthentication)
{
tokenAuthentication = null;
try
{
IConfidentialClientApplication app;
app = ConfidentialClientApplicationBuilder.Create(Authenticate.AppClientId)
.WithClientSecret(Authenticate.AppClientSecret)
.WithAuthority(new Uri(#"https://login.microsoftonline.com/common/oauth2/nativeclient"))
.Build();
string scope = $"onedrive.readwrite offline_access";
System.Collections.Generic.List<string> enumScopes = new System.Collections.Generic.List<string>();
enumScopes.Add("api://<GUID>/.default");
//enumScopes.Add(Authenticate.Scopes[1]);
var result = Task.Run(async () => await app.AcquireTokenForClient(enumScopes).ExecuteAsync()).Result;
...
}
...
}
I believe that I have my application configured properly now on Azure, but am not 100% positive.
API Permissions:
Authentication:
Desktop Applications: https://login.microsoftonline.com/common/oauth2/nativeclient
Desktop Applications: https://login.live.com/oauth20_desktop.srf
Implicit Grants: Access tokens & ID tokens
Live SDK support (Yes)
Default client type (Yes)
Others:
I do have a client secret and kept note of all the Overview GUIDs
Microsoft Doc 1
I tried several different URLs, but only the one not commented out works with the fragment above, but throws the referenced error.
//string redirect_uri = #"https://www.myapp.com/auth";
//string redirect_uri = "https://login.live.com/oauth20_desktop.srf";
string url = #"https://login.microsoftonline.com/common/oauth2/nativeclient";
//string url = $"https://login.live.com/oauth20_authorize.srf?client_id={appClientId}&scope={scope}&response_type=code&redirect_uri={redirect_uri}";
//string url = $"https://login.microsoftonline.com/common/oauth2/v2.0/authorize?" +
// $"client_id={Authenticate.AppClientId}&" +
// $"scope={scope}&" +
// $"response_type=token&" +
// $"redirect_uri={redirect_uri}";
The goal is the same, namely to obtain an access token that I can use with RESTful calls to work with files and/or directories on OneDrive, e.g.
System.Net.Http.HttpClient client = new System.Net.Http.HttpClient();
client.GetAsync(...);
You are trying to implement Client credentials grant type to get the access token.
Based on MSAL initialization, Authority is
(Optional) The STS endpoint for user to authenticate. Usually
https://login.microsoftonline.com/{tenant} for public cloud, where
{tenant} is the name of your tenant or your tenant Id.
We assume that your tenant is "myTenent.onmicrosoft.com", then you should set it as https://login.microsoftonline.com/myTenent.onmicrosoft.com here.
I notice that you specify a scope "onedrive.readwrite" in your code. But it's not a valid permission of Microsoft Graph. The default scope of Microsoft Graph is https://graph.microsoft.com/.default.

Dropbox - Migrating oauth1 to oauth2 using token_from_oauth1

I have been using Dropbox via the Sharpbox toolkit for a while. It's based on oAuth1, so I have a database full of oAuth1 access tokens for my users.
I'd like to convert to the new Dropbox API, which is based on oAuth2. I see that there is a "token_from_oauth1" endpoint in Dropbox's v1 spec (reference here), but I'm not figuring out how to successfully connect to this endpoint to upgrade a user's existing token. (I'm using C#/.NET).
Can anybody point me to some sample code that shows how to create a properly authenticated call to perform this operation? I think the problem is in trying to correctly authenticate/sign the request. (All of my existing dropbox calls are done by the Sharpbox library, so I can't see how it does the authentication).
Thanks!
You can get this using a simple rest client (Like RestSharp) and doing a call like this
I'm currently doing this in a xamarin app, i use the xamarin dropbox core api to login, and get the oauth_token, oauth_consumer_key and the oauth_signature. If you managed the oauth1 flow with c# is then easy to get the oauth2 token.
var rclient = new RestSharp.RestClient("https://api.dropboxapi.com/1/");
var rrequest = new RestSharp.RestRequest("oauth2/token_from_oauth1", Method.POST);
rrequest.AddHeader("Authorization", "OAuth oauth_version=\"1.0\", oauth_signature_method=\"PLAINTEXT\"");
rrequest.AddParameter("oauth_consumer_key", store.GetConsumerKey());
rrequest.AddParameter("oauth_token", store.GetAccessToken());
rrequest.AddParameter("oauth_signature", String.Concat(App.DropboxAppSecret, "&", store.GetAccessTokenSecret()));
var rresponse = rclient.Execute(rrequest);
string content = rresponse.Content;
There's a library for Twitter oAuth 1.0 (see http://www.voiceoftech.com/swhitley/?p=681) that actually makes it easy to make oAuth 1.0 authenticated calls. So the code below seems to work pretty well for me:
oAuthTwitter oat = new oAuthTwitter();
oat.Token = <oauth 1.0 token>;
oat.TokenSecret = <oauth 1.0 secret>;
oat.ConsumerKey = <application key>;
oat.ConsumerSecret = <application secret>;
string resultJSON = oat.oAuthWebRequest(oAuthTwitter.Method.POST, "https://api.dropboxapi.com/1/oauth2/token_from_oauth1", null);

C# application - Read Google Contacts

Since Google stopped support for their older Auth, and now we have to use oAuth 2, our simple desktop application can no longer read contacts from my google account.
Fine - i understand this, however this new oAuth 2 is extraordinarily complicated... and im not talking about from a developer perspective. From what i am reading online. We now have to make our customers jump over a multitude of hoops in order for our simple application to read contacts stored in their Google mail/Contacts.
My iPhone seems to be able to sync contacts just fine with just the typical email and password that i entered about a year ago. How do they get it to work? and yet with my simple desktop application, the client has to be rummaging around in Google Developer sites and with API settings etc. I'm a developer and im confused!! - could you imagine what my customer is going to go through... it cant be this complicated.
Is there anyone who can give me the simple 1,2,3 to get a C# desktop application to go off and get the contacts (read-only) from a particular Gmail account... with the least amount of fiddling around (for the owner of the Gmail account).
Ill do all the hard work in the application - i just don't want to client to have to spend an hour authorizing and creating API's and clicking around in a developer site (he/she is NOT a developer).
The main problem you have here is that contacts is an old Gdata API. It is possible to use Oauth2 with the Gdata library but its not pretty. Personally I like to hack things a little. I use the Current .net client library with the old Gdata client library.
Nuget New client library for authentication:
not 100% sure this is the only one you need let me know if it doesn't work we can find it. You basically need Google.apis.auth.oauth2 and google apis.util.store.
Install-Package Google.Apis.Auth
Nuget old client library for contacts:
Install-Package Google.GData.Contacts
Code
using Google.Apis.Auth.OAuth2;
using Google.Apis.Util.Store;
using Google.Contacts;
using Google.GData.Client;
using System;
using System.Threading;
public static void auth()
{
string clientId = "xxxxxx.apps.googleusercontent.com";
string clientSecret = "xxxxx";
string[] scopes = new string[] { "https://www.googleapis.com/auth/contacts.readonly" }; // view your basic profile info.
try
{
// Use the current Google .net client library to get the Oauth2 stuff.
UserCredential credential = GoogleWebAuthorizationBroker.AuthorizeAsync(new ClientSecrets { ClientId = clientId, ClientSecret = clientSecret }
, scopes
, "test"
, CancellationToken.None
, new FileDataStore("test")).Result;
// Translate the Oauth permissions to something the old client libray can read
OAuth2Parameters parameters = new OAuth2Parameters();
parameters.AccessToken = credential.Token.AccessToken;
parameters.RefreshToken = credential.Token.RefreshToken;
RunContactsSample(parameters);
Console.ReadLine();
}
catch (Exception ex)
{
Console.ReadLine();
}
Console.ReadLine();
}
/// <summary>
/// Send authorized queries to a Request-based library
/// </summary>
/// <param name="service"></param>
private static void RunContactsSample(OAuth2Parameters parameters)
{
try
{
RequestSettings settings = new RequestSettings("Google contacts tutorial", parameters);
ContactsRequest cr = new ContactsRequest(settings);
Feed<Contact> f = cr.GetContacts();
foreach (Contact c in f.Entries)
{
Console.WriteLine(c.Name.FullName);
}
}
catch (Exception a)
{
Console.WriteLine("A Google Apps error occurred.");
Console.WriteLine();
}
}
Tutorial can be found here
Google developers console
All applications accessing google apis must be registered on Google developers console. It is the application accessing Google that is registered users running the code do not need to do this step. Its you as a developer who has to register it.
From this you get the client id and client secret used in the code above.
I have done this but its all a bit of a blur from like you say, a lot of fiddling.
I think you can sign up and setup a project in google developer console and generate a service account. Then the client will need to sign in to HERE as the google app admin and fill out the clientID field with the name of your service account generated by the developer console and the API scope you need access to.
In the end I just logged in as the client to their admin panel and set it up for them. There is no easy way about it without the client also engaging a google apps re-seller to assist. I managed to figure it out as a developer with a lot of googling.

Google Calendar V3 2 Legged authentication fails

I'm trying to create web page that access the (business) private calendar of the company and insert events if the time slot is available. Still I'm facing an authentication problem.
The API manual states that I should use an API key and Oauth2LeggedAuthenticator, so I did all this and the request that is fired is quite okey (it has a oauth token and such) But still the response is an exception with Invalid Credentials; Easy to say is that my credentials are wrong, still clientID, clientSecret and API Key are valid; I doubt the 2 last params of the 2legged authenticater, is this correct?
var provider = new NativeApplicationClient(GoogleAuthenticationServer.Description);
provider.ClientIdentifier = ClientCredentials.ClientID;
provider.ClientSecret = ClientCredentials.ClientSecret;
var authenticator =
new OAuth2LeggedAuthenticator(ClientCredentials.ClientID, ClientCredentials.ClientSecret, "myworkusername", "workdomain.com");
Google.Apis.Calendar.v3.CalendarService service = new Google.Apis.Calendar.v3.CalendarService(authenticator);
service.Key = ClientCredentials.ApiKey;
var result = service.CalendarList.List().Fetch();
Assert.IsTrue(result.Items.Count > 0);
NB: At the time of writing you can only used 2-legged authentication with Google Apps for Business/Eduction, this won't work on personal accounts as there's no way to get an OAuth 1.0 key/secret pair, you will have to use online authentication at least once (but you can use the out-of-browser option so you don't have to create a dedicated page).
Your code is correct apart from you don't need the first three lines relating to the NativeApplicationClient. This is most likely failing because you haven't properly set the OAuth keys, this causes 401s.
The other thing that causes 401s is using "matt#example.com" instead of "matt" as the username, the username is without including your domain.
To setup OAuth follow the instructions in this article from Google.
The most important parts to note are "Allow access to all APIs" must be unchecked and you have to individually grant access to all the APIs. If this hasn't been done you will get a 401 Invalid Credentials error. You then also need to turn those services on in the api console. If the api console step hasn't been done you will get a different error of 403 Daily Limit Exceeded.
This will cause you problems if you were previously relying on the "Allow access to all APIs" to use various services, you will have to grant them all individually as far as I understand it to use the v3 APIs. This seems to have been confirmed by google (4th reply by Nicolas Garnier) and is supposedly a bug, but that is an old post so it looks as if it's here to stay.
For reference once this has been done, this code will work, which in essence is the same as yours:
var auth = new OAuth2LeggedAuthenticator(domainName, consumerSecret, usernameWithoutDomain, domainName); //domainName is presently used as the OAuth ConsumerKey for Google's 2legged OAuth
var service = new CalendarService(auth);
service.Key = serviceKey;
var results = service.CalendarList.List().Fetch();
Console.WriteLine(results.Items.Count);
So in summary:
In Google Apps "Manage this Domain" > "Advanced Tools"
Using "Manage OAuth domain key" enable key, generate secret, uncheck "Allow access to all APIs".
Using "Manage third party OAuth Client access" enable the APIs you want access to using your domain as "Client Name" and the APIs you want to access e.g. "http://www.google.com/calendar/feeds/" for the calendar.
Then finally create a project in the API console, use the APIKey as the serviceKey in the above example and turn on the APIs you need to access.
I am answering this as I kept hitting this question when I was trying to find out why my code was constantly returning 401s. Hope this helps someone as the Google instructions are awful and scattered all over the place at the moment.

Categories