Is it possible to use gRPC Google APIs from Rust today? - google-api

There is a prehistoric example where protobuf crate is used with reqwest HTTP client to call one of the few whitelisted services that can used with permanent API keys instead of OAuth / service accounts. This doesn't work with most of the googleapis zoo.
Furthermore, using OAuth with gRPC doesn't seem as simple as attaching a Authorization: BearerSIGNED_JWT to the request. As seen in all the Authenticate with Google examples on grpc.io, this requires calling the grpc_composite_channel_credentials_create function in the C core library.
It looks like pingcap/grpc-rs doesn't wrap or use this function. However, it does mention Google OAuth suddenly.
What is the truth?

Still not sure what exactly the authorization constitutes on the wire, but
google_default_credentials successfully allows me to call Google APIs.
In fact, it not only works with GOOGLE_APPLICATION_CREDENTIALS env var pointing to the service account key .json but even magically uses my signed in google account from gcloud cli.
For example with pingcap/grpc-rs aka grpcio = "0.5.0-alpha.3" all it took was
let env = Arc::from(EnvBuilder::new().build());
let creds = ChannelCredentials::google_default_credentials().unwrap();
let ch = ChannelBuilder::new(env).secure_connect("firestore.googleapis.com", creds);
let client = FirestoreClient::new(ch);

Related

Accessing google calendar API with pure HTTP calls

I was able to access the API by generating API key and using a Google web client. Now, I like to access the API using a simple HTTP client like curl without using any client libraries supplied by Google, I know this should be theoretically possible since those libraries have to use HTTP at their core. Has anyone done it? if so can someone point me in the right direction?
This is possible! Some applications use their own backend services to make calls on Google API (without Client Lib then).
You need to get some things, like on client calls -> clientID, authorization etc...
Get more informations about CURL on Google here : https://developers.google.com/gdata/articles/using_cURL
Concerning the OAuth 2.0 with a backend service : https://developers.google.com/api-client-library/php/auth/web-app
OAuth2 or Single Sign On will allow you to access to Calendar.

uploading fails to google cloud storage using rest API POST

I'm trying to figure out how to upload a file to google cloud storage using rest API , i don't want to use the client Library .
i read the documents but it was not helpful for a beginner in this flied ,
anyone can give me a step-by-step how to do this ? and how the URL/header/body format should look like , if also can give me an examples that would be very helpful .
If you're not going to use any of the helper libraries and are also a beginner, the hardest part of implementing an upload to GCS will likely be authenticating yourself. Let's ignore that for now.
The simplest way to upload an object to Google Cloud Storage is to make an HTTPS call to storage.googleapis.com that looks like this:
PUT /your-bucket-name/your-object.txt HTTP/1.1
Authorization: (YOUR ACCESS TOKEN GOES HERE)
Content-Length: 20
Content-Type: text/plain-or-whatever; charset=utf-8
Host: storage.googleapis.com
User-Agent: YourApplication/1.0
This is a test file
That will upload a file named "your-object.txt" of type "text/plain-or-whatever" to the bucket "your-bucket-name", with the contents "This is a test file."
If your bucket allows anonymous users to upload files (you shouldn't do that), then just don't include the Authorization line and you're done.
Now, since you really don't want to use any client libraries, and that presumably includes Google's OAuth libraries, you're going to need to implement authorization yourself, so let me give you an overview.
First, though, if you want to try this out immediately, install the "gcloud" tool, login with "gcloud auth login", and the print an access token with gcloud auth print-access-token. Then use the Authorization header Authorization: Bearer whatever.gcloudprintedout. That way you can be off and running with GCS quickly. But the token will only last an hour or so, so you'll need to implement OAuth for real.
Google Cloud APIs use OAuth to handle their requests, which is a powerful but not simple auth mechanism. There's extensive documentation on how OAuth with Google works: https://developers.google.com/identity/protocols/OAuth2
And there's also more general information on authorizing Google Cloud requests: https://cloud.google.com/docs/authentication
If you are running your application on a Google Cloud technology like App Engine or GCE, auth will be somewhat easier, but I will assume you're running this on your own machine. I will further assume that you want your application to have its own identity, rather than simply having you log in as part of the upload flow. For such a case, you'll need a service account, which will have an associated private key.
The basic flow for a service account is that you will create a JWT request for access credentials, then cryptographically sign that request with your private key, then send that signed request to Google. It will return you a token that may then be passed to your actual upload request later. You can keep using that token until it expires, at which time you'll need to build another JWT request to request another token.
Again, the client libraries entirely take care of this whole process for you. I am describing the approach of implementing everything exclusively on your own.
You can find the same example here:
https://stackoverflow.com/a/53955058/4345389
in which I already explained how to upload a file to google cloud storage using rest API.
Thanks

Correct way to use a Google Apps Marketplace service account to connect to Gmail IMAP and other services

One of the features of our Marketplace app makes use of accessing the user's Gmail account via IMAP. We are using the google-api-java-client and google-oauth-java-client libraries and code similar to this example in the java-gmail-imap project as follows:
GoogleCredential credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(SERVICE_ACCOUNT_ID)
.setServiceAccountScopes(Arrays.asList(GMAIL_SCOPE))
.setServiceAccountPrivateKey(PRIVATE_KEY)
.setServiceAccountUser(emailAddress)
.build();
credential.refreshToken();
We are then using code based on the examples at https://code.google.com/p/google-mail-oauth2-tools to make the IMAP connection e.g.
IMAPStore imapStore = OAuth2Authenticator.connectToImap("imap.googlemail.com",
993, emailAddress, credential.getAccessToken(), false);
The majority of the time this appears to work correctly, however we are seeing that for a small but significant number of requests the call to Google made by refreshToken() fails with an HTTP 500 error and an HTML response where the JSON would normally be returned e.g.
<p class="large"><b>500.</b> <ins>That's an error.</ins></p>
<p class="large">The server could not process your request.
<ins>That's all we know.</ins></p>
We were advised by a developer advocate at Google that we refresh tokens are not supported for service accounts and we should be using an approach like in this example.
However, it seems like without the call to refreshToken then accessToken is not populated on the credential object and then this results in a NullPointerException when we call OAuth2Authenticator.connectToImap
From the source for GoogleCredential it did seem like executeRefreshToken() is overridden to handle service accounts i.e. instead of performing a refresh it simply requests a new token, and then this bit of code in Credential then handles populating the access token:
TokenResponse tokenResponse = executeRefreshToken();
if (tokenResponse != null) {
setFromTokenResponse(tokenResponse); ....
We were unsure whether we need to enclose our call to refreshToken() in a retry loop to work around the intermittent 500 errors or whether we need to make other changes to our code to follow the recommended approach for this scenario.
Can anyone advise?
I use the java-gmail-imap example code in production (but it is only used to display an inbox in our University portal, there isn't much interaction that would require me to reuse the same refresh token for instance).
Depending on your usage, I wonder if in your case some kind of throttling is coming into play (I've read in places that Gmail can occasionally throttle access).
Elsewhere I've seen Google APIs talk about making retries using an exponential backoff algorithm.
You have to be a little careful when comparing the usage of OAuth 2.0 with the other Google Service APIs and Gmail. Gmail is special in that it uses XOAUTH2. That said I've seen other Google API's that appear to need the refreshToken call. The documentation is a bit unclear and says things like "Refresh the access token, if necessary" (as you say it doesn't seem to work without this step but I haven't done any experimentation with re-using refresh tokens via credential.setRefreshToken(String refreshToken)).
I'd be interested to hear how you get on.

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.

Using Ruby to authenticate to Azure (HTTP Header authentication)?

Since the Google Search API has been deprecated, I'd like to use the Bing Search API (now a Windows Azure API) in my Ruby apps.
However, Azure has a strange authentication pattern where you build a query URI, paste it into a browser, pass the key into the password box of the standard HTTP authentication box, and make POST to see the results. I assume this generates a signature and passes it in the header somehow. I'd like to do the complete process in Ruby and skip the browser portion if possible.
I found one example in the source of an obscure Windows Azure storage gem, but I can't figure out how tthey're building the signature and make the call. Is there a simple way to do basic HTTP auth in Ruby?
I went ahead and used Faraday's built in basic authentication scheme like so:
connection = Faraday.new "http://api.something.com/1/dudez"
connection.basic_auth "username" "password"
connection.get
I want to recommend the RestClient gem for this. I've used it with great success for GET'ing and POST'ing across domains. If you really have to act like a browser to implement the API, you can always use Capybara.
I'm sorry I haven't tried the Azure API myself, or I would give an example. :)
I recall doing this previously with another Azure API but am unable to find the code.
Look here for the details of the signature process:
http://msdn.microsoft.com/en-us/library/windowsazure/ee395415.aspx
I'm unable to find immediately if the Azure API uses the SharedSignature method
The way to sign a request to Windows Azure blob storage thru the REST API is described here: http://msdn.microsoft.com/en-us/library/dd179428.aspx.
Basically, you don't authenticate by simply adding some credentials in a HTTP header, you have to sign your request with the secret key that is associated to your storage account.

Resources