liqd / adhocracy3

Adhocracy 3 with customizations for various projects
https://adhocracy3.readthedocs.io
Other
50 stars 11 forks source link

Concepts for weak anonymity #2212

Closed pallix closed 8 years ago

pallix commented 8 years ago

Introduction

This document is a starter to discuss a solution to provide weak anonymity in adhocracy 3 when creating proposals or comments.

Definition

Weak anonymity: provides anonymity between an anonymous user and other users of the platform but not between the user and the system administrator.

Real creator: the user that created the resource (in opposition to the value 'creator' of the metadata).

Requirements

Notes: most of these requirements are about information hidding.

Additional requirements

Eventually

These last requirements are an answer to the following threat:

CEO of EvilCorp asks the system administrator of the platform to reveal the
name of the employee who wrote anonymously a comment
critizing him. The demand is asked after n days.

To clarify: if the threat is meaningful.

Proposed solution for the backend

Global 'anonymous' user

First a global user named 'anonymous' [1] is created on the platform, such as the admin account. This user has no permission and is not used by any real users but acts as a placeholder / marker for resources created anonymously.

Note that we do not have any 'anonymous' role anymore in the backend so there is no real confusion possible ; also we do not give any anonymous-like (it's called "everybody" role now) permissions to the user.

Marker sheet for resources

We create a marker sheet that indicates resources that can be created anonymously. The sheet is named 'CanBeAnonymous' and contains a boolean field 'anonymous'.

When the frontend needs to create a resource anonymously for the logged-in user, the frontend set the 'anonymous' field to 'true' for the POST request.

Factory resources

The resource factory of the backend is modified as follows:

When a resource has a CanBeAnonymous sheet with the field 'anonymous' set to true, the creator field of the metadata is set to references the anonymous user of the platform.

A "get creator" adapter can be created to dynamically get either real creator or anoymous user depending of the context and of the value of the CanBeAnonymous sheet.

Mapping between resource and creator

To allow the user to edit its anonymously created resources, a mapping between the user and the resource must be kept on the backend without being revealed by the API. This is actually already done in the backend: the mapping is created in resource.__local_roles__.

Platform switch for anonymity

We can have a boolean in the configuration and throws an error message when validating POST request if the frontend tries to create an anonymous resource when the boolean is false.

Consideration regarding the REST API

PUT requests changing the value of the CanBeAnonymous sheet should probably be avoided to avoid a user putting its resource as anonymous afterwards.

Additional requirements implementation

Can be implemented with a script deleting __local_roles__ for anonymous resources mapping after n days.

Security

The biggest threat is leaking the real user to the others users of the platform.

Since __local_roles__ are not exposed in the API and the 'creator' metadata field is set to 'anonymous' for anonymous resources, all the catalog indexes and API queries should not be able to leak the real creator.

General comments

This solution requires a minimal change to the factory and no change to the catalogs and API. It does not require special measures to avoid leaking the real creator on the API or frontend and allows to implement all requirements.

Maybe I forgot some things, or there are some other security threats. I would be happy to have some feedback.

Notes

[1] if you have a better name's idea, please suggest it as a comment below

pallix commented 8 years ago

@nidico @joka @xi @slomo please have a look and comment!

xi commented 8 years ago

I can not say much about the proposed backend implementation, but the writeup seems to be pretty complete to me. Nice job!

slomo commented 8 years ago

Why aren't we exposing the local roles? Is that a missing feature or a design decision?

pallix commented 8 years ago

There is no need for that as local roles are only used for permission checks.

xi commented 8 years ago

We may have to expose a bit more of the permission system when we add user management. Will this be an issue?

pallix commented 8 years ago

I was thinking about that too. We probably want to allow users with the admin role to specify __local_roles__ for resources.

  1. if we want to allow that to only some resources, like processes, then there will be no information leak for proposals / comments.
  2. if we want to allow that for any arbitrary resources then 'admin' could deanonymize an anonymous resource. If we find that it is okay for our security model, then it's okay by definition. (Keep in mind that system administrator can always deanonymise anyway). If it's not ok we may want to have a separate field for the mapping like __real_creator__ which we do not expose. We then need to extend the authorization code in the backend.
joka commented 8 years ago

looks fine, but I did not manage to read it properly yet.

This subject is also part of the epic concept story: how to implement thentos features with adhcoracy. https://tree.taiga.io/project/ggr-meinberlinteam/us/148 I propose we add a meta issue for Anonymitiy/Pseudonymity and user profile data.

joka commented 8 years ago

I was thinking about that too. We probably want to allow users with the admin role to specify local_roles for resources.

This is also part of the substanced sdi story "admin wants to set local roles for groups" https://tree.taiga.io/project/ggr-meinberlinteam/us/153?no-milestone=1

joka commented 8 years ago

Could you point out what is the user story/motivation we want to match?

pallix commented 8 years ago

@joka https://tree.taiga.io/project/evpa-euth/us/137

joka commented 8 years ago

"weak anonymity" looks like a pseudonym shared by all users. We should make the concept work well with the upcoming "Personas/User Pseudonyms" story.

slomo commented 8 years ago

There is an other case where we might need to expose local roles: When we establish a process membership. So that users can become members of organisation or a process. The most straight forward way for now would be to expose the local roles (but maybe only for the mentioned content types).

fisx commented 8 years ago

"weak anonymity" looks like a pseudonym shared by all users.

Interesting. So far I've always understood "pseudonym" as a name that cannot be shared between users, but dropping that restriction would allow for nice applications like this, and possibly better (weak) anonymity.

nidico commented 8 years ago

Looks good.

I'm not really happy about keeping the mapping between resource and user in the first place, but clearly this is the way to make sure that (only) the creator can edit her own proposal.

As editing is only relevant for a short amount of time and might not be relevant in some scenarios, I'm very much in favor of allowing to disconnect the mapping between creator and resource of anonymous resources later on.

In the case of S1, I'd propose to trigger these disconnections as a side effect of the S1 process workflow switch.

joka commented 8 years ago

As mentioned the crucial part is the connection between creator and real creator, this is also an outcome of the PAAS user research. Adding and then hiding or maybe later removing the connection does not sound trustworthy from a user point of view.

nidico commented 8 years ago

I Propose we don't do it at all. We just give the anonymous user the same roles as a normal participator.

This would mean that everybody can add anonymous content, though this should be restricted to the participatants of the team, so this isn't really an option.

Or am I wrong?

joka commented 8 years ago

This would mean that everybody can add anonymous content, though this should be restricted to the participatants of the team, so this isn't really an option.

no, this would only be the case if you can login as anonymous user. The only difference is that the anonymous resources cannot be edited at all or by all paticipants. I guess cannot be edited is more intuitive.

nidico commented 8 years ago

no, this would only be the case if you can login as anonymous user.

What does "login as an anonymous user"? Authenticate as anonymous while being logged in as a normal user?

Does this allow

The only difference is that the anonymous resources cannot be edited at all or by all paticipants. I guess cannot be edited is more intuitive.

I'd be personally fine with not storing the connection in the first place, however the outcome of the discussion in the PaaS consortium was that it's important to store the connection for a while to allow editing, and remove the connection later (e.g. every night or on phase switch in S-1).

However there's a stronger argument in favor of storing the creator together when posting a certain resource type: ratings. Storing the connection would allow to rate anonymously basically the same way as ratings work currently. There might be other solutions, but they'd be much more complex. If anybody has a simple alternative idea, I'm curious.

In my opinion allowing to rate anonymously is almost as important as posting anonymously in a process like S-1 - so this is the argument which convinced me that storing the resource does more good than harm. But we should really make sure to remove the connection as early as possible.

joka commented 8 years ago

Ok, we need to store the connection, but should make it configurable.

I forget to mention that there are more issues with the original proposed implementation:

I had a talk with @2e2a and we came up with the following solution, this also explains "login as anonymous users":

Create:

  1. client sends "options" request to check if he may set the "X-Anonymize" header to post anoymous
  2. clients sends "post" request with "X-Anonymize" header
  3. server sets the request attribute "user" to the anonymous user and "anoymized_user" to the real users.
    That means the real user is used for authentication/authorization only, the anonymous user for everything else
  4. server creates the resource and sets the hidden resource attribute anonymized_creator instead of the local role "creator"

Edit

  1. same with "put"
  2. same with "put"
  3. same, authorization adds dynamically the local role "creator" if "anonymized_creator" matches the current "anonymised_user". The attribute value is stored only for a certain time, checked on access (configurable).
    This allows us to delete or prolong the mapping between creator and resource as wanted
  4. server edits the resource as usual

Delete

same with "delete"

xi commented 8 years ago

What about GET/OPTIONS requests? Will the X-Anonymize header be silently ignored?

And what about batch requests?

joka commented 8 years ago

GET / OPTION request with X-Anonymize does not make sense, but is ignored. POST/PUT/DELETE request with Anonnyize header raises error if not allowed.

Batch requests uses the same Anonymize header for all subrequests, so you should only add subrequests with allowed anonymize header.

joka commented 8 years ago

How does the frontend know if X-Anonymize header is forced?

Maybe this is better solved in the backend only, or we use the list of possible header values in the options response, but this does not sound right.

joka commented 8 years ago

What about special endpoints like "report_abuse" ?

The backend needs the real user to send the abuse message. Apart from this the action is not stored in the database or in the audit log. So the X-Anonymize header with the current implementation does not make much sense.

xi commented 8 years ago

How does the frontend know if X-Anonymize header is forced?

Maybe this is better solved in the backend.

I disagree. The user should be able to know whether an action is anonymous or not. So the frontend needs to know.

joka commented 8 years ago

I disagree. The user should be able to know whether an action is anonymous or not. So the frontend needs to know.

right, to reuse the UI,
we could add this information to options response, process settings or the global frontend config.

2e2a commented 8 years ago

Implemented in #2609