4

I'm creating a mobile app in Ionic (which uses Angular). I've set up a D8.3-dev BE which will hold the users and their data.

I've figured out how to register as an anonymous user (this is why I'm using D8.3-dev because this functionality is introduced here) and wrote a blog post about it (https://fonsvandamme.be/en/blog/how-create-user-rest-drupal-8).

Logging in also works after I registered a user.

This is how I login:

  /*
   * Login User with username and password.
   */
  login: function (email, password) {

    var defer = $q.defer();

    $http({
      method: 'POST',
      url: config.endpoint + '/user/login?_format=json',
      data: {
        name: email,
        pass: password
      },
    })
      .success(function (data, status, headers, config) {

        // Store the CSRF token.
        localStorage.set('csrf_token', data.csrf_token);

        // Store the Logout token
        localStorage.set('logout_token', data.logout_token);

        // Set the user object.
        localStorage.setObject('user', data.current_user);

        defer.resolve(data);
      })
      .error(function (data, status, headers, config) {
        defer.reject(data);
      });

    return defer.promise;
  },

When logging in I receive the following:

current user object, a csrf_token and a logout_token.

When I use these tokens to logout (I tried a lot of different ways already:

  /*
   * Logout User.
   */
  logout: function () {

    var defer = $q.defer();

    $http({
      method: 'POST',
      url: config.endpoint + '/user/logout?_format=json&token=' + localStorage.get('csrf_token'),
      dataType: 'json',
    })
      .success(function (data, status, headers, config) {
        defer.resolve(data);

        // Go to the login page.
        $state.go("login");
      })
      .error(function (data, status, headers, config) {
        defer.reject(data);
      });

    return defer.promise;
  },

I keep getting the following error:

{"message":"\u0027csrf_token\u0027 URL query argument is invalid."}

So it seems the crsf_token I use from logging in isn't correct.

What am I doing wrong or overseeing here?

EDIT: after testing a lot and trying it seems like I need to use get. I use this code now for logout but I still get a 403:

  /*
   * Logout User.
   */
  logout: function () {

    var defer = $q.defer();

    $http({
      method: 'GET',
      url: config.endpoint + '/user/logout?_format=json',
      headers: {
        'X-CSRF-Token': localStorage.get('csrf_token'),
        'Authorization': 'Basic xxxxxxxxx',
      },
    })
      .success(function (data, status, headers, config) {
        defer.resolve(data);
      })
      .error(function (data, status, headers, config) {
        defer.reject(data);
      });

    return defer.promise;
  },

Here is what the Drupal 8.3-dev BE returns, it seems like it recognizes the user I want to log out but it's still throwing the 403.

enter image description here

0

3 Answers 3

5

To logout using REST in Drupal 8, you can do a POST to:

https://example.com/user/logout?_format=json&token=logout_token

Use the following headers on your request:

  • Content-type: application/json
  • X-CSRF-Token: csrf_token

The values for logout_token and csrf_token are available in the login response.

Be sure to visit admin/config/services/rest and enable the following for the User resource:

  • methods: POST
  • formats: json
  • authentication: cookie

Earlier versions of Drupal 8

Do a GET on ?q=user/logout

This is noted in the JS D8 REST docs: https://www.drupal.org/docs/8/core/modules/rest/javascript-and-drupal-8-restful-web-services

Although it should not matter, the Content-type may need to be set to application/x-www-form-urlencoded.

Here's an example usage from jDrupal: https://github.com/signalpoint/jDrupal/blob/8.x-1.x/src/includes/rest.inc.js#L113

11
  • I tried this but with and without the token in the url I get a 403 forbidden with {"message":""} Commented Jan 11, 2017 at 7:50
  • 1
    Do you have an example because this doesn't work. Commented Jan 12, 2017 at 7:04
  • I've updated my answer with some more details and a link to example usage. Commented Jan 12, 2017 at 15:31
  • I keep getting a 403. I have updated my question. Commented Jan 12, 2017 at 16:12
  • Perhaps removing the X-CSRF-Token from both the Login and Logout resources will do the trick. Have you considered moving to a Cookie based authentication? Commented Jan 13, 2017 at 1:06
1

It seems to work now after adding this into my Angular App under app.js

.config(['$httpProvider', function($httpProvider) {
    $httpProvider.defaults.withCredentials = true;
}])
0

Still having problems to get a REST logout to work. Creating a simple rest\resource workes well.

<?php

namespace Drupal\MYMODULE\Plugin\rest\resource;

use Drupal\rest\Plugin\ResourceBase;
use Drupal\rest\ResourceResponse;
use Symfony\Component\HttpFoundation\Request;
use Drupal\Core\Session\SessionManagerInterface;

/**
 * Provides a resource to log a user out.
 *
 * @RestResource(
 *   id = "custom_logout_resource",
 *   label = @Translation("API - Custom Logout Resource"),
 *   uri_paths = {
 *     "canonical" = "/api/logout"
 *   }
 * )
 */
class CustomLogoutResource extends ResourceBase {

  /**
   * The session manager.
   *
   * @var \Drupal\Core\Session\SessionManagerInterface
   */
  protected $sessionManager;
  /**
   * Responds to GET requests.
   *
   * @return \Drupal\rest\ResourceResponse
   */
  public function get() {
    user_logout();

    // Return a response indicating success.
    return new ResourceResponse(['message' => 'Logged out successfully.']);
  }

}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.