Sheets API from Google App Engine - google-app-engine

I am trying to access my own sheets from Google App Engine. I followed the following tutorial
https://developers.google.com/sheets/quickstart/java
this code works fine as long as the code does not run inside the Google App Engine. The following line of code throws an exception (your are not allowed to use sockets)
Credential credential = new AuthorizationCodeInstalledApp(
flow, new LocalServerReceiver()).authorize("user");
So as you can I see, I have problems with the authorization between my app engine and my google sheets.
Has someone a working example how I can access the Google Sheets API from App Engine or can give me an example how the OAuth2 Autorization between App Engine and any other Google Service will work?
Regards
Michael

I think Google App Engine has guides with regard to connecting to your App like
Issuing HTTP(S) Requests:
To issue an outbound HTTP request, use java.net.URLConnection. App Engine implements the methods defined in this abstract class by using the URL Fetch API.
The following snippet demonstrates how to perform a basic HTTP GET request. The application creates a new URL object, then calls the object's openStream() method to retrieve the content at that URL:
URL url = new URL("http://api.icndb.com/jokes/random");
BufferedReader reader = new BufferedReader(new InputStreamReader(url.openStream()));
StringBuffer json = new StringBuffer();
String line;
while ((line = reader.readLine()) != null) {
json.append(line);
}
reader.close();
Since you received an error with regard to sockets, App Engine has a guide for that too:
Overview of Sockets API for Java
-Sockets are available only for paid apps.
-You cannot create a listen socket; you can only create outbound sockets.
-FTP is not supported.
-java.net.URL is still configured to use the URL Fetch API; there is currently no way around this.
-InetAddress.isReachable is a no-op, etc
Overview of App Identity API for Java
The App Identity API lets an application discover its application ID (also called the project ID). Using the ID, an App Engine application can assert its identity to other App Engine Apps, Google APIs, and third-party applications and services. The application ID can also be used to generate a URL or email address, or to make a run-time decision.

Related

AppEngine Multi backends keeping autoscaling

I have an AppEngine webapp with a JavaScript tracker. I want it to make HTTP calls to a collector (which is a REST API that saves data into BigQuery) without making an entire app-to-app authentication process with OAuth/JWT or whatever.
According to this thread it's not possible for AppEngine to use a REST API located on a compute engine instance with an internal IP.
In addition, it seems that it's not possible to use GAE multibackends feature since it loses autoscaling and I really need this feature.
What is the proper Google Cloud way to achieve this ?
I presume that the collector is running on compute engine and the problem is how to verify that requests to the collector are genuine requests from the AppEngine service since the only way for the AppEngine app to reach the collector is via a public IP.
AppEngine has an Identity API for an AppEngine to assert to a third party service that a request is genuine. A more detailed (and less contrived) example of how to use this is discussed here. The code link no longer works but the code is available here.
This specific sequence from the last article seems to be more or less what you need:
Client App generates a signed blob by calling app_identity.signForApp(string_blob)
Client App exposes its public certificates on a public endpoint, for example clientapp.com/certs. In the demos below we use a trivial Json format to expose certificates, something like: {"cert1":"x509 cert pem", "cert2":"x509 cert pem 2"...}.
Client App sends a request to API App along with the signed blob and the URL that contains Client App's public certificates.
API App fetches Client App's public certificates from that URL
API App verifies the signature of the signed blob. The API App might perform other business logic like checking if the Client App (as identified by the URL of its public certificates) is on an access control list.
Both apps should agree on the same 'signed blob' format. In our demo we use JWT as the signed token format. The detailed spec can be found at http://self-issued.info/

Asserting identity to Google APIs with App Engine development server

I have a Golang app running on App Engine and I would like to call the Analytics API to process some metrics. Both on App Engine and on the development server.
This page describes the overall procedure using a service account for server-to-server communication and getting an access token using OAuth2. I would like to avoid doing this myself so I found Google APIs for Go and the following that describes how to do it for App Engine.
I have added the App Engine app's service account email to Google Analytics for read access.
I have played around with queries using the Query Explorer and that works great. I have even used the API Query URI from here that includes the proper access token and that works fine. That works fine with cURL or calling it through urlfetch on App Engine.
What I need is to get hold of an access token automatically on App Engine and also while using the development server.
In here is an example for URL shortener which a have modified to use the Analytics API instead.
client := http.Client{
Transport: &oauth2.Transport{
Source: google.AppEngineTokenSource(c, analytics.AnalyticsScope),
Base: &urlfetch.Transport{Context: c},
},
}
svc, err := analytics.New(&client)
if err != nil {
return nil, err
}
data, err := svc.Data.Ga.Get("...")
The response in the development server is 401 Invalid Credentials, authError.
Is this supposed to work like this or am I missing something?
UPDATE
So, the problem is half solved. It works fine now using the development server when I pass in the service account's email and .pem file. However, that very same service account that is in App Engine does not work with the above code!
googleapi: Error 403: User does not have any Google Analytics account., insufficientPermissions
User should be the service account that I already successfully use on the development server, so I don't really understand this problem. It's the exact same code on App Engine and on the development server as well.
Google Analytics is set up to have read access and I use the read-only API. And it already works on the development server so that should be fine.
What might be different that is the issue?
It is possible to provide the development server with the necessary information at start like here.
$ dev_appserver.py --appidentity_email_address email --appidentity_private_key_path file.pem
And for App Engine you need to not use this Service Account but the one with the app name:
app_name#appspot.gserviceaccount.com

Consuming Endpoints APIs elsewhere in App engine

I have programmed and tested my API using Proto-datastore and now I'm ready to do something more with it.
As well as having generated the client library to allow apps to communicate with the API, I'm looking to create a web-based 'Dashboard' for the service (which would be based on the guestbook example). This would be also be built and hosted on the same App-Engine project. But I have no idea how to go about consuming the API in App Engine.
Importing the API and just calling the #Model.method() decorated functions won't work. I have found this but I was wondering if there's anything in proto-datastore I've missed that would let me do this?
The way I'm doing it is to access the endpoint, the same way I would access any other Discovery-based API hosted somewhere else, by using use the Google APIs Client Library for Python which is compatible with endpoints.
Normally you would build a client for one of the Google APIs using service = build(api, version, http=http) for example service = build("plus", "v1", http=http) to build a client to access to Google+ API.
For using the library for your endpoint you would use:
service = build("your_api", "your_api_version", http=http,
discoveryServiceUrl=("https://yourapp.appspot.com/_ah/api/discovery/v1/"
"apis/{api}/{apiVersion}/rest"))
You can then access your API with
result = service.resource().method([parameters]).execute()
Might not be the most optimal way, but it works like a charm.

OAuth: Starting a Google Compute Instance from within Google App Engine

I have a Google App Engine web app that runs the majority of my site. However, for certain functions, I need a linux machine. I would like my Google App Engine app to automatically spin-up a Google Compute Instance on certain events.
I understand that you can add Google Compute instances using the Compute Engine REST API. However, in order to access the Google Compute REST API, you need to get an access token using the OAuth2 authentication process.
How can I programmatically get an access token from within Google App Engine?
It seems that all of the authentication methods require a window to appear so you can type in your username and password, which is impractical from within Google App Engine.
Here is a complete example of using service accounts and App Engine cron tasks to stop instances after they've been running for a while:
(opposite of starting instances, but the authorization code will be the same)
https://github.com/GoogleCloudPlatform/compute-appengine-timeout-python
AppAssertionCredentials handles the access token using this code:
# Obtain App Engine AppAssertion credentials and authorize HTTP connection.
# https://developers.google.com/appengine/docs/python/appidentity/overview
credentials = AppAssertionCredentials(
scope='https://www.googleapis.com/auth/compute')
HTTP = credentials.authorize(httplib2.Http(memcache))
# Build object for the 'v1beta15' version of the GCE API.
# https://developers.google.com/compute/docs/reference/v1beta13/
compute = build('compute', 'v1beta15', http=HTTP)
You should be able to use the service account associated with your project to authenticate to the Compute Engine API and launch VMs.
Documentation on service accounts suggests that the following python code should fetch a service account token.
import httplib2
import discovery
from oauth2client.appengine import AppAssertionCredentials
...
credentials = AppAssertionCredentials(
scope='https://www.googleapis.com/auth/compute')
auth_http = credentials.authorize(httplib2.Http())
compute_service = discovery.build('compute', 'v1beta15', http=auth_http)
I'd thought that the Google I/O demo from this year where they built a video-sharing site was going to be available, but I don't see it on GitHub yet. There are a number of demos that use AppEngine to control GCE, but most of them seem to use the user's project and credentials, rather the app's own credentials.
Obviously, you probably don't want to spin up a VM on direct user input unless you've got a very large budget or some form of rate limiting in place, but it's quite helpful to spin up a VM now and then when you've got a lot of computation to do. (Transcoding, etc.)

How to specify URLs from glassware .net application

I would like specify Urls as in the below code in my .net glassware application
{
IList<string> imageUrls = new List<string>();
imageUrls.Add (what is it here?")
Iconact.ImageUrls = imageUrls;
}
Currently this url will be used at the time of rendering at the device (or mirror api?), so web app, this url makes sense, how about .net client as a glassware, i have my image as part of the glassware app and how to pass this image as a url?
Similar question how to specify subscription endpoint url in .net app?, it makes sense in web app, but i could not get the concept in .net client.
Thanks
Those assets need to be hosted somewhere: they don't necessarily need to be within your Glassware and can be hosted separately. However, those URLs need to be publicly accessible for the Glass client to fetch them.
You could host them on a free Google App Engine app that only purpose would be to serve those images.
Regarding the subscription endpoint: it needs to be publicly accessible and support POST requests over HTTPS.
One solution could be that creating WebServiceHost and adding service end point such as:
WebServiceHost host = new WebServiceHost(typeof(Service), new Uri("http://localhost:8000/"));
ServiceEndpoint ep = host.AddServiceEndpoint(typeof(IService), new WebHttpBinding(), "");
host.Open();
Will it work?
Finally what I did was that as in the Alain's answer having a Java Servlet app running in Google App Engine which receives all the notification and maintains all the user account logic and sends the notification to specific client(part of glassware app) in the local system thru XML over XMPP.

Resources