w3c / sensors

Generic Sensor API
https://www.w3.org/TR/generic-sensor/
Other
127 stars 59 forks source link

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

Closed alexshalamov closed 7 years ago

alexshalamov commented 8 years ago

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.

lknik commented 8 years ago

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

maryammjd commented 8 years ago

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

tobie commented 8 years ago

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 commented 8 years ago

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 commented 8 years ago

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

tobie commented 8 years ago

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 commented 8 years ago

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

maryammjd commented 7 years ago

@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 commented 7 years ago

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

lknik commented 7 years ago

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 commented 7 years ago

@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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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.

lknik commented 7 years ago

You're right @tobie - all is working asynchronously! Make the async call to never "finish" is also not the right thing to do. I would reiterate: SHOULD ask for permissions. But generally leave it to UAs how they choose to ship it.

As per detection - if I get it right, with more sensors supported by platforms, discovery API will be a thing at some point.

tobie commented 7 years ago

So that's not how permissions are designed (you always ask for them, the UA decides whether to prompt the user or respond itself). But that's not the question, here. The question is about the order of operations between checking to see if there's a sensor and asking for permission.

lknik commented 7 years ago

Sure (I know how permissions currently work...). As I said, I recommend the following order: ask permission, check if a sensor exists.

Access to API requires permissions, regardless of there being a sensor(s) or not.

Second, and to the point: ask for permission to access the API first, otherwise you may end up introducing fingerprinting/profiling issues. That's it.

tobie commented 7 years ago

So how would that work? Would you really ask for permission?

"Website wants to know if you have such a sensor?"

Would you distinguish between permission denied and no available sensor? If so, how?

lknik commented 7 years ago

Asking (to see if a sensor exists) for a permission to ask for a permission (to use the sensor) sounds non-optimal :)

Seriously, why not just ask for permission once?

  1. Platform supports a sensor API? Fine, let's try to use it
  2. Ask for permission
  3. Granted. Good! Let's see how it works
  4. Listen for new data, so:
  5. either leave the app to forever listen for data (because no sensor is there, no data ever shows up; also, what if at some point in the future some device types will have manual switches to turn off a sensor?), or
  6. allow a webdev to see if the sensor is actually functioning, e.g. signal that a sensor is not working (a flag, or a frequency of 0, or so)?

I would not distinguish between permission denied and no available sensor.

pozdnyakov commented 7 years ago

If needed you can always distinguish between permission denied and no available sensor from onerror arguments.

pozdnyakov commented 7 years ago

I would not do any requests to the platform (including checking if a certain sensor actually exists on the device) before permissions are granted.

tobie commented 7 years ago

So would you ask the user for permission to use a gyroscope despite them not having any?

tobie commented 7 years ago

if needed you can always distinguish between permission denied and no available sensor from onerror

But then you're back to the fingerprinting issue, no?

lknik commented 7 years ago

So would you ask the user for permission to use a gyroscope despite them not having any?

My understanding is it's an API call. An API call fenced behind a permission mechanism.

It doesn't matter what happens behind the scenes after the API is called. Consider an operating system enforcing OS permissions for apps wishing to access the underlying hardware sensor. What happens if a particular browser does not have an OS-level permission to access a particular sensor?

From a website perspective, this sensor is not providing any data. So the website has a permission to access the API, but it so happens that the API is simply not returning much (because the browser cannot access a particular sensor).

tobie commented 7 years ago

There's a bunch of use cases, and thus improved UX, tied to developers having access to more detailed information about the underlying sensor.

For example:

  1. there's no point asking a user for the permission to access a sensor you know they do not have,
  2. it's useful to try polling a sensor you've be given permission to but which has been disconnected,
  3. it might be useful to explain to a user that they're forgoing some features by denying permission to access a sensor. It's impossible to do that if you can't distinguish between permission denied and missing hardware.
  4. it's good to advise a user that they're sensor got disconnected or is suddenly no longer working, it's useless to tell them this if they actually revoked access.

From a devX point of view, it's also better to send error events rather than to force the developer to set their own timeouts on the sensor and assume something is broken if they don't get data within x ms.

I'm sure we can do better than that.

lknik commented 7 years ago

I agree there is a room for good design here. Any suggestion (food for thought) welcome.

there's no point asking a user for the permission to access a sensor you know they do not have,

Correct, can we defer it to the implementor? This sounds like a browser issue ("not prompting when it's not necessary", e.g. returning 'denied' after some random delay), so can we just provide a non-normative suggestion?

it might be useful to explain to a user that they're forgoing some features by denying permission to access a sensor. It's impossible to do that if you can't distinguish between permission denied and missing hardware.

Again, sounds like a browser item? At the spec level: (1) ask for permission (2) then check for a flag marking if a sensor exists (or "works"), or error out even - but after point (1).

it's good to advise a user that they're sensor got disconnected or is suddenly no longer working, it's useless to tell them this if they actually revoked access.

A webapp can still provide information that "this app works better with sensor X enabled".

I understand and agree with your timeout comment ;)

pozdnyakov commented 7 years ago

if needed you can always distinguish between permission denied and no available sensor from onerror

But then you're back to the fingerprinting issue, no?

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.

pozdnyakov commented 7 years ago

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

tobie commented 7 years ago

@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 commented 7 years ago

You mean NotAllowedError?

yeah NotAllowedError, thanks for pointing out

tobie commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

Questions for you, @lknik:

lknik commented 7 years ago

@tobie

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:

tobie commented 7 years ago
  • 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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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 commented 7 years ago

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

pozdnyakov commented 7 years ago

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 commented 7 years ago

@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 commented 7 years ago

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

pozdnyakov commented 7 years ago

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 commented 7 years ago

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

Emailing some folks. Stay tuned.

owencm commented 7 years ago

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: