I have an application that accesses Google APIs out of a Chrome extension via the workflow outlined here.
Chrome Extensions OAuth Tutorial
The basics of the workflow are to initialize the OAuth flow
var oauth = ChromeExOAuth.initBackgroundPage({
'request_url': 'https://www.google.com/accounts/OAuthGetRequestToken',
'authorize_url': 'https://www.google.com/accounts/OAuthAuthorizeToken',
'access_url': 'https://www.google.com/accounts/OAuthGetAccessToken',
'consumer_key': '{MY_CLIENT_ID}',
'consumer_secret': '{MY_CLIENT_SECRET}',
'scope': 'https://www.google.com/m8/feeds/ https://apps-apis.google.com/a/feeds/emailsettings/2.0/ https://mail.google.com/',
'app_name': 'Gmail Plugin',
'callback_page': 'src/google-oauth/chrome_ex_oauth.html'
});
Upon installing the extension, the user is taken to dialog page to authenticate and agree to the scopes I ask for. From here I infer that my consumer key and secret are OK. I have allowed access to the GMail, Contacts, and Admin SDK in the Google Developers console.
Prior to this I had requests working with the Contacts API and Admin SDK API. I'm now trying to add some features that utilize the Gmail REST API.
The next step in setting up a request is to make a request from the background page.
function getSentEmails() {
var emailCollection;
var url = "https://www.googleapis.com/gmail/v1/users/me/messages";
var request = {
'method': 'GET',
'parameters': {
'labelIds': 'SENT'
}
};
var callback = function(response, xhr) {
emailCollection = JSON.parse(response);
console.dir(emailCollection);
}
oauth.sendSignedRequest(url, callback, request);
};
The way the signed requests work is to call a method to complete the next step of the OAuth dance,
oauth.authorize(function() {
getSentEmails();
});
This results in a 403 Forbidden every time. I seem to have no issue accessing the other APIs I mentioned though this OAuth flow. I've allowed the scope in my manifest.json
manifest.json
"permissions": [
"tabs",
"storage",
"https://mail.google.com/*",
"https://www.google.com/m8/feeds/*",
"https://apps-apis.google.com/a/feeds/emailsettings/2.0/*",
"https://www.googleapis.com/gmail/v1/users/*",
"https://www.googleapis.com/auth/gmail.modify/*",
"https://www.googleapis.com/auth/gmail.compose/*",
"https://www.googleapis.com/auth/gmail.readonly/*",
"https://www.google.com/accounts/OAuthGetRequestToken",
"https://www.google.com/accounts/OAuthAuthorizeToken",
"https://www.google.com/accounts/OAuthGetAccessToken"
]
I tried an alternate method of building the HTTP request as outlined in the link above.
function stringify(parameters) {
var params = [];
for(var p in parameters) {
params.push(encodeURIComponent(p) + '=' +
encodeURIComponent(parameters[p]));
}
return params.join('&');
};
function xhrGetSentEmails() {
var method = 'GET';
var url = 'https://www.googleapis.com/gmail/v1/users/me/messages';
var params = {'labelIds': 'SENT'};
var callback = function(resp, xhr) {
console.log(resp);
}
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function(data) {
callback(xhr, data);
};
xhr.open(method, url + '?' + stringify(params), true);
xhr.setRequestHeader('Authorization', oauth.getAuthorizationHeader(url, method, params));
xhr.send();
}
I get the same 403 doing this.
I believe I'm authenticating properly though, because if I change
xhr.setRequestHeader('Authorization', oauth.getAuthorizationHeader(url, method, params));
to
xhr.setRequestHeader('Authorization','foo' + oauth.getAuthorizationHeader(url, method, params));
I get a 401 Unauthorized instead.
Again, no trouble accessing the other APIs I mentioned.
Any input would be much appreciated.
This question is probably fairly obscure, so I'll share how I ended up resolving it.
I moved my chrome extensions OAuth 2.0 workflow to the newer (since Chrome 29) chrome.identity setup for apps and extensions.
Detailed instructions for setting up OAuth 2.0 for an extension are here.
Chrome Identity API User Authentication
Now I can use
And none of my HTTP requests come up forbidden (403) anymore.
Hope this is helpful to extension builders out there!