diff --git a/resources/user_resource.inc b/resources/user_resource.inc
index 082afe2..e7eead4 100644
--- a/resources/user_resource.inc
+++ b/resources/user_resource.inc
@@ -154,6 +154,16 @@ function _user_resource_definition() {
           'callback' => '_user_resource_logout',
           'access callback' => 'services_access_menu',
         ),
+        'token' => array(
+          'file' => array(
+            'type' => 'inc',
+            'module' => 'services',
+            'name' => 'user_resource',
+          ),
+          'callback' => '_user_resource_get_token',
+          'access callback' => 'services_access_menu',
+          'help' => t('Returns the CSRF token.'),
+        ),
       ),
     ),
   );
@@ -548,3 +558,7 @@ function _user_resource_login_update_1_1() {
   );
   return $new_set;
 }
+
+function _user_resource_get_token() {
+  return array('token' => drupal_get_token('services'));
+}
diff --git a/services.module b/services.module
index 518aa22..d25d785 100644
--- a/services.module
+++ b/services.module
@@ -399,7 +399,7 @@ function _services_sessions_authenticate_call() {
   global $user;
   $original_user = services_get_server_info('original_user');
 
-  if ($original_user->uid != 0) {
+  if ($original_user->uid != 0 && !preg_match('#/user/token$#', request_uri())) {
     $non_safe_method_called = !in_array($_SERVER['REQUEST_METHOD'], array('GET', 'HEAD', 'OPTIONS', 'TRACE'));
     $csrf_token_invalid = !isset($_SERVER['HTTP_X_CSRF_TOKEN']) || !drupal_valid_token($_SERVER['HTTP_X_CSRF_TOKEN'], 'services');
     if ($non_safe_method_called && $csrf_token_invalid) {
