Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Should we request permission when sensor is not supported by the platform? #145

Closed
alexshalamov opened this issue Oct 31, 2016 · 55 comments
Closed
Assignees
Labels
api-refactoring ED-ready permissions privacy-tracker Group bringing to attention of Privacy, or tracked by the Privacy Group but not needing response. security-tracker Group bringing to attention of security, or tracked by the security Group but not needing response.
Milestone

Comments

@alexshalamov
Copy link

It would be nice if specification could provide guideline for the order of "get default sensor" and "request permission" steps.

If we request permission first, end user would get notification like "page would like to use sensor X" if user grants permission and then we figure out that it is not supported by HW, it would be annoying for the user / web developer.

If we check whether sensor is supported before the permission request, user experience might be better, but then information about platform is exposed before permission is granted.

@anssiko anssiko added this to the Level 1 milestone Oct 31, 2016
@lknik
Copy link
Contributor

lknik commented Oct 31, 2016

Correct. Immediately returning a permission reject/deny is leaking information. Perhaps it could be rejected/denied after a random (small) delay?

@tobie tobie added privacy-tracker Group bringing to attention of Privacy, or tracked by the Privacy Group but not needing response. needs-research permissions labels Oct 31, 2016
@maryammjd
Copy link

Alex suggestion seems reasonable. @tobie are you concerned that the device would be fingerprinted based on what types of sensors does it support?

@tobie
Copy link
Member

tobie commented Nov 8, 2016

Alex suggestion seems reasonable.

Which one?

are you concerned that the device would be fingerprinted based on what types of sensors does it support?

Yes.

@maryammjd
Copy link

The type/brand of the device would be revealed ONLY, which is not difficult to obtain though other ways anyway such as the size of screen and etc. (navigator.platform, screen.width and screen.height).

@maryammjd
Copy link

maryammjd commented Nov 8, 2016

This seems reasonable: "If we check whether sensor is supported before the permission request, user experience might be better"

@tobie
Copy link
Member

tobie commented Nov 8, 2016

The type/brand of the device would be revealed ONLY, which is not difficult to obtain though other ways anyway such as the size of screen and etc. (navigator.platform, screen.width and screen.height).

So you're suggesting this doesn't provide more details about a device than what can already be inferred from APIs available without permission? That WFM, we just need to add a note for it.

@maryammjd
Copy link

@tobie Yes, that is my understanding. I can give it another thought and get back to you later.

@maryammjd
Copy link

@tobie Discussed it with a few colleagues. It seems that we already have better ways to know the brand of the mobile and then its sensors: http://www.w3schools.com/jsref/prop_nav_useragent.asp

@tobie
Copy link
Member

tobie commented Nov 14, 2016

As per @maryammjd's comment above, we first "get default sensor" before "requesting permission." I'll amend the abstract operation accordingly.

@lknik
Copy link
Contributor

lknik commented Nov 14, 2016

Hey @maryammjd, indeed User-Agent is the basic old-school way of discovering the UA string (among other ways of getting the same). But I'm unsure if that's the right way to think about it.

Thinking long-term, a strict association between UA string and a known list of sensors may not necessarily be maintained. It's a good idea to keep in mind and plan ahead.

@maryammjd
Copy link

@lknik Thansk for your comment. I think i am missing something in you comment. Can you please provide me with a concrete example of what we can get from a list of sensors being supported by a sensor-enabled device that we can not find it in the device public specification?

@lknik
Copy link
Contributor

lknik commented Nov 14, 2016

That's not what I meant. What I intended to convey: Sensors API will be integral part of the Web. Let's not exclude the possibility that hardware and use cases 5-10 years from now might be slightly different than today.
It's also a matter of implementation but that's a different story.

@tobie
Copy link
Member

tobie commented Nov 14, 2016

So thinking about this a bit more, I can see plenty of cases where the 1:1 relationship isn't that clear. For example, desktop browser user agents strings can be identical despite widely different hardware capabilities. Similarly, third party browsers on phones might not necessarily expose enough information to identify the underlying device. e.g. Chrome on iOS has similar UA string across devices that run the same UA and OS builds.

@tobie
Copy link
Member

tobie commented Nov 14, 2016

Emojis are cool, but how do we move this forward? It seems allowing the developer to map out the supported sensors increases the fingerprinting surface. Should we avoid making a distinction between the two errors? What are the UX cost of doing so? Etc.

@lknik
Copy link
Contributor

lknik commented Nov 14, 2016

I recommend to request a permission prior to any attempt leading to accessing of a default sensor - and currently, "any sensor". Regardless of the sensor's existence.
Web developers currently have standard ways of checking whether a feature is available: https://w3c.github.io/sensors/#feature-detection

I think that the current Generic Sensors API won't be shipping a sensor discovery API anyway?

I'd say just write it down in the spec and let's see once it's down there.

@tobie
Copy link
Member

tobie commented Nov 14, 2016

I recommend to request a permission prior to any attempt leading to accessing of a default sensor - and currently, "any sensor". Regardless of the sensor's existence.

How would that work precisely, though? Would you really ask the user for permission? Or instead just return permission "denied"? What if the developer then tells the user that they can't get functionality x because they've "denied access to the gyroscope." Bad UX, especially if the user has no idea what a gyroscope is. This needs to be researched more thoroughly. We're trading privacy for bad UX and this is not a decision that can be taken lightly. It might even be worth considering leaving the option up to implementors.

Web developers currently have standard ways of checking whether a feature is available: https://w3c.github.io/sensors/#feature-detection

I'm not sure where you're going with this.

I think that the current Generic Sensors API won't be shipping a sensor discovery API anyway?

That's correct, but not sure either what you mean by this.

I'd say just write it down in the spec and let's see once it's down there.

We need sound technical arguments here before we proceed.

@lknik
Copy link
Contributor

lknik commented Nov 14, 2016

How would that work precisely, though? Would you really ask the user for permission? Or instead just return permission "denied"? What if the developer then tells the user that they can't get functionality x because they've "denied access to the gyroscope." Bad UX, especially if the user has no idea what a gyroscope is. This needs to be researched more thoroughly. We're trading privacy for bad UX and this is not a decision that can be taken lightly. It might even be worth considering leaving the option up to implementors.

That's precisely what I mean. We leave it to implementors, but require permissions. Implementors might e.g. not expose the object at all (if device not supported/detected), or make different "sensitivity levels", some requiring a prompt, others pre-chosen (but configurable). So: default, ask, but generally leave to implementors.

You definitely don't want to return "denied" just like that in the spec. But if implementors decide otherwise, that's their (bad) choice, as it would be trivial to detect whether a sensor is supported (and the user is really asked for permission) or not (and a default answer "denied" is returned).

Web developers currently have standard ways of checking whether a feature is available: https://w3c.github.io/sensors/#feature-detection

What I mean is: if I understand correctly, the systematic solution to this issue should be "solved" by feature detection mechanism? And if I get it right, that feature is left for later.

@tobie
Copy link
Member

tobie commented Nov 14, 2016

Web developers currently have standard ways of checking whether a feature is available: https://w3c.github.io/sensors/#feature-detection

What I mean is: if I understand correctly, the systematic solution to this issue should be "solved" by feature detection mechanism? And if I get it right, that feature is left for later.

No. As explained in the section you link to, feature detection tells you whether there's software support for accessing a particular sensor, not what's happening on the hardware side.

@tobie
Copy link
Member

tobie commented Nov 14, 2016

e.g. not expose the object at all (if device not supported/detected)

So that's not an option, actually. The availability/existence of the sensor is only known at runtime and requires an async call.

@tobie
Copy link
Member

tobie commented Nov 15, 2016

@pozdnyakov:

Not really, as in this case we give chance to the user to deny the access before any data is leaked. So if start call fails with Abort error you've got no idea of actual HW environment.

You mean NotAllowedError?

@pozdnyakov
Copy link

You mean NotAllowedError?

yeah NotAllowedError, thanks for pointing out

@tobie
Copy link
Member

tobie commented Nov 15, 2016

I agree with @lknik : permissions are the fence around API whatever sensors are actually present on the system.

Just to clarify here, what would the algorithm called on .start() do?

I see three options:

Option 1

  1. Check to see if the sensor exists.
  2. If it doesn't, then throw a NotAllowedError and abort these steps (i.e. pretend the user rejected access to the sensor)
  3. Prompt the user for permission to access the sensor.
  4. If the user grants access, then update readings.
  5. Otherwise, throw a NotAllowedError.

From a fingerprinting perspective, this is better, but it prevents the developer from making distinctions between missing HW and denied access.

Option 2

  1. Prompt the user for permission to access the sensor.
  2. If the user grants access, then:
    1. Check to see if the sensor exists.
    2. If the sensor exists go ahead and provide data.
    3. Otherwise, throw a NotReadableError.
  3. Otherwise, throw a NotAllowedError.

This option is still good from a fingerprinting perspective, provides the developer with more accurate information, but prompts users with weird questions if they don't have the requested sensor.

Option 3

  1. Check to see if the sensor exists.
  2. If it doesn't, then throw a NotReadableError and abort these steps
  3. Prompt the user for permission to access the sensor.
  4. If the user grants access, then update readings.
  5. Otherwise, throw a NotAllowedError.

This option is bad from a fingerprinting perspective. Great from UX and devX perspective.

@lknik
Copy link
Contributor

lknik commented Nov 15, 2016

Option 1 is (privacy) functionally equivalent to Option 3 (unless deployed carefully by implementors). I'm actually not speaking in fingerprinting, but privacy in general terms.

With these three options, my vote is on Option 2 or its variants.

@tobie
Copy link
Member

tobie commented Nov 15, 2016

Questions for you, @lknik:

  • How is 1) similar to 3)?
  • wrt to 2) How do you propose dealing with the awkwardness of asking the user permission to access a sensor they don't have?
  • What do you mean by variants of 2) ? Can you describe them using a similar algorithmic step format?

@lknik
Copy link
Contributor

lknik commented Nov 15, 2016

@tobie

  • 1 vs 3. Same error, different response times ;-)
  • Interesting research question: what % of users is aware of sensors supported by their devices ;-)

If we agree that Option 2 is the way to go, we can explore further (although admittedly not much to go?). Probably no ideal solution.

Initial idea:

  • as I said, we may instruct (non-normative suggestion) platforms to think in creative ways here about actual replies for permission calls to make it (functionally) act somewhat similar to Option 1 (think random delays). I realize it's not foreseen by Permissions API, it would only highlight new possible directions to pursue ;)

@tobie
Copy link
Member

tobie commented Nov 15, 2016

  • 1 vs 3. Same error, different response times ;-)

No, that's incorrect. 3) has different error types for missing sensor (NotReadableError) and rejected permission request (NotAllowedError).

If we agree that Option 2 is the way to go, we can explore further (although admittedly not much to go?). Probably no ideal solution.

Well, do we? This is a tradeoff between UX and fulfilling use cases on one side and increasing the browser's fingerprint by one bit per permission group on the other.

Initial idea:

  • as I said, we may instruct (non-normative suggestion) platforms to think in creative ways here about actual replies for permission calls to make it (functionally) act somewhat similar to Option 1 (think random delays). I realize it's not foreseen by Permissions API, it would only highlight new possible directions to pursue ;)

Can you be a bit more explicit here, and actually provide algorithm steps? I don't see how you'd make 2) look more like 1) without loosing the error distinction which is the part we're interested in.

@lknik
Copy link
Contributor

lknik commented Nov 15, 2016

1 vs 3. Same error, different response times ;-)

No, that's incorrect. 3) has different error types for missing sensor (NotReadableError) and rejected permission request (NotAllowedError).

You are right (sorry), I treated it as the same as functionally it would be the same due to timing.

Well, do we? This is a tradeoff between UX and fulfilling use cases on one side and increasing the browser's fingerprint by one bit per permission group on the other.

Not sure now how many bits, depending on the future.

Can you be a bit more explicit here, and actually provide algorithm steps? I don't see how you'd make 2) look more like 1) without loosing the error distinction which is the part we're interested in.

The following idea would be using something along the lines:

Option 2a (or 1a? or 1.5)

  1. Site requests permission
  2. If the sensor exists, UA prompts the user, all is fine. If the user rejects, return NotAllowedError
  3. If the sensor does not exist, UA is not prompting the user, but it throws a NotAllowedError after a random delay.

Basically Option 1.5, with additional compromise (compromise is on privacy, UX is better, no prompts if sensor exists).

I know it's not warranted by any spec-like features (i.e. Permissions API), so it's probably in hands of implementors.

It's still a trade-off (better UX, still more acceptable privacy layer; bonus points, if a browser vendor will propose inadequate random-delay choice in an implementation, someone can even make an academic paper! ;-) - I wonder if they would provide a reference to this thread).

Caveat: some information would still be leaking, but less than in the case of immediate informing that a sensor does not exist, or allowing to check if it does.

I guess a spec-legit alternative is to just propose Option 1 and also document that it increases fingerprinting surface and suggest browser vendors to choose Option 1.5 if they wish.

That said, in my opinion API calls should be fenced with permissions.

@tobie
Copy link
Member

tobie commented Nov 15, 2016

Can you explain how the random delay helps prevent fingerprinting if the error thrown is distinguishable from the one thrown when permission is denied?

What you're proposing is basically option 3 with an artificial delay that doesn't provide any privacy/fingerprinting benefit as far as I can see.

@lknik
Copy link
Contributor

lknik commented Nov 15, 2016

Oopsie, obviously updated my comment. ;)

Now the errors are identical. If there is no sensor, there is no prompt, and a site has no access.

@tobie
Copy link
Member

tobie commented Nov 15, 2016

Ok, so that's option 1 plus a random delay.

@pozdnyakov
Copy link

My vote for option 2.
In future we'll need discovery API to know beforehand which sensors are present and in order to obviate unneeded prompts.
Please don't specify random delays.

@tobie
Copy link
Member

tobie commented Nov 16, 2016

@pozdnyakov: so you're suggesting prompting the user even if they don't have a sensor on their device? Have you discussed that with the UX folks?

@tobie
Copy link
Member

tobie commented Nov 18, 2016

@pozdnyakov: ping. Would love to have a better understanding of how this would look UX wise.

@pozdnyakov
Copy link

yeah, I'm proposing to prompt even if there are no real sensors present. I did not discussed it with UX folks (could you point out a concrete person who can help?)

@tobie
Copy link
Member

tobie commented Nov 18, 2016

(could you point out a concrete person who can help?)

Emailing some folks. Stay tuned.

@owencm
Copy link

owencm commented Nov 22, 2016

Context: I helped determine Chrome's internal guide on when to apply permissions to APIs, but I am not on the security team and thus am not the ultimate decision maker.

Disclaimer: I don't have full context here and may be missing something, but regardless, here are some general thoughts:

  • A single bit of "fingerprinting" surface isn't a meaningful vector of attack, given the already huge surface area. Low amounts of fingerprinting surface are not justification for adding permissions IMHO
  • Permissions are an extremely heavy hammer and will significantly reduce usage and developer adoption, and thus we should consider them very carefully.

@raymeskhoury
Copy link

(Chrome Security UX engineer chiming in) +1 to @owencm. I think that prompting prior to knowing whether a device is available will be a bad user experience (users already have many problems with prompts).

As a precedent, webrtc doesn't do this, for example if you go to https://webrtc.github.io/samples/src/content/getusermedia/gum/ without a device plugged in, you will see getUserMedia error: DevicesNotFoundError and there won't be a permission prompt. If you plug in a webcam and refresh the page, you will see a prompt.

@lknik
Copy link
Contributor

lknik commented Nov 22, 2016

Thanks @owencm for your reply.

I'm happy you forwarded us details from Chrome Security team. It sounds like the quoted message is referring to the current situation (i.e. 2016). Also, what about the issue of profiling? If I understand correctly, you asked them for fingerprinting. I'm interested in viewing it more generally.

What if the use cases (hardware, software) will be subject to change. Change/break the API then?
In that case, we'll hear that we can't break the Web just like that.

I agree with @raymeskhoury that WebRTC isn't asking for permissions. Accidentally, it can also disclose your local IP address.

@tobie
Copy link
Member

tobie commented Nov 22, 2016

Thanks for the feedback, @raymeskhoury and @owencm. This matches my thoughts wrt to UX.

@lknik: if this did end-up causing fingerprinting/profiling issues down the road, we could always carve out the ability for the implementor to lie about the error type and pretend the user had denied access instead of the device missing such a sensor.

@lknik
Copy link
Contributor

lknik commented Nov 22, 2016

@tobie - how can we specify an option for doing so? Still, the discussion from above applies.
Can we offer an optional way of fencing all API calls behind permissions?

@tobie
Copy link
Member

tobie commented Nov 23, 2016

how can we specify an option for doing so?

In the future, we could do something like this instead:

  1. Check to see if the sensor exists.
  2. If it doesn't, then throw a NotReadableError and abort these steps.
    Note User Agents may decide to throw a NotAllowedError here instead (after random but bounded delay) in order to hide the absence of the sensor on the device.
  3. Prompt the user for permission to access the sensor.
  4. If the user grants access, then update readings.
  5. Otherwise, throw a NotAllowedError.

Still, the discussion from above applies.
Can we offer an optional way of fencing all API calls behind permissions?

Not sure what you mean. What are you suggesting we do? What are you intending to accomplish by it?

@tobie tobie added the security-tracker Group bringing to attention of security, or tracked by the security Group but not needing response. label Dec 2, 2016
tobie added a commit to tobie/sensors that referenced this issue Jan 26, 2017
This fixes a number of pending issues listed below,
for which there was consensus, but editing was still pending.

This introduces a dependency on the infra standard [[INFRA]],
to define precisely the low-level data structures
used by slots and concepts.

This also specifies slots more clearly.

Additionally, this rewrite sprinkles inline issues
in areas of the specs which require more work.

* Handle GC issues by getting rid of the SensorReading interface. 
  Closes w3c#153. Closes w3c#101.
* Check sensor existence before requesting permission. Closes w3c#145.
* Remove side effects from constructors. Closes w3c#138.
* Move default sensor check to start() and add "unconnected" state.
  Closes w3c#128 and closes w3c#104.
* Throttle update frequency to 60Hz by relying on
  requestAnimationFrame. Closes w3c#100.
tobie added a commit that referenced this issue Jan 26, 2017
This fixes a number of pending issues listed below,
for which there was consensus, but editing was still pending.

This introduces a dependency on the infra standard [[INFRA]],
to define precisely the low-level data structures
used by slots and concepts.

This also specifies slots more clearly.

Additionally, this rewrite sprinkles inline issues
in areas of the specs which require more work.

* Handle GC issues by getting rid of the SensorReading interface. 
  Closes #153. Closes #101.
* Check sensor existence before requesting permission. Closes #145.
* Remove side effects from constructors. Closes #138.
* Move default sensor check to start() and add "unconnected" state.
  Closes #128 and closes #104.
* Throttle update frequency to 60Hz by relying on
  requestAnimationFrame. Closes #100.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
api-refactoring ED-ready permissions privacy-tracker Group bringing to attention of Privacy, or tracked by the Privacy Group but not needing response. security-tracker Group bringing to attention of security, or tracked by the security Group but not needing response.
Projects
None yet
Development

No branches or pull requests

8 participants