0

I have an app using the Google JS API to log in the user with oauth and then get info from their gmail acct, etc. The app works fine on the web but is having trouble with Trigger.io (Android and iOS builds). The script is loaded via

<script src="https://apis.google.com/js/client.js?onload=ginit"></script>

and the ginit function then calls the gapi client loaded by client.js:

if (!!gapi) {
    gapi.client.setApiKey(GoogleApp.apiKey);
}

On Android, gapi exists, but gapi.client somehow does not, causing an error.

On iOS, the library load works fine, but a subsequent call to gapi.auth.authorize (which may cause a new window to open) causes a Webview error: Error Domain=NSURLErrorDomain Code=-999 "The operation couldn’t be completed." I am using both the Child Browser and Cross-domain ajax modules, but of course have no way to change the way the Google library implements calls. I put in code to ignore the error per this and similar, but still the auth doesn't work:

try {
    gapi.auth.authorize({client_id: GoogleApp.clientId, scope: GoogleApp.scopes, response_type: 'token id_token', immediate: false, approval_prompt: 'force'}, gHandleAuthResult);
} catch (e) {
    if (e.indexOf('NSURLErrorCancelled') === -1) { // iOS error on cancelled window, ignore
        throw e;
    }
}  

Is there a better way to use the Google API from a Trigger.io app? Or an example of a Trigger.io app using the Google API?

My next issue will probably be with determining the js origin, which is already covered in another post but no answer yet. Thanks for any and all help!

Community
  • 1
  • 1
Adam
  • 63
  • 1
  • 6

1 Answers1

0

I did a detailed write up on how to get this working here:

Using OAuth 2.0 and the Google API Client Library for Javascript with Trigger.io Forge

Basically, the solution boils down to:

  1. Use the forge httpd module to work around the bug in Google's library loader which causes it to fail when run from pages with an originating protocol other than http:, https: or file:

  2. Use the forge tabs module to handle the OAuth flow rather than Google's gapi.auth.authorize function to avoid the issues caused by trying to open a popup browser window in a Hybrid app.

Example code:

function OAuthorize(options, success, error) {
    options.response_type = "token";
    var url = options.url;
    delete options.url;

    forge.tabs.openWithOptions({
        url: url + "?" + $.param(options),
        pattern: (options.redirect_uri + "*")
    }, function (data) {
        if (data.userCancelled) {
            return error("Login failed: User Cancelled");
        }

        // parse token from the url encoded response
        var token = {}, queryString = data.url.substring(data.url.indexOf("#") + 1),
        regex = /([^&=]+)=([^&]*)/g, m;
        while ((m = regex.exec(queryString))) {
            token[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
        }

        if (token.error) {
            return error("Login failed: " + token.error);
        }

        success(token);
    });
}

…and you can use it like this:

OAuthorize({
    url: "https://accounts.google.com/o/oauth2/auth",
    client_id: "your google client id",
    redirect_uri: "http://localhost/oauth2callback",
    scope: "https://www.googleapis.com/auth/plus.me"
}, function (token) {
    // set auth token for gapi 
    gapi.auth.setToken(token);

}, function (e) {
    forge.logging.error("Auth failed: " + e);
});