GAE HttpResponseException: 401

201 Views Asked by At

I am trying to access the DataStore of one app from another GAE project using Remote API. I am using the following code:

        String serverString = "http://example.com";//this should be the target appengine
    RemoteApiOptions options;
    if (serverString.equals("localhost")) {
        options = new RemoteApiOptions().server(serverString, 8080).useDevelopmentServerCredential();
    } else {
        options = new RemoteApiOptions().server(serverString, 80).useApplicationDefaultCredential();
    }
    RemoteApiInstaller installer = new RemoteApiInstaller();

    installer.install(options);
    datastore = DatastoreServiceFactory.getDatastoreService();

    try {
        results = datastore.get(KeyFactory.createKey("some key"));
    } catch (EntityNotFoundException e) {
        e.printStackTrace();
        return null;
    }

when I run this locally, i get a nullpointerexception at installer.install(options);. and when deployed, the error seen from error reporting on the appengine is :HttpResponseException: 401 You must be logged in as an administrator, or access from an approved application. That being said, I made a small java application with the follwing code:

String serverString = "http://example.com";//same string as the one used in the above code
    RemoteApiOptions options;
    if (serverString.equals("localhost")) {
        options = new RemoteApiOptions().server(serverString, 8080).useDevelopmentServerCredential();
    } else {
        options = new RemoteApiOptions().server(serverString, 80).useApplicationDefaultCredential();
    }
    RemoteApiInstaller installer = new RemoteApiInstaller();
    installer.install(options);
    try {
        DatastoreService ds = DatastoreServiceFactory.getDatastoreService();
        System.out.println("Key of new entity is " + ds.put(new Entity("Hello Remote API!")));

and this one works!! Hello Remote API entity is added.

1

There are 1 best solutions below

1
On

The reason it does not work when running on App Engine vs running locally has to do with the credentials that are being picked up. When running locally, it is likely using your own credentials (which has access to both projects); by contrast, when running on App Engine, you are likely picking up the App Engine default service account, which only has access to that App Engine project.

Try fixing this by opening the Cloud IAM section of Cloud Console for the project containing the Cloud Datastore that you wish to access. There, grant the appropriate level of access to the default App Engine service account that is being used by the other project.

If you don't want all App Engine services in the other project to have this kind of access, you might also consider, instead, generating a service account for this cross-project access that you grant the appropriate access to (rather than granting that access to the default App Engine service account). Then, in your code that calls the API, you would explicitly use that service account by calling the useServiceAccountCredential() method of RemoteApiOptions to ensure that the API requests that are issued use the specified service account rather than the default App Engine service account.