Privacy/Reviews/F1A: Difference between revisions

 
(39 intermediate revisions by 2 users not shown)
Line 12: Line 12:
|'''Security Contact:''' || Curtis Koenig
|'''Security Contact:''' || Curtis Koenig
|-
|-
|'''Document State:''' || <section begin='status'/>{{new|documenting}}<section end='status'/>
|'''Document State:''' || <section begin='status'/>{{resolved|(18-Oct-2011) complete}}<section end='status'/>
|}
|}


Line 19: Line 19:


{|
{|
|'''Architectural Overview:''' || (date TBD)
|'''Architectural Overview:''' || Done 7-Oct-2011
|-
|-
|'''Recommendation Meeting:''' || (date TBD)
|'''Recommendation Meeting:''' || Async via email
|-
|-
|'''Wrap-up Meeting:''' || (if necessary)
|'''Wrap-up Meeting:''' || (not necessary)
|}
|}


Line 88: Line 88:




=== Mediator Panel  ===
=== Share Mediator Panel  ===


F1 is an implementation of a mediator for the share activity.  The mediator panel is content
F1 is an implementation of a mediator for the share activity.  The Share Mediator Panel is content
loaded locally from the addon.  APIs (navigator.mozApps.mediator.*) are injected by the mediator class.  Communication between the panel and the mediator class are through sdk ports, passing JSON data.
loaded locally from the addon.  APIs (navigator.mozApps.mediator.*) are injected by the mediator class.  Communication between the panel and the mediator class are through sdk ports, passing JSON data.


Line 104: Line 104:
In order to tunnel a call into a service: the Mediator Panel emits a owa.mediator.invoke port message that contains the data necessary to complete the calls below, along with string id's that the service iframe uses to send a response back.  To send a response, the service iframe will emit an owa.mediation.success.# or owa.mediation.error.# with the response data.
In order to tunnel a call into a service: the Mediator Panel emits a owa.mediator.invoke port message that contains the data necessary to complete the calls below, along with string id's that the service iframe uses to send a response back.  To send a response, the service iframe will emit an owa.mediation.success.# or owa.mediation.error.# with the response data.


The Mediator Panel initiates most of the communication with the third party webapps as necessary to share stuff.
Each 3rd party webapp that supports the share activity implements the other end of these calls


{| class="wikitable"
{| class="wikitable"
Line 112: Line 112:
! Data  
! Data  
! Notes
! Notes
|-
| ''In:''
| return from getParameters
| parameter information for ui configuration and oauth
|
|-
| return from getShareTypeRecipients
| abbreviated contact data for autocompletion support
|
|-
| return from resolveRecipients
| success/error of recipient validation
|
|-
| return from getLogin
| user profile on success
|
|-
| confirm (2)
| success/error of send
|
|-
|-
| ''Out:''  
| ''Out:''  
Line 166: Line 141:
| logout/clearCredentials
| logout/clearCredentials
| none
| none
|
|-
| ''In:''
| return from getShareTypeRecipients
| abbreviated contact data for autocompletion support
|
|-
| return from resolveRecipients
| success/error of recipient validation
|
|-
| return from getLogin
| user profile
| profile returned on success
|-
| return from confirm (2)
| success/error of send
|
|-
|
| return from getParameters
| parameter information for ui configuration and oauth
|  
|  
|}
|}


''Footnotes:''
# if getLogin returns nothing, the login flow is initiated.  If the login type is oauth (defined in the webapp), openwebapps initiates the oauth flow to get the credentials, and passes them to the webapp via the setAuthorization call.
# confirm is only called when the user clicks "send" in the chrome based UI.
# page information such as URL, opengraph data, Title, select share image (currently the first one found), etc.


1. if getLogin returns nothing, the login flow is initiated.  If the login type is oauth (defined in the webapp), openwebapps initiates the oauth flow to get the credentials, and passes them to the webapp via the setAuthorization call.


2. confirm is only called when the user clicks "send" in the chrome based UI.
'''Communication with Share Mediator Component'''  
 
3. page information such as URL, opengraph data, Title, select share image (currently the first one found), etc.
 
 
'''Communication with mediator class'''  


{| class="wikitable"
{| class="wikitable"
Line 188: Line 186:
| ''In:''  
| ''In:''  
| owa.app.ready
| owa.app.ready
| origin
| origin (scheme/host/port)
| one call for each service iframe, received after the service iframe has called owa.service.ready
| one call for each 3rd party webapp. received after the webapp has called owa.service.ready
|-
|-
| ''In:''
|  
| owa.mediation.setup
| owa.mediation.setup
| activity object, services list, caller href
| activity object, services list, caller URL
| data necessary to setup the mediator UI and load service iframes
| data necessary to setup the mediator UI and load webapp iframes
|-
| owa.mediation.onLogin
| authorization credentials if any (e.g. oauth user tokens)
| response from doLogin
|-
| owa.mediation.reconfigure
| none
| sent to mediator content to reconfigure (e.g. a share app was installed or removed)
|-
|-
| ''Out:''  
| ''Out:''  
Line 201: Line 209:
| called by mediator content after load is finished
| called by mediator content after load is finished
|-
|-
| ''Out:''
|  
| owa.mediation.sizeToContent
| owa.mediation.sizeToContent
| width,height
| width,height
| request the mediator class to resize the panel to fit the content
| request the mediator class to resize the panel to fit the content
|-
|-
| ''In:''
|
| owa.mediation.onLogin
| authorization credentials if any (e.g. oauth user tokens)
| response from doLogin
|-
| ''Out:''
| owa.mediation.doLogin
| owa.mediation.doLogin
| auth configuration received from service iframe, may contain consumer oauth key/secret
| auth configuration received from service iframe, may contain consumer oauth key/secret
| requests mediator class to manage logging in for a service
| requests mediator class to manage logging in for a service
|-
|-
| ''Out:''
|
| owa.success
| owa.success
| none
| none
| sent upon successful send
| sent upon successful send
|-
|-
| ''Out:''
|
| owa.failure
| owa.failure
| failure message
| failure message
| sent upon failure to send
| sent upon failure to send
|-
| ''In:''
| owa.mediation.reconfigure
| none
| sent to mediator content to reconfigure (e.g. a share app was installed or removed)
|}
|}


Line 254: Line 252:
|-
|-
| users oauth credentials, secrets, etc
| users oauth credentials, secrets, etc
| localstorage (see oauthorizer component)
| localstorage (obtained using the Share Mediator Component)
|}
|}


'''Communication with mediator panel'''  
'''Communication with Share Mediator Panel'''  


Communication with mediator content is tunneled through the mediator class.  There is no direct conduit
Communication with the Share Mediator Panel is tunneled through the Share Mediator Component.  There is no direct conduit between the Share Mediator Panel and the 3rd Party Webapp component (even though the mediator content could directly access the service iframe via postmessage, it doesn't).  Any call IN will have a response OUT, even if it is an empty response.
between the mediator content and the service content (even though the mediator content could directly access the service iframe).  Any call IN will have a response OUT, even if it is an empty response.


Each app that supports the share activity implements these calls, each is registered using the registerHandler API.  The built-in apps in Firefox Share have the implemenation.
Each app that supports the share activity implements these calls, each is registered using the registerHandler API.  The built-in apps in Firefox Share have the implemenation.
''This mirrors the "Communication with 3rd party webapp components" section of the Share Mediator Panel''.  See that section for the details of this communication.
'''Communication with Share Mediator Component'''
These are all uni-directional calls with the exception of the oauth and sendEmail calls.  The implementation of these APIs are in the openwebapps addon (see servicesapi.js).


{| class="wikitable"
{| class="wikitable"
Line 272: Line 276:
|-
|-
| ''In:''  
| ''In:''  
| getParameters
| service.origin
| none
| app origin (scheme/host/port)
|  
|
|-
|-
| ''Out:''
| getParameters
| parameter information for ui configuration and oauth
|  
|  
|-
| service.registerHandler
| ''In:''
| none
| getShareTypeRecipients
| type of share (e.g. direct, public, group name)
|  
|  
|-
|-
| ''Out:''
|  
| getShareTypeRecipients
| return from oauth.call
| abbreviated contact data for autocompletion support
| results returned by call to oauth endpoint
|  
|  
|-
|-
| ''In:''
|
| resolveRecipients
| return from sendEmail.call
| list of recipients user has entered into TO field
| simple success/failure object
|  
|  
|-
|-
| ''Out:''  
| ''Out:''  
| resolveRecipients
| service.ready
| success/error of recipient validation
| app origin (scheme/host/port)
|  
| same as origin in postMessage api
|-
|-
| ''In:''
|
| getLogin
| service.registerHandler
| none
| origin, activity and message
|  
| all strings used by mediator to call a specific handler (e.g. url, "link.send", "confirm")
|-
|-
| ''Out:''
|
| getLogin/getCredentials
| oauth.call
| user profile on success
| auth service information, user tokens, url to oauth endpoint, parameters (share data)
|  
| for oauth call which are sent to oauth endpoints
|-
|-
| ''In:''
|
| setAuthorization (1)
| sendEmail.call
| oauth credentials
| user oauth tokens, share data, recipients list
|  
|  
|}
=== Share Mediator Component  ===
The Share Mediator Component serves two purposes; 1) managing the Share Mediator Panel and mediator APIs, 2) acting as a tunnel between the 3rd party webapps and the rest of the OWA system.
'''Stored Data:'''
The mediator class stores no data.
'''Communication with 3rd Party Oauth Providers'''
The Share Mediator Component, via the [https://github.com/mozilla/oauthorizer oauthorizer library] communicates on behalf of the 3rd party webapp components to obtain oauth tokens.  The authentication is performed by the third party site (e.g., facebook.com) in a popup window, which calls back to a special URI that is controlled locally by the Mediator Component.
{| class="wikitable"
|-
|-
| ''Out:''
! Direction
| setAuthorization
! Message
| none
! Data
|
! Notes
|-
| ''In:''
| confirm (2)
| page data(3)
| called when the user clicks "send"
|-
|-
| ''Out:''  
| ''Out:''  
| confirm
| permission request
| success/error of send
| app_id
|  
|
|-
|-
| ''In:''  
| ''In:''
| logout/clearCredentials
| return from permission request
| none
| oauth token
|
| token is stored in 3rd party webapp's localstorage (in browser)
|-
| ''Out:''
| logout/clearCredentials
| none
|
|}
|}




'''Communication with mediator class'''  
'''Communication with 3rd Party Email Servers (via SMTP)'''


These are all uni-directional calls with the exception of the oauth and sendEmail calls.  The implementation of these APIs are in the openwebapps addon (see servicesapi.js).
To send messages, the Share Mediator Component employs SMTP communication with 3rd party email servers (google mail for starters).  The component obtains oauth tokens via the oauth protocol (previous section) and uses those and SMTP to send messages.


{| class="wikitable"
{| class="wikitable"
Line 353: Line 358:
! Data  
! Data  
! Notes
! Notes
|-
| ''In:''
| service.origin
| origin
| provides the app origin the code we inject into the service iframe, kind of an init for our injected code
|-
|-
| ''Out:''  
| ''Out:''  
| service.ready
| EHLO
| app origin
| hostname ("localhost")
| same as origin in postMessage api
|
|-
|-
| ''In:''
| service.registerHandler
| none
|  
|  
| STARTTLS
|
| Triggers TLS/secure communication with mail server
|-
|-
| ''Out:''
|  
| service.registerHandler
| AUTH
| origin, activity and message
| "xoauth" and token
| all strings used by mediator to call a specific handler (e.g. url, "link.send", "confirm")
| Authenticates the user to the SMTP server
|-
|-
| ''In:''
|  
| oauth.call
| MAIL FROM
| results returned by call to oauth endpoint
| email address
|  
|  
|-
|-
| ''Out:''
|  
| oauth.call
| RCPT TO
| auth service information, user tokens, url to oauth endpoint, parameters (share data)
| sharing targets
| for oauth call which are sent to oauth endpoints
|  
|-
|-
| ''In:''
| sendEmail.call
| simple success/failure object
|  
|  
| DATA
| URL, etc
| Contents of the share message
|-
|-
| ''Out:''  
| ''In:''
| sendEmail.call
| return from various SMTP commands
| user oauth tokens, share data, recipients list
| return codes
|  
| either error or success
|}
|}


=== mediator class  ===


The mediator class serves two purposes; 1) managing the mediator panel and mediator APIs, 2) acting as a tunnel between the service iframes and the rest of the OWA system.
'''Communication with 3rd party webapp components'''


'''Stored Data:'''  
''This mirrors the "Communication with Share Mediator Component" section of the 3rd party webapp component. See that section for the details of this communication.''


The mediator class stores no data.


'''Communication with mediator content'''  
'''Communication with Share Mediator Panel'''  


{| class="wikitable"
{| class="wikitable"
Line 415: Line 413:
| owa.app.ready
| owa.app.ready
| origin
| origin
| one call for each service iframe, received after the service iframe has called owa.service.ready
| sends one call for each service iframe, received after the service iframe has called owa.service.ready
|-
|-
| ''Out:''
|
| owa.mediation.setup
| owa.mediation.setup
| activity object, services list, caller href
| activity object, services list, caller href
| data necessary to setup the mediator UI and load service iframes
| data necessary to setup the mediator UI and load service iframes
|-
| owa.mediation.doLogin
| authorization credentials if any (e.g. oauth user tokens)
| response from doLogin
|-
| owa.mediation.reconfigure
| none
| sent to mediator content to reconfigure (e.g. a share app was installed or removed)
|-
|-
| ''In:''  
| ''In:''  
Line 427: Line 435:
| called by mediator content after load is finished
| called by mediator content after load is finished
|-
|-
| ''In:''
|
| owa.mediation.sizeToContent
| owa.mediation.sizeToContent
| width,height
| width,height
| request the mediator class to resize the panel to fit the content
| request the mediator class to resize the panel to fit the content
|-
|-
| ''In:''
|
| owa.mediation.onLogin
| owa.mediation.onLogin
| auth configuration received from service iframe, may contain consumer oauth key/secret
| auth configuration received from service iframe, may contain consumer oauth key/secret
| requests mediator class to manage logging in for a service
| requests mediator class to manage logging in for a service
|-
|-
| ''Out:''
|
| owa.mediation.doLogin
| authorization credentials if any (e.g. oauth user tokens)
| response from doLogin
|-
| ''In:''
| owa.success
| owa.success
| none
| none
| sent upon successful send
| sent upon successful send
|-
|-
| ''In:''
|
| owa.failure
| owa.failure
| failure message
| failure message
| sent upon failure to send
| sent upon failure to send
|-
| ''Out:''
| owa.mediation.reconfigure
| none
| sent to mediator content to reconfigure (e.g. a share app was installed or removed)
|}
|}


'''Communication with service iframes'''
= User Data Risk Minimization =


In this section, the privacy champion will identify areas of user data risk and recommendations for minimizing the risk.


{| class="wikitable"
== Credentials ==
|-
There are various credentials employed in this system (oauth tokens) that are used via OWA and the 3rd party webapp components to share information.   Additionally, other users of the system could potentially have access to a user's sharing credentials. The OAuth tokens are stored in the apps localStorage.
! Direction
! Message
! Data
! Notes
|-
| ''Out:''
| service.origin
| origin
| provides the app origin the code we inject into the service iframe, kind of an init for our injected code
|-
| ''In:''
| service.ready
| app origin
| same as origin in postMessage api
|-
| ''In:''
| service.registerHandler
| origin, activity and message
| all strings used by mediator to call a specific handler (e.g. url, "link.send", "confirm")
|-
| ''In:''
| oauth.call
| auth service information, user tokens, url to oauth endpoint, parameters (share data)  
| for oauth call which are sent to oauth endpoints
|-
| ''Out:''
| oauth.call.CALL_ID
| results returned by call to oauth endpoint
|
|-
| ''In:''  
| sendEmail.call
| user oauth tokens, share data, recipients list
|
|-
| ''Out:''
| sendEmail.call.CALL_ID
| simple success/failure object
|
|}
 
=== OWA stuff  ===


OpenWebApps provides the ability for content to install an "app" which may also include a "services" component using the Web Activities APIs.  fx-share-addon relies on the Web Activities/services functionality for extensibility.
''The Risk'' is that these credentials might be leaked across third parties or to other users of the system.


* currently we have disabled all UI and ability to externally install any web apps.
''Requirement:'' These credentials are stored by the 3rd party webapp components who use them and only those components (and the browser, extended by the Share Mediator Component) should be able to touch them. Any non-oauth credentials should be stored in the password database (not localstorage) and, when possible, encrypted using the browser's master password.
** Only the fx-share mediator UI is available to the user. 
** Web content does not have the ability currently to instantiate the share mediator, only UI in chrome (the share button in the url bar) can show the UI.


{{ResolutionBox|{{resolved|This software only ships with 3rd party webapps that use oauth and store the tokens in localstorage so there is no threat of password leak.  When we open F1A to allow users to install additional apps, we will make clear in the documentation how to store different types of credentials properly.}}}}


'''Stored Data:'''
== Clearing Private Data ==
Anything stored persistently should be cleared when the user clears that type of data elsewhere in the browser.  For example, when a user clears stored passwords, any passwords that are stored for purposes of sharing should be cleared.  The oauth tokens should be removed when the user clears cookies or passwords (since they are related to both).


{| class="wikitable"
''The Risk'' is that, while the user may think he is "resetting" credentials stored in his browser, this may not be the case if the 3rd party webapps don't store data in the right place or erase it at the right time.
|-
! What
! Where
|-
| manifest data for apps
| sqlite database
|}


'''Communication with Component Y'''  
''Requirement:'' when stored passwords in the browser are cleared, the webapps should delete passwords.  Oauth tokens should be deleted when users clear "active logins".  Contacts and other account data should be erased when the user clears localstorage.


{| class="wikitable"
''Recommendation:'' if a user has not set up Firefox to remember passwords, no passwords should be stored in localstorage by the share add-on or its webapp components (they can be retained in memory, but lost when Firefox is closed).
|-
! Direction
! Message
! Data
! Notes
|-
| ''In:''  
| message 1
| types of data received from component Y with the message
|
|-
| ''Out:''
| message 2
| types of data sent to component Y with the message
|
|}


=== oauthorizer  ===
{{ResolutionBox|{{resolved|oauth tokens are stored in localStorage and are cleared when users click logout or clear browser's localStorage. Oauth tokens stored by this addon's apps are purged when users clear "active logins".}}}}


OAuthorizer provides simple APIs for initiating OAuth login/authorization flow and calling OAuth version 1 and 2 based APIs.  In our use of oauthorizer, a service iframe makes a call which is received by the mediator classThe mediator class passes that to oauthorizer which makes the oauth call and returns the response.
== Browsing History ==
A subset of the user's browsing history is exposed to third party servicesThis is done through the core UI and functionality of the product.


* future changes
''The Risk:'' the user will knowingly provide third parties with insight into what sites they've visited in the past.  Browsing history is generally considered to be private, and the disclosure of such data should be calculated.  This is a very tiny risk since the whole point of this feature is to share URLs.  Nonetheless, the risk is there and unless the user is always at the helm when data sharing happens, it could be leaked without consent.
** remove ability to store credentials completely
** remove content-available API and make available only to mediated openwebapps


'''Stored Data:'''
URLs shortened through a URL shortening service are disclosed to that service.  If third-party URL shortening services are used (shorteners not part of the service used for sharing), it must be clear what is happening.


While oauthorizer can be used to store OAuth credentials, in our use it does not.   
''Requirement:'' The UI must clearly show each URL being shared and with which parties the URL will be shared before it is transmitted.  If an additional URL shortening service is used, there must be user intervention before the URL is sent to the service for shortening.  (UI can be used to "remember" the user's preference to shorten URLs, but that must be opt-in).   


'''Communication with Component Y'''
{{ResolutionBox|{{resolved|UI is clear about with whom users are sharing URLs.  Twitter uses its own in-house shortening on the server-side (their end).}}}}


{| class="wikitable"
=Conformity to Private Browsing Mode (If Applicable)=
|-
Since sharing is an explicitly user-initiated action (like bookmarking), it can remain available during a private browsing mode.
! Direction
! Message
! Data
! Notes
|-
| ''In:''
| message 1
| types of data received from component Y with the message
|
|-
| ''Out:''
| message 2
| types of data sent to component Y with the message
|
|}


= User Data Risk Minimization =
''Recommendation'': During a private browsing session, any data automatically obtained (and stored in the webapp components' localstorage) should be retained in volatile memory only.  This is data that the user doesn't explicitly ask for, such as automatically synced contacts.  New account setup data and other data explicitly "installed" by the user to be stored can be kept (as we do with sync).  The data stored in volatile memory during private mode should be "rolled back" or erased when private mode is exited.


In this section, the privacy champion will identify areas of user data risk and recommendations for minimizing the risk.
{{ResolutionBox|{{resolved|since the 3rd party webapps use the usual HTML cookies and localstorage, these will be managed by the private browsing service automatically.}}}}


= Alignment with Privacy Operating Principles =
= Alignment with Privacy Operating Principles =
Line 587: Line 505:


====Principle: Transparency / No Surprises====
====Principle: Transparency / No Surprises====
(How the feature addresses this)
It's pretty clear that this feature is sharing a URL with a third party service, and the UI seems to clearly explain with whom.  F1 is Transparent and not really surprising.
 
''Recommendations'': (what can be improved)


''Recommendations'': none


====Principle: Real Choice====
====Principle: Real Choice====
This product doesn't retain data not explicitly provided by the users.  It's off by default, and does nothing until users authenticate to their services.


''Recommendations'':  
''Requirement'': Provide a way to "forget" or disconnect from a service that has been used for sharing. -mixedpuppy: there is a logout button under the profile picture for each service which clears localstorage (including oauth tokens) for that service.
 


====Principle: Sensible Defaults====
====Principle: Sensible Defaults====
This feature is off by default.


''Recommendations'':
''Recommendations'': none


====Principle: Limited Data====
The data retained is only that used for sharing (and contact auto-complete).  No extra data is retained.


====Principle: Limited Data====
''Recommendations'': none.


''Recommendations'':
{{ResolutionBox|{{resolved|there is a logout button in the Share Mediator Panel}}}}


= Follow-up Tasks and tracking =
= Follow-up Tasks and tracking =
Line 614: Line 534:
! Details
! Details
|-
|-
| {{new|Initial Overview Discussion}}
| {{done|Initial Overview Discussion}}
| ?
| Sid & Shane
|  
|  
| Meeting time TBD
| Various meetings and iterations.  Completed 7-Oct-2011.
|-
| {{done|Discuss Recommendations}}
| Sid & Shane
|
| Async via email
|-
| {{done|verify data flow with [[#Share_Mediator_Component|SMTP and Oauth servers]]}}
| Mark Hammond
|
|
|-
| {{done|update add-on to purge oauth tokens (via logout() call) when user clears "active logins" via browser's "clear recent history" dialog}}
| Shane
| {{bug|695259}}
|
|-
| {{drop|<strike>disclose URL shortening in Twitter share UI, perhaps "about url shortening" linking to [http://support.twitter.com/entries/109623]</strike>}}
| Shane
|
| Unnecessary, Twitter uses their own shortener.
|}
|}




[[Category:Privacy/Reviews|Template]]
[[Category:Privacy/Reviews|F1A]]
canmove, Confirmed users
1,537

edits