Background
In D8 the default access settings are simple: there is a single 'administer users' permission that controls editing other users.
More complex schemes are possible using contrib modules to allow selective editing of other users under certain conditions. An example of such a module is Administer Users by Role. I am the maintainer of this module, trying to port it to D8.
Problem
contrib modules cannot grant field-level access to some fields on the user. For example, in a view of users, the "status" column will not be present except to a user with 'administer users' permission.
- The code in the contrib module can implement hook_ENTITY_TYPE_access() for entity type "user" which works to allow editing of the user.
- The code in the contrib module can implement hook_entity_field_access, but this doesn't work because the default code in UserAccessControlHandler has set AccessResult::forbidden().
The documentation here states
Note: Even a single module returning an AccessResultInterface object from hook_node_access() whose isForbidden() method equals TRUE will block access to the node. Therefore, implementers should take care to not deny access unless they really intend to. Unless a module wishes to actively forbid access it should return an AccessResultInterface object whose isAllowed() nor isForbidden() methods return TRUE, to allow other modules or the node_access table to control access.
Solution
UserAccessControlHandler should set AccessResult::neutral. This prevents access by default, but allows other modules to override.
The password field is an exception because it should be forbidden for any user to read it under any circumstances.
Patch coming.