Retrieve blog feeds using google oauth 2.0 and scribe - google-api

I used scribe to connect to google using oAuth 2.0 and successfully got the access token. When i am trying to get the blogs i always get the below error
Unauthorized
Must authenticate to use 'default' user
Below is the code snippet
GoogleOAuthParameters oauthParameters = new GoogleOAuthParameters();
oauthParameters.setOAuthConsumerKey(CONSUMER_KEY);
oauthParameters.setOAuthConsumerSecret(CONSUMER_SECRET_KEY);
oauthParameters.setScope("http://www.blogger.com/feeds");
oauthParameters.setOAuthToken(ACCESS_TOKEN);
oauthParameters.setOAuthTokenSecret(ACCESS_TOKEN_SECRET); // this is null
BloggerService myService = new BloggerService("blogger");
try {
myService.setOAuthCredentials(oauthParameters, new OAuthHmacSha1Signer());
} catch (OAuthException e) {
e.printStackTrace();
}
final URL feedUrl = new URL("http://www.blogger.com/feeds/default/blogs");
Query query = new Query(feedUrl);
Feed resultFeed = myService.getFeed(query, Feed.class);
Not able to get the feeds here and displays the Unauthorized error as mentioned above.

Jason has answered your question, I believe.
You do not want to use the library code above to access blogger. Use the new API, and use OAuth2 https://developers.google.com/blogger/docs/3.0/using#auth
I'm not sure what scribe is, but with OAuth2, you need to indicate what type of application you're building, It might be one that runs from a web server, or an installed application. What's you've determined that, you can follow the appropriate documentation for the java client library linked to above to get the access token and retrieve the data.

Related

Google Admin Setttings API connection for .NET

I've been working with the Google directory API for quite some time now.
However, I need to update SSO settings in the admin settings section of Google. Yes, they say it will be deprecated at some point, but according to a google employee, it's going to be a while before a new API is available and then the old one will be removed.
First, if there is a NUGET package out there, please let me know. I can't seem to find anything that works with the admin settings API: https://developers.google.com/admin-sdk/admin-settings/
My first attempt is getting the SSO settings in Google.
I can use postman to pull this information so I know the API works.
However, I'm running into two issues:
How can I authenticate using the service certificate that I use in the apis.google.directory class?
Anticipating, how do I request access to the admin settings? In directory API, I have the scope enum to select from. If I'm making a manual connection to the API I assume I'll need to call this by hand?
Code
var certificate = new X509Certificate2(serviceAccountCertPath,
serviceAccountCertPassword,
X509KeyStorageFlags.Exportable);
// below the scopes are going to get in my way, right? What is the scope process I need to do for this manually?
credential = new ServiceAccountCredential(
new ServiceAccountCredential.Initializer(serviceAccountEmail)
{
Scopes = new[] { DirectoryService.Scope.AdminDirectoryUser,
DirectoryService.Scope.AdminDirectoryGroup,
DirectoryService.Scope.AdminDirectoryOrgunit},
User = _szAdminEmail
}.FromCertificate(certificate));
// I'm not seeing anyway to call the above credentials
using (HttpClient client = new HttpClient())
{
// client.DefaultRequestHeaders.Add("Authorization", "Bearer " + accessToken);
client.BaseAddress = new Uri(#"https://apps-apis.google.com/a/feeds/domain/2.0/[mydomain]/sso/general");
client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
//client.DefaultRequestHeaders.
HttpResponseMessage response = client.GetAsync("api/Values").Result; // Blocking call!
var products = response.Content.ReadAsStringAsync().Result;
return products.ToString();
}
The admin settings API does not appear to support service account authentication you will need to use Oauth2. Admin Settings Oauth
Your not going to be able to use it very easily using the Google .net client library as that library was designed for use with the Google discovery apis. I dont think the Admin Settings API is a discovery api. You might be able to use the old gdata library for it I am not sure if one exists I have not been able to find it on nuget. If you do find it the old gdata library doesn't support oauth2 which means that you will need to use the new library for that and plug in the gdata library after.
I have only done this before using the Google contacts api I have a tutorial here on how i did it it may help you here
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);
If you cant find the gdata library for it you may have better luck just using the library for authencation and then code the rest of the calls yourself. It returns xml not json.

Spring Boot Facebook Starter how to login several users? how to obtain accessToken or providerId

I've followed several tutorials and got really close to nowhere understanding spring integration with facebook API, having strong knowledge in other spring modules I found myself surprised...
Every tutorial uses:
public <A> Connection<A> findPrimaryConnection(Class<A> apiType) {
String providerId = getProviderId(apiType);
if (connections.containsKey(providerId)) {
return (Connection<A>) connections.get(providerId).get(0);
}
return null;
}
As this returns me first connection every time?
I've tried connecting to my app from two different machines and both requests return same facebook profile..
So as usual I went to investigate api what is required to obtain user-specific-connection when stumbled upon method which does what I want:
public <A> Connection<A> getConnection(Class<A> apiType, String providerUserId) {
return (Connection<A>) getConnection(new ConnectionKey(getProviderId(apiType), providerUserId));
}
Ok, so I went trying to figure out how to obtain providerId... I fail, many questions such as:
How to get providerUserId by providerId, accessToken and secret? (Spring Social)
don't make it clearer.
It seems I am not the first to fail understand philosophy of Spring integration with facebook. As to many of us it is obvious that we want to use advanced features where every user needs to have it's own connection to facebook with its own data returned and possibility to login via facebook.
Could you kindly please explain how to get connection/facebook object per user as I am very disoriented by the implementation of this spring module.
Does Spring Social Facebook even support concurrent users logged in to Facebook? It all feels to me like building beautiful Eiffel tower without any doors.
I didn't use Spring Security integration as I felt ConnectController approach will provide more control, but apparently it does not and has biased assumptions. Now looking at Spring Security integration.
I tried thi myself some month ago and found it also very confusing.
For me it looked like as if all this spring-social stuff is trying to identify a user of your web-app interactively using OAuth.
What I was looking for was connecting my spring application to facebook to e.g. post something there.
For this purpose you can use the FacebookTemplate and forget about the provider etc. :
public String postOnFacebook(Machine machine, String url) {
Facebook facebook = new FacebookTemplate(accessToken);
FacebookLink link = createLink(machine, url);
// the first parm is the title on top of the message
String message = facebook.feedOperations().postLink("message", link);
return message;
}
You need an accessToken for the facebook account, which is a different story. Finally this helped :
http://www.slickremix.com/facebook-60-day-user-access-token-generator/

Google Domain Shared Contacts API Using OAuth 2.0 for Server to Server Applications - Credential params

I'm trying to get the "Google Domain Shared Contacts API" described here:
https://developers.google.com/admin-sdk/domain-shared-contacts/
Working using "OAuth 2.0 for Server to Server Applications" described here:
https://developers.google.com/accounts/docs/OAuth2ServiceAccount
The recommendation from the OAuth page is to use the provided Google client library... I'm using the Java library. But the Shared-Contacts API doesn't have an example that uses this library, and I'm having trouble figuring out how to use the library with the Shared-Contacts API.
I am able to make the example for the OAuth to work for me... It uses Google Cloud Storage. Here's a snippet of the code:
String STORAGE_SCOPE = "https://www.googleapis.com/auth/devstorage.read_write";
try {
try {
httpTransport = GoogleNetHttpTransport.newTrustedTransport();
String p12Content = Files.readFirstLine(new File(keyFile), Charset.defaultCharset());
// Build service account credential.
GoogleCredential credential = new GoogleCredential.Builder().setTransport(httpTransport)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(SERVICE_ACCOUNT_EMAIL)
.setServiceAccountScopes(Collections.singleton(STORAGE_SCOPE))
.setServiceAccountPrivateKeyFromP12File(new File(keyFile))
.build();
// Set up and execute Google Cloud Storage request.
String URI;
URI = "https://storage.googleapis.com/" + BUCKET_NAME;
HttpRequestFactory requestFactory = httpTransport.createRequestFactory(credential);
GenericUrl url = new GenericUrl(URI);
HttpRequest request = requestFactory.buildGetRequest(url);
HttpResponse response = request.execute();
content = response.parseAsString();
} catch (IOException e) {
System.err.println(e.getMessage());
}
} catch (Throwable t) {
t.printStackTrace();
}
return content;
It's a request to get a listing of what's in a certain bucket on GCS. It calls a specific URL using the Credentials object, where the Credentials object does the work of the OAuth, using a key file I downloaded. There's other steps involved for getting it to work (setting the service account email, etc), which I did. It returns an xml string containing what is inside the bucket, and it works fine for me.
I then tried changing the URI to this string:
URI = "https://www.google.com/m8/feeds/contacts/myGoogleAppsDomain.com/full";
and I changed the STORAGE_SCOPE variable to be this string:
STORAGE_SCOPE = "http://www.google.com/m8/feeds/";
Hoping it would then return an xml-string of the shared-contacts. But instead, it returns this error:
403 Cannot request contacts belonging to another domain
I believe I'm getting this error because I'm not specifying the "hd" parameter when I do the authentication request... However, I'm unsure how I can specify the "hd" parameter using the GoogleCredential object (or the other parameters, except for "scope")... Can someone help me with that?
I think the issue here is that you are not specifying which user you want to impersonate in the domain (and you haven't configured the security settings in your domain to authorize the service account to impersonate users in the domain).
The doubleclick API auth documentation has good examples on how to do this. You can use their sample and replace the scopes and API endpoint:
https://developers.google.com/doubleclick-publishers/docs/service_accounts#benefits

How to use 2 legged oauth on Google Admin Directory API

I am trying to write code to get all user accounts in our Google Apps domain using Google Admin Directory API with 2 Legged OAuth. Unfortunately, I can hardly find any documents or sample code for directory API. I tried the code below:
AdminService adminService = new AdminService();
Google.Apis.Authentication.OAuth2LeggedAuthenticator authenticator= new Google.Apis.Authentication.OAuth2LeggedAuthenticator(mydomainName, domainConsumerSecret, adminId, mydomainName);
UsersResource usrRes = new UsersResource(adminService, authenticator);
UsersResource.ListRequest listReq = usrRes.List();
Google.Apis.Admin.directory_v1.Data.Users allUsers = listReq .Fetch();
foreach (Google.Apis.Admin.directory_v1.Data.User usr in allUsers.UsersValue)
{ ... }
But I got the 401 unauthorized error.
Then I tried the low level way using the old GData Lib.
Google.GData.Client.OAuth2LeggedAuthenticator authenticator = new OAuth2LeggedAuthenticator("MyAPP", mydomainName, domainConsumerSecret,adminId, mydomainName, "HMAC-SHA1");
HttpWebRequest request = authenticator.CreateHttpWebRequest("GET", new Uri("https://www.googleapis.com/admin/directory/v1/users?domain=mydomain.com"));
HttpWebResponse response = request.GetResponse() as HttpWebResponse;
the above code got the same 401 error.
Based on the source code of Directory API, I think 2LO is supported. However, I just cannot make it work. Anyone can help to point out my problem? Thanks.
Another question: Is the userid (xoauth_requestor_id parameter) necessary for 2LO directory API request? I know this parameter is required for other APIs when using 2LO, but not clear if it is required for the Directory and Provisioning API.
BTW: I would like to construct the 2LO HTTP requests from scratch without using any lib, but I haven't started this yet. I need to make sure that 2LO works on the Directory API requests.
If anyone else stumbles across this, Google deprecated the Provisioning API about a month before the original post. I recently had the same problem when trying to authorize API access to my Google Apps domain using the Admin Directory API. After finally figuring it out, I decided to document it, and I'm actually in the midst of putting together a series on how to make some sense out of Google Apps Directory API and OAuth 2.0... Keep in mind that Google now strongly encourages the use of OAuth 2.0, so 2LO is a thing of the past, and the above "fix" may no longer be relevant.
In case folks don't want to click the link, I would recommend using Google's API Explorer to find out how a successful POST/GET request is formulated using specific APIs. This saved me heaps of time. Also, be forewarned, if you're trying to use the directory.users.list API and have thousands of accounts in the domain, it will take a very long time to retrieve the users. I would suggest starting with the directory.users.get API to retrieve a specific user and check out what a successful API request/response looks like.

Invalid grant when accessing Google API

I'm trying to invoke any of the Google API using "Service account" authorization access. I have downloaded ".pk2" file and activated "URL Shortener API" in Services tab of Google API console. Whenever I try to invoke any API (URL shortener or Adsense). I've got following exception -
com.google.api.client.auth.oauth2.TokenResponseException: 400 Bad Request
{
"error" : "invalid_grant"
}
at com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:105)
at com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:303)
at com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:323)
at com.google.api.client.googleapis.auth.oauth2.GoogleCredential.executeRefreshToken(GoogleCredential.java:345)
at com.google.api.client.auth.oauth2.Credential.refreshToken(Credential.java:526)
at com.google.api.client.auth.oauth2.Credential.intercept(Credential.java:287)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:836)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:412)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:345)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:463)
Below is code snippet -
HttpTransport HTTP_TRANSPORT = new NetHttpTransport();
JsonFactory JSON_FACTORY = new JacksonFactory();
File privateKey = new File(ReportAdsense.class.getResource("mykey.p12").toURI());
GoogleCredential credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId("my_valid_account_id#developer.gserviceaccount.com")
.setServiceAccountScopes(UrlshortenerScopes.URLSHORTENER)
.setServiceAccountPrivateKeyFromP12File(privateKey)
.build();
Urlshortener service = new Urlshortener.Builder(new NetHttpTransport(), JSON_FACTORY, null).setHttpRequestInitializer(credential).build();
UrlHistory history = service.url().list().execute();
First of all "Service account" will not work for Adsense, since it requires user authorization. Hence for Adsense you should use Oauth 2.0. When you are authorized first time using URL https://accounts.google.com/o/oauth2/token, copy-paste and hardcode your refresh token. Than you can use it to get access token, specify client_id, client_secret and your refresh_token to get new access token. Now access token can be used in your application.
Regarding your error, I have faced with similar issue and spent plenty of time to resolve it. First of all, make sure that you are using valid ServiceAccountId - it should point to email which finishes with "developer.gserviceaccount.com". Make sure, that you specified account scopes and activated services in Google Console API.
I fixed this issue by synchronizing system clock in my machine.
There are a lot of topics with similar error without answers. Even more, some people says, that sometimes it works, sometimes it returns invalid grant. It could work on one machine and fail on another. I don't know if it is system clock issue, but I would avoid using Service Account API, since looks like there are bugs and support would not help you

Resources