Feature request: return OpenID connect id_token via the chrome.identity API
Reported by
dylan.sa...@gmail.com,
May 12 2017
|
|||||||||
Issue descriptionUserAgent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_12_1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/58.0.3029.110 Safari/537.36 Steps to reproduce the problem: 1. From a Chrome extension, launch the Identity API Scope Approval UI (Gaia) using chrome.identity.launchWebAuthFlow, and using the Google OAuth flow (i.e. by initiating a well-formed OAuth request to https://accounts.google.com/o/oauth2/v2/auth) 2. Log into Google through that flow 3. Restart Chrome 4. Launch the OAuth flow again using chrome.identity.launchWebAuthFlow. Gaia cookies have been cleared on Chrome restart, and therefore the Google session information is lost - you'll be forced to login again. What is the expected behavior? It's unclear whether this is a bug or a feature. Personally, my expected behavior is that session cookies should persist in Gaia so that OAuth requests using chrome.identity.launchWebAuthFlow continue working after the user restarts Chrome. What went wrong? Since Gaia wipes cookies on Chrome restart, any OAuth flow that requests access tokens using chrome.identity.launchWebAuthFlow fails when the user closes and re-opens Chrome, forcing the user to re-authenticate. This is a poor user experience. I'm trying to get this working for a Chrome extension. Performing OAuth successfully in Chrome extensions requires working with multiple tradeoffs (e.g. fetching access tokens using chrome.identity.getAuthToken() requires logging into Chrome, which isn't ideal in our circumstance - this has been reported here: https://bugs.chromium.org/p/chromium/issues/detail?id=345104). I've documented more context on Stack Overflow, here: http://stackoverflow.com/questions/43876232/how-to-fetch-google-oauth-access-tokens-from-chrome-extensions-tradeoffs-betwe?noredirect=1#comment74900552_43876232 . Others have reported the same issue with gaia cookies clearing on reboot here: http://stackoverflow.com/questions/33954876/different-ways-to-fetch-oauth-token-from-an-extension . Did this work before? N/A Does this work in other browsers? Yes Chrome version: 58.0.3029.110 Channel: stable OS Version: OS X 10.12.1 Flash Version: Please let me know if you need any more specific information from me.
,
May 15 2017
,
May 15 2017
,
May 16 2017
,
May 17 2017
Mihai - are you familiar with this flow? I wasn't aware that we had separate APIs for accessing the account signed into Chrome and going through the auth flow for any Google Account.
,
May 22 2017
Gaia does *not* wipe out cookies on restart. Chrome does *not* wipe out cookies on restart. I think Chrome uses a separated cookie jar for the extension web authorization flow - maybe this is why you're seeing that the cookies for that account are not persisted. It is the responsibility of the extension to take the authorization code from the response URL, exchange it for a OAuth2 token and then use it to generate OAuth 2.0 access tokens. What exactly are you trying to do?
,
May 22 2017
Thanks for all the comments. Fundamentally, I'm just trying to fetch data from Google APIs from the Chrome extension, over time, without having to prompt the user for login / consent after the initial interaction with the app. This works fine - I'm able to fetch access tokens in the background - until the user restarts Chrome. AFAIK, I should _not_ be retrieving an OAuth authorization code from the browser, since that could be used to generate access / refresh tokens indefinitely, and since I'd need my client secret to generate those (which shouldn't be stored in the extension). Google's documentation (https://developers.google.com/identity/protocols/OAuth2UserAgent) and other OAuth resources suggest that I should request short-lived access tokens directly, not authorization codes, when running code in the client. If Chrome has a separate cookie jar for the extension auth flow, it is working well while the user has Chrome open (cookies persist, and I'm able to fetch access tokens silently using chrome.identity.launchWebAuthFlow). When the user restarts Chrome, the cookies in that cookie jar do appear to be cleared. Based on what you've said, that doesn't seem like the expected behavior, since Chrome doesn't clear cookies on restart. Let me know if that answers your questions or if you need any more data from me.
,
May 24 2017
Let me explain more in detail what I think is happening here and why I think we cannot do what you would like to: For security reasons, the Gaia authorization page dialog is loaded in an extension context, which uses a Guest WebView, which uses an in-memory storage partition (this includes the cookie store). The code that is responsible for this is here: https://cs.chromium.org/chromium/src/chrome/browser/extensions/api/identity/web_auth_flow.cc?rcl=f09a33ec69c0ad5a9e59c49a9e39291d8fe795d9&l=107 * This pretty much means that people need to always go through a Google web-sign in in the extension (you cannot reuse the Google accounts that are already present in the profile cookie jar) * This also means that once Chrome is restarted, the in-memory storage is lost. Note that that store is available as long as Chrome is running (this is not tied to the lifetime of the extension). My question would be: Why do you want to avoid asking the users to sign in to Chrome? I would personally strongly advise you to consider using the chrome.identity API. The benefit would be 2 fold: * the flow would be very simple for users that are already signed in to Chrome (no need to reauth) * when the user signs out of Chrome, they will also sign out of your extension.
,
May 24 2017
Really appreciate the explanation - the behavior makes sense now. There are a few reasons we'd like to avoid having users sign into Chrome: - I have a hypothesis that most "normal" users are not logged into Chrome. If y'all have statistics on the percentage of users actually utilizing Chrome login, I'd actually love to see those stats - it'd help validate or invalidate this hypothesis. - If a user isn't logged into Chrome, the sign-in flow is heavy for the average user. If we initiate Chrome login from a "Get Started" button in our app, the user has to first login (some might be logged into Google already, so wonder why they're being asked to login again - understand that these users are non-technical). Next, they're directed to a page asking them what data they'd like to sync with Chrome. Since none of this is related to the app itself, this is heavy and confusing. At the exact same time as they see this screen, the Identity Scope Approval UI pops up, asking the user to approve the OAuth grants our app has requested. So quite a bit happens at once. For the kind of users we'd like to work with, this can be overwhelming. If you put yourself in the shoes of a non-technical user, can you understand how the flow of signing into Chrome and granting auth might be a little heavy, compared to web apps that have access to the browser cookie jar and can navigate OAuth in one simple step? - I don't believe there's a way to retrieve an OpenID Connect id_token from the chrome.identity API, which we'd like to use to authenticate users of the extension with backend services. In order to retrieve an id_token, it seems like we'd need to use launchWebAuthFlow anyway - is that correct?
,
May 24 2017
Just speaking to your first two points: (1) We don't publicly share our sign-in statistics, but generally you're not wrong. However, whether you use the chrome.identity API or your current mechanism, the user is going to have to sign-in (since the extension doesn't share the profile cookie jar), right? So even if not many users are signed in to Chrome, *some* users are, and those users wouldn't have to re-authenticate again (as opposed to your current setup, where *all* users have to re-authenticate). (2) Fair point. The "sign in to Chrome" flow is intentionally somewhat heavyweight, because we don't want users to accidentally start syncing all of their browsing data/history without realizing what they're doing. Note that the issue where the Identity Scope Approval UI popping up at the same time as the sync confirmation dialogue is an unfortunate consequence of the way it's implemented, since technically the sign-in is completed before that confirmation dialogue is shown. However, it's worth noting that the confirmation dialogue does not ask users to choose what data they'd like to sync. By default, everything is synced, and there's a single, big, blue "OK, GOT IT" button. I'd imagine that most non-tech-savvy users would just click through both that dialogue and the Identity Scope Approval UI by selecting the default "OK" buttons. I grant you that it's a little more heavyweight, since they'll have to click two confirmation buttons instead of one, but the sync confirmation dialogue isn't asking the user to make a very complex decision. So, in short, I hear your concerns, but overall I concur with #8 that the best user experience is likely to be the chrome.identity API :) While I can't give you precise numbers, I can assure you that most of the drop-off we see in our "sign in to Chrome" flow comes before the confirmation dialogue. Usually, as long as a user manages to open the flow in the first place and enter their email address & password, they manage to click "OK, GOT IT" on the final screen. However, I can't speak to (3) - I'll let Mihai answer that.
,
May 24 2017
Ok, I really appreciate the thorough review. Clearly y'all put a lot of thought into the sign-in process and it's good to know that most of the drop-off happens prior to the sync confirmation. This definitely helps.
,
May 24 2017
Sure thing! Thanks for your own thoughtful explanations as well. Note that as I mentioned in #10, the biggest drop off is in opening the flow in the first place (which you will take care of by calling the chrome.identity API when the user clicks the "Get Started" button) and entering their email address/password. Honestly, I would imagine the drop-off at that step is probably similar between our sign-in flow and the web authorization flow. So the only users you're losing out on are those that click "UNDO" on the confirmation screen, which as I said, is low. Hope that helps! I'll still let Mihai comment on the OpenID Connect id_token question before closing this out.
,
May 29 2017
I do not think that we expose an API to extract the OpenID connect id_token for an account via the chrome.identity API. I think we never had a request to do that - I think the idea we had for this API is to be used from the client and so far the only data we thought would be necessary was the following: * the email / account id (available via chrome.identity.getProfileUserInfo) * an OAuth 2.0 access token (avaiable via chrome.identity.getAuthToken ) I suppose you could try using launchWebAuthFlow is non-interactive mode and see if you can get the id_token without any user interaction (I do not know if getting the id_token would require an additional authentication / authorization flow). Providing the Open ID Connect id_token would be something that we may expose in the API (I do not see any downside for doing that), unfortunately we do not have a lot of cycles to implement that soon.
,
May 31 2017
Thanks, Mihai. Understood that that might take some time. Should I create a separate feature request for that, since this ticket is tied to a tangential issue? I am able to fetch an id_token using launchWebAuthFlow, non-interactively, but encounter the same issue I originally reported - on Chrome restart, the user is promoted to login again. I'm new to implementing the OAuth flow, but as far as I know, using an OpenID Connect id_token is the preferred way to authenticate a user "signed into" my Chrome extension with a backend service I operate. I originally tried handling this with the Google Sign-In library (see https://developers.google.com/identity/sign-in/web/backend-auth), but that fails to work in a Chrome extension environment (see https://github.com/GoogleWebComponents/google-signin/issues/102). Let me know if that separate feature request makes sense, or if you need any more info from me.
,
May 31 2017
CC+ courage@ I think used the OpenID connect id_token is the right solution to authenticate the user to the backend. Just to make sure I understand how this would work for you: * your extension gets an OpenID connect id_token * it passes this token to the baskend service (is this a server somewhere?) * the backend service can ask Google to validate that the user is a valid Google user I think I can understand your problem: basically the Open ID token also expires after some time, so you cannot store it on disk. So after a while you'll need to fetch it again and if this after a restart you'll hit the prompt to login. I am afraid I do not have a solution for you that would ensure that you can only get an OpenID token without any user interaction using the current API. We'll discuss this internally and see if this is something we want to do and if we have the bandwidth to implement it.
,
May 31 2017
Given the above discussion, I'm going to just re-purpose this bug for the feature request.
,
Jun 1 2017
Great, thanks for re-purposing this ticket. Mihai: yes, your understanding of my intended flow is correct. I've got a backend service that should accept id tokens, where I validate the token as suggested by that Google Sign-in documentation. The id_token work isn't a blocker for us now, but from seeing others on the web trying (and failing) to implement Google Sign-In in a Chrome extension, I'd imagine this would be a huge help to people trying to develop extensions that talk to backend services. Again, I very much appreciate the willingness to listen to the use cases and talk this out. Thanks! Dylan
,
Jun 1 2017
Also, I just read your comment again and wanted to comment on this section: "I think I can understand your problem: basically the Open ID token also expires after some time, so you cannot store it on disk. So after a while you'll need to fetch it again and if this after a restart you'll hit the prompt to login." Correct. As I understand it, Google's libraries for validating id_tokens confirm the value of the 'exp' claim hasn't passed (see: https://developers.google.com/identity/protocols/OpenIDConnect#validatinganidtoken), so caching and re-using this token indefinitely isn't an option.
,
Mar 2 2018
I'd like to make a case for the id_token. I don't care if it expires - I don't want to store it - I just need a way to authenticate a user to my backend. I have a business webapp that exclusively authenticates with Google Sign In. Calls to my server pass the id_token; my server infrastructure validates this token to identify the caller. I use the google-provided GoogleIdTokenVerifier in the SDK. I'm now building a chrome extension that needs to perform the same authentication to my backend. Unfortunately I only get an access_token, not an id_token. It looks like it's possible to validate this token on my server, but AFAICT Google doesn't provide any SDK tooling so I'll have to build it myself from scratch (or rely on hitting the https://www.googleapis.com/oauth2/v3/tokeninfo endpoint). It would be much better if I can just use chrome identity to get the same id_token that the Google Sign In javascript provides; then my server can remain blissfully ignorant of whether it's being used from a webapp or a chrome extension.
,
Mar 8 2018
The team is currently under fire to implement a different thing. I do not think we'll get to this request before Q3.
,
Sep 12
This is an annoying issue, our users are complaining all the time about the number of login's they have to do. Please do something about this! |
|||||||||
►
Sign in to add a comment |
|||||||||
Comment 1 by phistuck@chromium.org
, May 12 2017Labels: -Hotlist-Interop