I am fairly new to developing chrome extensions, more specifically to the user authentication part in chrome extensions. I am following User Identity example from Google Developer docs.
The example works perfectly fine. I was able to generate the client id for the chrome app, add the scope for API's in my case Gmail API. And finally get the Auth Token by adding the identity
permission in manifest.json
as follows
"oauth2": {
"client_id": "MY CLIENT ID",
"scopes": [
".readonly",
".modify"
]
}
And my app.js is a content_script which has the following code.
chrome.identity.getAuthToken({ 'interactive': true }, function(token) {
/* With which I can use xhr requests to get data from Gmail API */
console.log('Access Token : '+token);
});
Now this token that I get gives me the result for the user with which I have logged into chrome. Meaning Let's say I have a UserA with email address [email protected] and I have used this log into the chrome browser.
Question
How do I get the associated accounts or the secondary accounts? For instance, let's say a UserB logs into Gmail from the chrome browser. Is it possible to access the Gmail API for that particular user who is currently logged in?
I have tried a couple of things here.
gapi.auth.authorize({
'client_id': CLIENT_ID,
'scope': SCOPES.join(' '),
'immediate': true
},
function(authResult){//do something});
In the above scenario, the client id and scopes are fetched from the manifest.json
using chrome.runtime.getManifest();
.
- This method uses the client.js from google api's and makes use of gapi variable.
- In this case, I get the access token for the user whom I generated the client id, not even the chrome application user.
- Furthermore, When I open an incognito mode and access this plugin, still I get the same user's access token.
Additional Note
I tried the same gapi.auth.authorize()
using a Web OAuth 2 Client Id. It works perfectly fine. I mean whenever this authorize is executed it fetches the current logged in user's data or it asks for a login where the user can log in and authenticate. How do I achieve the same thing in chrome extension? Kindly let me know if I am missing something here.
I am fairly new to developing chrome extensions, more specifically to the user authentication part in chrome extensions. I am following User Identity example from Google Developer docs.
The example works perfectly fine. I was able to generate the client id for the chrome app, add the scope for API's in my case Gmail API. And finally get the Auth Token by adding the identity
permission in manifest.json
as follows
"oauth2": {
"client_id": "MY CLIENT ID",
"scopes": [
"https://www.googleapis./auth/gmail.readonly",
"https://www.googleapis./auth/gmail.modify"
]
}
And my app.js is a content_script which has the following code.
chrome.identity.getAuthToken({ 'interactive': true }, function(token) {
/* With which I can use xhr requests to get data from Gmail API */
console.log('Access Token : '+token);
});
Now this token that I get gives me the result for the user with which I have logged into chrome. Meaning Let's say I have a UserA with email address [email protected] and I have used this log into the chrome browser.
Question
How do I get the associated accounts or the secondary accounts? For instance, let's say a UserB logs into Gmail from the chrome browser. Is it possible to access the Gmail API for that particular user who is currently logged in?
I have tried a couple of things here.
gapi.auth.authorize({
'client_id': CLIENT_ID,
'scope': SCOPES.join(' '),
'immediate': true
},
function(authResult){//do something});
In the above scenario, the client id and scopes are fetched from the manifest.json
using chrome.runtime.getManifest();
.
- This method uses the client.js from google api's and makes use of gapi variable.
- In this case, I get the access token for the user whom I generated the client id, not even the chrome application user.
- Furthermore, When I open an incognito mode and access this plugin, still I get the same user's access token.
Additional Note
I tried the same gapi.auth.authorize()
using a Web OAuth 2 Client Id. It works perfectly fine. I mean whenever this authorize is executed it fetches the current logged in user's data or it asks for a login where the user can log in and authenticate. How do I achieve the same thing in chrome extension? Kindly let me know if I am missing something here.
- 2 I've been trying to find an answer to this myself. The lack of help here is discouraging. Looking at the documentation, it looks like you can specify the account ID, but the question is how to get that account ID. There is the getAccounts Method, but it is in dev channel, so not of much help. :( – Matt McCallum Commented Mar 8, 2017 at 2:57
- 1 I have been DESPERATELY trying to find an answer to this. I've tried many many methods. launchWebAuthFlow(), gapi, chrome.identity, xhr requests, etc. NOTHING has worked. The documentation is terrible and there is a serious lack of info on the Internet about this. If ANYONE has any info on this, PRETTY PRETTY PLEASE share!!! – Morfie Commented Apr 6, 2017 at 23:35
- @Morfie : Any luck so far? I have opened a bounty for the same. Let's see if we can get some pointers. – Sumuga Commented Dec 5, 2017 at 9:37
- Actually, yes. Let me post some updates. I can't do it this second (in the middle of fixing something, but I'll add a reminder to update it.) – Morfie Commented Dec 5, 2017 at 18:25
3 Answers
Reset to default 2As of now, this is not possible using supported APIs in Google Chrome stable (Version 63). However, in the Dev channel and most likely with a future release, the following will be possible:
chrome.identity.getAccounts(function(accounts) {
// accounts is a list of accounts.
chrome.identity.getAuthToken({ 'interactive': true, 'account': accounts[0] }, function(token) {
/* With which i can use xhr requests to get data from gmail api */
console.log('Access Token : '+token);
});
});
See the documentation for getAccounts()
.
EDIT: Something that might work in the meantime is registering for the onSigninChanged
event.
How I ended up handling is was this (summary):
- In the page layer, on load, I send a message down the stack to the background layer.
- I used launchWebAuthFlow() to https://accounts.google./o/oauth2/auth to get the access_token for the account.
- I made an AJAX call to https://www.googleapis./oauth2/v4/token using the access_token to get a refresh token.
When a user changes which account they are using via the avatar button on the top-right, this process is triggered again, as it is initiated by onLoad for the page layer of the extension.
The things left out the description above are caching and error handling, which are super-important.
http://developer.streak./2014/10/how-to-use-gmail-api-in-chrome-extension.html
is the plete solution which I have recently implemented on background page to work with Gmail API.
The content script is calling popup window to authorize using generated URL and simple server endpoint to store the refresh token.
$.oauthpopup = function (options) {
options.windowName = options.windowName || 'ConnectWithOAuth'; // should not include space for IE
var left = (screen.width / 2) - (800 / 2);
var top = (screen.height / 2) - (500 / 1.4);
options.windowOptions = options.windowOptions || 'location=0,status=0,width=800,height=500,left=' + left + ',top=' + top;
options.callback = options.callback || function () {
window.location.reload();
};
var that = this;
debug('oauthpopup open separate _oauthWindow');
that._oauthWindow = window.open(options.path, options.windowName, options.windowOptions);
};
$.oauthpopup({
path: 'https://accounts.google./o/oauth2/auth?' +
'access_type=offline' +
'&approval_prompt=force' +
'&client_id=' + clientID +
'&redirect_uri=' + callBackUrl +
'&response_type=code' +
'&scope=https://mail.google./ email profile' +
'&state=' + login.timyoUUID +
'&user_id=' + login.user_email,
callback: function () {
// do callback stuff
},
});
callBackUrl is used to store refresh token on the server.
Here is the example how I set access token for every request to gapi
export function setTokenForGAPI(accessToken) {
return getGAPIClient()
.then(() => {
const isSameToken = (currentAccessToken === accessToken);
const noToken = ((accessToken === undefined) || (accessToken === ''));
if (isSameToken || noToken) return;
gapi.auth.setToken({
access_token: accessToken,
});
currentAccessToken = accessToken;
})
.catch(function (e) {
console.log('error in setTokenForGAPI', e);
});
}
export function getEmailsByThreadIds(accessToken, ids) {
return setTokenForGAPI(accessToken)
.then(groupedThreadDetailsRequests(ids))
.then(processEmailDetailsResponse);
}