Impossible to use identity.launchWebAuthFlow to authorize with Google OAuth scopes
Categories
(WebExtensions :: Compatibility, defect, P2)
Tracking
(firefox-esr78 fixed, firefox76 wontfix, firefox77 wontfix, firefox78 wontfix, firefox79 wontfix, firefox80 wontfix, firefox84 wontfix, firefox85 fixed, firefox86 fixed)
People
(Reporter: mymindstorm, Assigned: mymindstorm)
References
(Regression)
Details
(Keywords: dev-doc-complete, regression)
Attachments
(1 file)
47 bytes,
text/x-phabricator-request
|
jcristau
:
approval-mozilla-beta+
RyanVM
:
approval-mozilla-esr78+
|
Details | Review |
User Agent: Mozilla/5.0 (X11; Fedora; Linux x86_64; rv:75.0) Gecko/20100101 Firefox/75.0
Steps to reproduce:
After the new redirect_uri requirements for identity.launchWebAuthFlow introduced in Bug 1614919 (still restricted), it is now impossible to use Google OAuth flows. Google requires that you verify all websites that you redirect to. It is impossible to verify ownership of extensions.allizom.org through Google's developer console.
- Create a Google OAuth client id using your extension's redirect URI
- Try to verify OAuth consent screen
Actual results:
Cannot verify domain. Can only use extensions.allizom.org as redirect URI.
Expected results:
I should be able to use a redirect URI that I control as part of the authorization process.
This is probably not a Google-specific issue. I'm sure there are other examples of OAuth providers requiring that you verify ownership of your redirect URIs. I don't see the point of restricting the redirect_uri parameter, as it's still possible to just create a popup window and have the extension manage the redirect to work around the restrictions put on the identity API. It would be nice to at least have some insight into why this restriction was put on identity.launchWebAuthFlow.
Updated•4 years ago
|
Comment 1•4 years ago
|
||
I just created an oauth app entry and was not required to do any verification. The only place I see domain verification is for webhook/push notifications. My test extension performed as expected. If you can provide a specific STR that shows otherwise please reopen.
Assignee | ||
Comment 2•4 years ago
|
||
You have to verify the consent screen for public use.
https://support.google.com/cloud/answer/7454865
Apps in development: if your app is experimental or a test build, you don't need to go through verification unless you decide to launch it to the public.
https://support.google.com/cloud/answer/9110914
The process you need to complete depends on whether your app requests sensitive scopes, or restricted scopes (all apps must complete the first process, brand verification)
Under all apps section:
Verify ownership of your project’s authorized domains using the Search Console. Use an account that is either a Project Owner or a Project Editor of your Cloud Console project.
If you add a redirect URI it will be automatically added to authorized domains.
Updated•4 years ago
|
Comment 3•4 years ago
|
||
S1 or S2 bugs needs an assignee - could you find someone for this bug?
Updated•4 years ago
|
Updated•4 years ago
|
Comment 4•4 years ago
|
||
I can confirm there doesn't seem to be a way to go through the oauth flow for Google that will pass verification:
STR:
- Go to cloud console, add credentials:
- The "Desktop App" option doesn't allow setting a redirect URL
- The "Web Application" does allow setting a redirect URL, so this is the only path right now
- Add your
...extensions.allizom.org
URL as a redirect URL - Go to the Consent Screen options, your app requires verification
- In the options you will see that allizom.org is automatically added to "authorized domains"
- If you send this to Google, they will reject the verification saying you need to verify ownership of allizom.org
Expected:
The ideal approach would be to allow for the "Desktop Application" option from Google. No redirect url is selectable here. The documentation suggests a few different values that can be passed to the redirect_uri
parameter:
- custom uri scheme (used for mainly for mobile apps?)
- loopback ip address (might cause conflicts with other software?)
- Manual copy/paste (not great UX)
- Programatic extraction (yay!)
The proposed change here would be to accept urn:ietf:wg:oauth:2.0:oob:auto
as a redirect uri, and then monitor the requests to wait for the token to appear. Do note however that Google considers this method deprecated (click the programmatic extraction button in the Sample authorization URLs section). Another possibility, which could be accepted in addition, would be the custom uri scheme, it uses the reverse notation of the client id, e.g. com.googleusercontent.apps.123:redirect_uri_path
, which should be possible to monitor and extract as well.
As a workaround I guess one could implement their own oauth flow with browser.windows.create() and webRequest. This bug shouldn't be too difficult for a contributor to fix, I wouldn't consider it an immediate priority for the WebExtensions team.
Updated•4 years ago
|
Assignee | ||
Comment 5•4 years ago
|
||
The proposed change here would be to accept
urn:ietf:wg:oauth:2.0:oob:auto
as a redirect uri, and then monitor the requests to wait for the token to appear. Do note however that Google considers this method deprecated (click the programmatic extraction button in the Sample authorization URLs section). Another possibility, which could be accepted in addition, would be the custom uri scheme, it uses the reverse notation of the client id, e.g.com.googleusercontent.apps.123:redirect_uri_path
, which should be possible to monitor and extract as well.
I don't think you should be using a deprecated method here. Outside of the possibility of oauth breaking again, this would only solve the issue for Google, and not any other oauth provider that requires domain verification. You can't use custom uri scheme since Google requires publishing info from an app store to use a mobile client type. A loopback address would work best as extensions wouldn't have to pretend to be a website.
I have some working code for using 127.0.0.1 that I will submit, I'm still going through the patch submission docs.
As a workaround I guess one could implement their own oauth flow with browser.windows.create() and webRequest. This bug shouldn't be too difficult for a contributor to fix, I wouldn't consider it an immediate priority for the WebExtensions team.
Could Bug 1614919 be made public so that if an extension does implement their own oauth flow it doesn't create a security issue?
Assignee | ||
Comment 6•4 years ago
|
||
Updated•4 years ago
|
Comment 7•4 years ago
|
||
Thank you so much for making the effort to create a patch! Bug 1614919 can likely be made public, I've asked the team to check.
Reading more about the oob:auto urn, it does look like this is Google-specific. rfc 8252 warns that using loopback might be a problem if other applications on the machine are using that port, so as long as we intercept the loopback request and don't actually execute it that seems fine to me as well.
I was interested in this for other reasons as well, so here is a proof of concept I wrote that doesn't use the identity API: https://gist.github.com/kewisch/be78a55577e58c6d88b5b39ea598365c
Assignee | ||
Comment 8•4 years ago
|
||
I think it's already cancelling the redirect from going through. I'm not too familiar with Firefox source, so I may be mistaken here.
Comment 9•4 years ago
|
||
The reason for limiting redirect_url
values in bug 1614919 is to prevent extensions from receiving OAuth tokens from unrelated OAuth providers.
An (external) OAuth service is expected to only accept registered values for redirect_url
, to prevent leakage of tokens to applications that aren't owned by the client that had been registered with the OAuth service.
The identity.launchWebAuthFlow()
API uses a dummy URL (https://<app-id>.chromiumapp.org/
in Chrome, extensions.allizom.org
in Firefox) to have a safe redirection target that isn't under control of third parties. Instead of the result (e.g. auth tokens) being passed to the page at redirect_url
, the result is passed to the callback of identity.launchWebAuthFlow()
. Because of this, the browser must ensure that redirect_url
is owned by the extension author:
- Chrome chooses a well-known dummy
redirect_url
containing the extension ID (https://<app-id>.chromiumapp.org/
). Google's OAuth service supports verification of extension ownership as seen in https://developer.chrome.com/extensions/tut_oauth . This only happens because Chrome and Google's OAuth server are from the same company. - Firefox also chooses a dummy
redirect_url
, but there is no way to prove Firefox extension ownership to providers such as Google.
The solution to this is to either allow extension developers to prove their ownership to OAuth providers, or to allow extension developers to prove their ownership of the domain to Firefox. The first is not likely to happen because of the high cost in engineering and operations. The latter can reasonably be implemented with existing primitives.
- When an extension requests host permissions, it is granted access to any data from the website. A user consenting to the permission can be taken as a signal that the extension is allowed to see the redirect URL.
- ( If we are concerned about overloading the meaning of host permissions, or if we want the ability to detect the use of
redirect_url
by static analysis, then we could require theredirect_url
to be set in manifest.json. This would theoretically be more "secure", but I am not convinced that we should bother, because the alternative is that the extension implements the OAuth flow with other extension APIs as demonstrated by Philipp in comment 7, which is less user-friendly and not more secure. )
P.S.: Whitelisting loopback addresses such as 127.0.0.1 is not the ideal solution IMO, since it does not address the issue of ownership and still has the potential for credential leakage of unrelated OAuth clients. This option was only considered because Google coincidentally treats it as a special endpoint (with less rigid ownership verification requirements), and I don't view that as a good justification to whitelist an arbitrary domain.
Updated•4 years ago
|
Assignee | ||
Comment 10•4 years ago
|
||
because the alternative is that the extension implements the OAuth flow with other extension APIs as demonstrated by Philipp in comment 7
I also mentioned this before when I opened this issue. I really don't see the point as anyone who knows the API well enough could easily work around the restrictions making any type of verification system meaningless.
Whitelisting loopback addresses such as 127.0.0.1 is not the ideal solution IMO, since it does not address the issue of ownership and still has the potential for credential leakage of unrelated OAuth clients.
The auth flows involving loopback addresses are designed for native apps. I see this as the most reasonable solution as all native apps are public clients that inherently share this problem. Using a native flow would allow providers to be aware of this. There are already standards to help mitigate the flaws with public clients such as RFC 7636.
Firefox might also be able to mitigate this by scanning for declared client ids in code during review and auto-rejecting/flagging if someone tries to upload an extension that is not authorized to use associated with a client id.
Comment 11•4 years ago
|
||
(In reply to mymindstorm from comment #10)
because the alternative is that the extension implements the OAuth flow with other extension APIs as demonstrated by Philipp in comment 7
I also mentioned this before when I opened this issue. I really don't see the point as anyone who knows the API well enough could easily work around the restrictions making any type of verification system meaningless.
The alternatives require permissions that the user need to approve (either host permissions or "Access browser tabs"), whereas the identity
API does not trigger any permission warnings.
Whitelisting loopback addresses such as 127.0.0.1 is not the ideal solution IMO, since it does not address the issue of ownership and still has the potential for credential leakage of unrelated OAuth clients.
The auth flows involving loopback addresses are designed for native apps. I see this as the most reasonable solution as all native apps are public clients that inherently share this problem.
I'm not fully onboard on this being the "most reasonable solution", because there is already a feasible alternative in the form of extension permissions. So far the only justification for relaxing the redirect_uri
requirements with regards to 127.0.0.1 is because Google accepts it. I'd like some evidence of this being a more widely used practice by other major OAuth service providers before accepting 127.0.0.1 as a dummy value.
Firefox might also be able to mitigate this by scanning for declared client ids in code during review and auto-rejecting/flagging if someone tries to upload an extension that is not authorized to use associated with a client id.
This suggested alternative is far less reliable than a static value in manifest.json.
Assignee | ||
Comment 12•4 years ago
|
||
(In reply to Rob Wu [:robwu] from comment #11)
(In reply to mymindstorm from comment #10)
Whitelisting loopback addresses such as 127.0.0.1 is not the ideal solution IMO, since it does not address the issue of ownership and still has the potential for credential leakage of unrelated OAuth clients.
The auth flows involving loopback addresses are designed for native apps. I see this as the most reasonable solution as all native apps are public clients that inherently share this problem.
I'm not fully onboard on this being the "most reasonable solution", because there is already a feasible alternative in the form of extension permissions. So far the only justification for relaxing the
redirect_uri
requirements with regards to 127.0.0.1 is because Google accepts it. I'd like some evidence of this being a more widely used practice by other major OAuth service providers before accepting 127.0.0.1 as a dummy value.
The justification for allowing loopback addresses is the OAuth spec. The below specifically allows letting native apps use loopback addresses.
Comment 13•4 years ago
|
||
The relevant part is:
The authorization server MUST allow any port to be specified at the
time of the request for loopback IP redirect URIs, to accommodate
clients that obtain an available ephemeral port from the operating
system at the time of the request.
This looks good enough to me, as it means that it applies to more services besides Google.
To still maintain proper isolation between native apps and extensions, let's only allow URLs in a fixed format such as http://127.0.0.1/oauth2identity/[hash]
.
Assignee | ||
Comment 14•4 years ago
|
||
(In reply to Rob Wu [:robwu] from comment #13)
The relevant part is:
The authorization server MUST allow any port to be specified at the
time of the request for loopback IP redirect URIs, to accommodate
clients that obtain an available ephemeral port from the operating
system at the time of the request.This looks good enough to me, as it means that it applies to more services besides Google.
I have never said that using loopback addresses was Google specific, and I have specifically said before that this is probably not just a Google issue.
To still maintain proper isolation between native apps and extensions, let's only allow URLs in a fixed format such as
http://127.0.0.1/oauth2identity/[hash]
.
Do you have a specific port you want me to use? 80 does not seem like the best choice. The purpose of that insecure match was to allow developers to specify a port. I was going to switch it to a regex, but if you only want one specific address that would make it simpler.
How about http://127.0.0.1:5440/mozoauth2identity/[hash]
and http://::1:5440/oauth2identity/mozoauth2identity/[hash]
?
Comment 15•4 years ago
|
||
Firefox will intercept the redirect to that URL; it's never going to be followed. So, we don't need to support more formats than absolutely necessary.
Just verifying that the URL starts with http://127.0.0.1/mozoauth2/[hash]
should be good enough.
Comment 16•4 years ago
|
||
Updated•4 years ago
|
Comment 17•4 years ago
|
||
Clearing old needinfo (the severity has already been set in the meantime)
Comment 18•4 years ago
|
||
bugherder |
Updated•4 years ago
|
Comment 19•4 years ago
|
||
The patch landed in nightly and beta is affected.
:mymindstorm, is this bug important enough to require an uplift?
If not please set status_beta
to wontfix
.
For more information, please visit auto_nag documentation.
Comment 20•4 years ago
|
||
Comment on attachment 9172932 [details]
Bug 1635344 - Allow launchWebAuthFlow redirect URI to be set to loopback address. r?rpl
Beta/Release Uplift Approval Request
- User impact if declined: Google oauth flows for extensions do not work right
- Is this code covered by automated tests?: Yes
- Has the fix been verified in Nightly?: No
- Needs manual test from QE?: No
- If yes, steps to reproduce:
- List of other uplifts needed: None
- Risk to taking this patch: Low
- Why is the change risky/not risky? (and alternatives if risky): This only effects one specific extension api, and only if a loopback url is used. It has automated testing.
- String changes made/needed: n/a
Comment 21•4 years ago
|
||
Comment on attachment 9172932 [details]
Bug 1635344 - Allow launchWebAuthFlow redirect URI to be set to loopback address. r?rpl
approved for 85.0b5
Comment 22•4 years ago
|
||
bugherder uplift |
Updated•4 years ago
|
Comment 23•4 years ago
|
||
Is this API widely used enough (particularly for enterprise-type situations) that we should consider uplifting to ESR also? It grafts cleanly.
Comment 24•4 years ago
|
||
Comment on attachment 9172932 [details]
Bug 1635344 - Allow launchWebAuthFlow redirect URI to be set to loopback address. r?rpl
ESR Uplift Approval Request
- If this is not a sec:{high,crit} bug, please state case for ESR consideration: widely used api that fails with google oauth
- User impact if declined: unable to use google services via extensions
- Fix Landed on Version: 86
- Risk to taking this patch: Low
- Why is the change risky/not risky? (and alternatives if risky): This only effects one specific extension api, and only if a loopback url is used. It has automated testing.
- String or UUID changes made by this patch: none
Updated•4 years ago
|
Comment 25•4 years ago
|
||
Comment on attachment 9172932 [details]
Bug 1635344 - Allow launchWebAuthFlow redirect URI to be set to loopback address. r?rpl
Approved for 78.7esr.
Comment 26•4 years ago
|
||
bugherder uplift |
Comment 27•4 years ago
|
||
I'd like to put this in the enterprise release notes, but I can't come up with a good summary. Can someone that fixed this help?
Assignee | ||
Comment 28•4 years ago
|
||
Something along the lines of this?
Extensions using
identity.launchWebAuthFlow
may now use a specifically formatted loopback address as the redirect URL.
The release notes will need to link to some documentation with the allowed redirect format.
Comment 29•4 years ago
|
||
I've submitted a documentation change at https://github.com/mdn/content/pull/1530
Comment 30•4 years ago
|
||
What's the URL where that doc lives? I can't tell from the github pull.
Comment 31•4 years ago
|
||
It will be rendered at https://developer.mozilla.org/en-US/docs/Mozilla/Add-ons/WebExtensions/API/identity
PS. even without my reply, you can find the page by copying a phrase from the source code and searching for "[phrase] mdn" on Google, DuckDuckGo, etc.
Comment 32•4 years ago
|
||
even without my reply, you can find the page by copying a phrase from the source code and searching for "[phrase] mdn" on Google, DuckDuckGo, etc.
I swear I tried that first and didn't get a hit. :)
Description
•