Third & GroveThird & Grove
Jun 27, 2014 - Mike DeWolf

Creating Users in Drupal with the Services Module’s REST API

Recently, for a client project, we needed to be able to authenticate users in Drupal from a mobile app built by another team. Contrib to the rescue. We found the Services module to be excellent for this. We were able to easily create a full REST API and give it access to the Drupal entities we needed. One thing we found, however, was that documentation was spotty, and spread throughout the web in various forum threads. How we eventually sorted everything out was equal parts googling and hands-on discovery.

As such, we thought it would be nice to offer to all a description of what we did: how to authenticate a user, create a user, and create a user with certain non-standard privileges (something only a site admin could do).

There is already plenty out there about setting up a services endpoint so I won’t be going into that here. This one is excellent: http://pingv.com/blog/an-introduction-drupal-7-restful-services, but there are many others. A quick google search will reveal scores of them.

For testing the services rest API, I’ve found the best tool to be the firefox RESTClient add on. You can download it here. Since Drupal stores authentication information in cookies, the firefox add-on is ideal. It allows you to use the firebug inspection tool to troubleshoot requests and responses. Also, when you log in via the API, your authentication is stored as a firefox cookie, allowing you to delete it and log yourself out with ease. You can also see confirmation of the success or failure of your log in attempt by visitng the website after in firefox.

On to the API. Logging in is the easiest of all. For the project I’ve mentioned, we were using logintobbogan because it allows users to use their email address as their username. Logintobbogan also comes prepackaged with its own custom services resource. Using the rest client, we POST a simple json package to our {your-endpoint}/user/logintobbogan.

A sample json might look like this:

 

{
"username": "[email protected]",
"password": "password123"
}

 

Of note is that for all requests, we included the Content-Type: Application/json header.

A successful login returns something like this:

 

sessid: nHzm9uHDixQdIJJbdLe5OazgZWFhcVbNlKFtSqUahfA
session_name: SSESSc5c37851bde2cc4cc2ec3939043dad7f
token: qwull3HjCn76BMPSbrqtfkg4MXsnjg5XrEwRwnqmlUw

 

This is your session id in Drupal (stored in a cookie for a normal login), as well as a Cross Site Request Forgery Token. We’ll come back to these in a bit.

On to creating users. Once the user create resource has been activated through the services GUI, you simply POST the user account fields, as they appear in the user object to {your-endpoint}/user. You only need to POST the fields that appear on your sites registration form. Thus, for the default, all you would need is:

 

{
"name": "johndoe"
"mail": "[email protected]",
}

 

And that will create a new Drupal user. If you have some non-standard fields, you simply add these to the json in the exact same format as they are in the drupal account object. Another example:

 

{
"name": "johndoe"
"mail": "[email protected]",
"pass": "password",
"field_favorite_food": {
"und": {
"0":{"value":"Pizza" }
}
}
}

 

Interestingly, any custom validation messages you have on you actual login form will come in the services response as well. In the above example, if favorite food is required on your registration form, and you don’t post it to the rest endpoint, your response might include:

 

Field favorite food is required.

 

It is very cool to see once it is all working.

Lastly, for the project I’ve mentioned, we needed to be able to create users with special roles that only an administrator could assign. To do this, we needed to authenticate as someone with the “administer users” permission via the services API as part of our request to create the account. Only then could we modify account fields that normal users don’t have access to.

The basic create user request is the same, but the process is a little more complicated as you must supply some additional headers.

Initially, you must log in as an admin user with the first endpoint, POST /mobileapp/user/logintoboggan. Once this is done, you will obtain the session_name, sessid, and token outlined in the example response for that endpoint.

The correct headers are as follows to authenticate ourselves as a user with the “Administer Users” permission.

 

Cookie: {session_name}={sessid};
X-CSRF-Token: {token}

 

So as in the example above these would look like:

 

Cookie: SSESSc5c37851bde2cc4cc2ec3939043dad7f=nHzm9uHDixQdIJJbdLe5OazgZWFhcVbNlKFtSqUahfA;
X-CSRF-Token: qwull3HjCn76BMPSbrqtfkg4MXsnjg5XrEwRwnqmlUw

 

In this request we can now specify values for any additional account fields that ordinary authenticated users can’t edit. The example below creates a new admin account:

 

{
"name": "johndoe"
"mail":"[email protected]",
"pass": "password",
"field_favorite_food": {
"und": {
"0":{"value":"Pizza" }
}
}
"roles": {
"1": "1"
}
}

 

UPDATE (12/2/2014): Logintoboggan does not come prepackaged with a services resource. We are using this patch: https://www.drupal.org/files/logintoboggan-services-1431724-5.patch. Many thanks to Michael in the comments for pointing this out!