Hello, when I access to the /user/user endpoint I can see a list with all the users registered in Drupal.

In the documentation, there is a note indicating that if I access this URL it will result in an HTTP 403 error, but there is a list of usernames instead which could be dangerous.

{
    "data": [
        {
            "type": "user--user",
            "id": "062ca030-8911-427b-a527-1505ee49f69f",
            "links": {
                "self": {
                    "href": "http://docker.localhost:8000/api/user/user/062ca030-8911-427b-a527-1505ee49f69f"
                }
            },
            "attributes": {
                "name": "Anónimo"
            }
        },
        {
            "type": "user--user",https://www.drupal.org/project/drupal/issues/3240913
            "id": "c1813407-e188-42b5-a9ca-672f08fdcc2b",
            "links": {
                "self": {
                    "href": "http://docker.localhost:8000/api/user/user/c1813407-e188-42b5-a9ca-672f08fdcc2b"
                }
            },
            "attributes": {
                "name": "admin"
            }
        },
        {
            "type": "user--user",
            "id": "08b880da-4fe0-45e6-b3b1-d0a7d89b4f93",
            "links": {
                "self": {
                    "href": "http://docker.localhost:8000/api/user/user/08b880da-4fe0-45e6-b3b1-d0a7d89b4f93"
                }
            },
            "attributes": {
                "name": "api_user"
            }
        }
    ],
    "jsonapi": {
        "version": "1.0",
        "meta": {
            "links": {
                "self": {
                    "href": "http://jsonapi.org/format/1.0/"
                }
            }
        }
    },
    "links": {
        "self": {
            "href": "http://docker.localhost:8000/api/user/user"
        }
    }
}

Comments

artem_antonov created an issue. See original summary.

Wim Leers’s picture

Category: Bug report » Support request
Issue summary: View changes
Status: Active » Fixed
Issue tags: +API-First Initiative

Note only user's names are revealed. Nothing else. Names are always allowed to be read, also on any "regular" (HTML) Drupal site.

See https://www.drupal.org/node/2983616

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.

David Spiessens’s picture

This is indeed dangerous and in the current privacy context not acceptabele as default behaviour. What's the easiest fix for this? Maybe interesting to launch as a little contrib module...

artem_antonov’s picture

Finally, I got managed this with a custom module in order to hide the name and mail fields if the user don't have "access user profiles" permission:


use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Session\AccountInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Access\AccessResult;

/**
 * Implements hook_entity_field_access().
 *
 * Deny access to mail and name fields if user have not permissions to view
 * them.
 */
function my_module_api_access_control_entity_field_access($operation, FieldDefinitionInterface $field_definition, AccountInterface $account, FieldItemListInterface $items = null)
{
    $is_own_account = $items ? $items->getEntity()->id() > 0 && $items->getEntity()->id() == $account->id() : false;
    if (in_array($field_definition->getName(), ['mail', 'name']) && $operation == 'view' && ($items && $items->getEntity()->getEntityTypeId() == 'user')) {
        return $is_own_account || $account->hasPermission('access user profiles') ? AccessResult::allowed()->cachePerUser() : AccessResult::forbidden()->cachePerPermissions();
    }

    return AccessResult::neutral();
}

e0ipso’s picture

This is indeed dangerous and in the current privacy context not acceptabele as default behaviour. What's the easiest fix for this? Maybe interesting to launch as a little contrib module...

I don't think usernames are private data, but in any case this is configurable so you can deny access to it if your site considers them private data.

Finally, I got managed this with a custom module in order to hide the name and mail fields if the user don't have "access user profiles" permission:

Just to clarify anyone landing here. The email was private all along. The only data publicly accessible by default in the user resource is the username, not the email.

artem_antonov’s picture

I don't think usernames are private data, but in any case this is configurable so you can deny access to it if your site considers them private data.

In one of our projects, we are copying the email address field into username field to use it as login when the user registers and if we do not restrict the access to the username it will display the email address, for this use case is useful to hide it.

Just to clarify anyone landing here. The email was private all along. The only data publicly accessible by default in the user resource is the username, not the email.

The reason for use this hook is another issue as Drupal not allows to access the mail field if the user is not the same who is making the request and we want to show all users mail address if the user who is making address have a permission to access user profiles.

sjpeters79’s picture

If you need to disable the json_api/user/user resource, you can do so using jsonapi_extras module:
https://www.drupal.org/project/jsonapi_extras

This will allow for the disabling and overriding of existing resources.

joshua.boltz’s picture

Is it possible for a non-admin user to see the user email in JSON API?

rudam’s picture

That is what I'm using to show account info only to owners or permission 'administer user'

function view_user_info_permission_user_access(EntityInterface $user, $operation, AccountInterface $account)
{
    // Admin account sees all.
    if ($account->id() == 1) {
        return AccessResult::allowed();
    }
    // Do not show anon account info because it is useless.
    if (!$account->isAnonymous()) {
        //  Display account info only to owner or roles with 'administer users' permission.
        if ($user->id() == $account->id()) {
            return AccessResult::allowed();
        }
        if ($account->hasPermission('administer users')) {
            return AccessResult::allowed();
        }
    }

    return AccessResult::forbidden()->cachePerUser();
}
jbguerraz’s picture

Exposing usernames is clearly not good:
- privacy: one could know you're a member of a site
- security: it gives half of the key

Disabling the resource is not a solution: you could need that resource

#11 is an acceptable workaround, https://www.drupal.org/project/jsonapi_permission is also one.

But, IMHO, it still needs to be fixed: JSON API should not leak any identity related information OOTB

mxr576’s picture