Parse-server: Request.user undefined and no information in request

Created on 19 Jun 2016  Â·  21Comments  Â·  Source: parse-community/parse-server

I'm trying to access a user in cloud code so I can modify user data. I don't have access to any session tokens and request.user is undefined

Steps to reproduce

Swift:

PFCloud.callFunctionInBackground("checkUser", withParameters: nil) {
(response: AnyObject?, error: NSError?) -> Void in
let responseString = response as? String
print(responseString)
}

Main.js

Parse.Cloud.define("checkUser", function(request, response) {
console.log(request);
var user = request.user;
response.success(user);
});

Expected Results

request.user or request.user.getSessionToken() give me correct data

Actual Outcome

request.user is undefined

Environment Setup

  • Server

    • parse-server version: latest

    • Operating System: OS X El Capitan

    • Hardware: Macbook pro

    • Localhost or remote server? (AWS, Heroku, Azure, Digital Ocean, etc): Locally and AWS Beanstalk

  • Database

    • MongoDB version: latest

    • Storage engine: mLabs

    • Localhost or remote server? (AWS, mLab, ObjectRocket, Digital Ocean, etc): [FILL THIS OUT]

      Logs/Trace


error: Uncaught internal server error. [TypeError: request.user is not a function] TypeError: request.user is not a function
at /var/app/current/cloud/main.js:54:24
at /var/app/current/node_modules/parse-server/lib/Routers/FunctionsRouter.js:95:11
at new Promise (/var/app/current/node_modules/parse-server/node_modules/babel-polyfill/node_modules/core-js/modules/es6.promise.js:193:7)
at handleCloudFunction (/var/app/current/node_modules/parse-server/lib/Routers/FunctionsRouter.js:89:16)
at /var/app/current/node_modules/parse-server/lib/PromiseRouter.js:286:7
at Layer.handle as handle_request
at next (/var/app/current/node_modules/parse-server/node_modules/express/lib/router/route.js:131:13)
at Route.dispatch (/var/app/current/node_modules/parse-server/node_modules/express/lib/router/route.js:112:3)
at Layer.handle as handle_request
at /var/app/current/node_modules/parse-server/node_modules/express/lib/router/index.js:277:22

I passed the session token myself, but this doesn't seem secure

{ params: { sessionToken: 'XXXXXXXXXXXXXXXXXX' },
master: false,
user: undefined,
installationId: 'xxx-xxx-xxx-xxx',
log: FileLoggerAdapter {} }

stale

Most helpful comment

I figure it out why request.user is undefined when calling Cloud function. It's because sessionToken is not set automatically in the request when calling Parse.Cloud.run() from Cloud code (not sure the reason behind this?). To fix the problem I have to set sessionToken manually like bellow. Hope it helps someone having same problem with me.

Parse.Cloud.afterSave("TodoItem", function(request) {
  Parse.Cloud.run("fixTodoItem", {todoId: request.object.id}, {
    success: function (result) {
      console.log('Success: ', result);
    },
    error: function(error) {
      console.log('Error: ', error);
    },
    sessionToken: request.user.getSessionToken()
  });
});

All 21 comments

This is because always before call a cloud function you must log in first, then user or session token can be used in your cloud function

Did you set the header correct ?

You should have a header set :

X-Parse-Session-Token : <SESSION_TOKEN>

Once you set this header you will have access to req.user in your cloud code .

How do you set the header with Swift?
On Fri, Jun 24, 2016 at 8:30 AM, zeustl [email protected] wrote:
Did you set the header correct ?

You should have a header set :

X-Parse-Session-Token :

Once you set this header you will have access to req.user in your cloud code .

—
You are receiving this because you authored the thread.
Reply to this email directly, view it on GitHub [https://github.com/ParsePlatform/parse-server/issues/2104#issuecomment-228333713] , or mute the thread [https://github.com/notifications/unsubscribe/AFqRM8BLz8LhfF34t1M-g5ILc6tqUas2ks5qO839gaJpZM4I5Okn] .

Make sure you have logged in your user before you make any cloud calls.

Parse SDK add your header by default once it has a user logged in .

I believe this is related to an intermittent issue I am having where I start to get access denied type of errors for any queries to private objects, that is, objects that have a certain ACL such as the user settings which only the current user should be able to access. The session becomes invalid or something.

I got same problem accessing request.user in Cloud Code. I've tried to logout/login several times but request.user is still undefined. When I console.log request I got this:

request =  { params: { paramName: 'objectId...' },
  master: false,
  user: undefined,
  installationId: 'uuid...',
  log: FileLoggerAdapter {} }

It seems that if I use request in Cloud function there's no user (undefined) but if I call request.user in Parse.Cloud.afterSave then user is set.
According to This compatibility document request.user should be available in Cloud function. Below is my sample cloud code.

Parse.Cloud.define("fixTodoItem", function (request, response) {
  console.log('*** Cloud function\'s request = ', request);
});

Parse.Cloud.afterSave("TodoItem", function(request) {
  console.log('*** Cloud aftersave\'s request = ', request);
  Parse.Cloud.run("fixTodoItem", {todoId: request.object.id}, {
    success: function (result) {
      console.log('Success: ', result);
    },
    error: function(error) {
      console.log('Error: ', error);
    }
  });
});

Output:

*** Cloud aftersave's request =  { triggerName: 'afterSave',
  object: ParseObject { _objCount: 1, className: 'TodoItem', id: 'objectId' },
  master: false,
  log: FileLoggerAdapter {},
  user: ParseUser { _objCount: 0, className: '_User', id: 'userId' },
  installationId: 'installationId' }
afterSave: request.user = ParseUser { _objCount: 0, className: '_User', id: 'userId' }
verbose: RESPONSE from [POST] /1/classes/TodoItem: {
  "status": 201,
  "response": {
    "objectId": "objectId",
    "createdAt": "2016-07-24T03:51:00.216Z"
  },
  "location": "http://localhost:1337/1/classes/TodoItem/objectId"
} status=201, objectId=objectId, createdAt=2016-07-24T03:51:00.216Z, location=http://localhost:1337/1/classes/TodoItem/objectId
verbose: REQUEST for [POST] /1/functions/fixTodoItem: {
  "todoId": "objectId"
} method=POST, url=/1/functions/fixTodoItem, user-agent=node-XMLHttpRequest, Parse/js1.9.0 (NodeJS 6.2.1), accept=*/*, content-type=text/plain, host=localhost:1337, content-length=193, connection=close, todoId=objectId
*** Cloud function's request =  { params: { todoId: 'objectId' },
  master: false,
  user: undefined,
  installationId: 'installationId',
  log: FileLoggerAdapter {},
  headers:
   { 'user-agent': 'node-XMLHttpRequest, Parse/js1.9.0 (NodeJS 6.2.1)',
     accept: '*/*',
     'content-type': 'text/plain',
     host: 'localhost:1337',
     'content-length': '193',
     connection: 'close' } }

I figure it out why request.user is undefined when calling Cloud function. It's because sessionToken is not set automatically in the request when calling Parse.Cloud.run() from Cloud code (not sure the reason behind this?). To fix the problem I have to set sessionToken manually like bellow. Hope it helps someone having same problem with me.

Parse.Cloud.afterSave("TodoItem", function(request) {
  Parse.Cloud.run("fixTodoItem", {todoId: request.object.id}, {
    success: function (result) {
      console.log('Success: ', result);
    },
    error: function(error) {
      console.log('Error: ', error);
    },
    sessionToken: request.user.getSessionToken()
  });
});

I'm also seeing req.user undefined in self-hosted Parse cloud code functions. It only occurs when attempting to make a cloud code call from a current user that is restored between launches of the iOS app.

NOTE: I have not tried against Parse.com, as this is a new project without a Parse.com app.

I recreated the bug in a fresh checkout of parse-server-example running on localhost. I only added the beforeSave function for Parse.User.

Steps to reproduce:

  1. Deleting existing app from Simulator if previously installed
  2. Launch iOS app
  3. Observe PFUser.current() is null so a new user "[email protected]" is created.
    3a. On server: Observe req.user is undefined (expected since this is a new user sign up)
  4. Observe saving string to the random column of the current user SUCCEEDS. (user is valid here)
    4a. On server: Observe req.user is a valid objectId (expected since we just signed up)
  5. Relaunch the app
  6. Observe PFUser.current() returns a valid authenticated user "[email protected]"
  7. Observe saving string to the random column of the current user FAILS.
    7a. On server: Observe req.user is undefined (not expected)

Client Environment:
Xcode 8 beta 5
Swift 3.0
Parse iOS SDK 1.14.2

Server Environment: (cloned current parse-server-example and added Cloud Code function below)
parse-server 2.2.18

Here's the Cloud Code - just one function in my main.js

Parse.Cloud.beforeSave(Parse.User, function(req, res) {
  console.log("beforeSave req.user: " + req.user);
  res.success();
});

Here's the offending iOS code.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject] ? ) - > Bool {

    let configuration = ParseClientConfiguration {
        $0.applicationId = "myAppId"
        $0.server = "http://localhost:1337/parse"
    }
    Parse.initialize(with: configuration)

    if let user = PFUser.current() {

        print("Save will fail...")
        saveRandomToCurrentUser()

    } else {

        let user = PFUser()
        user.username = "[email protected]"
        user.password = "password"

        user.signUpInBackground { success, error in
            if let error = error {
                print("user sign up error: \(error)")
            } else {
                print("user sign up successful!")
                print("Save will succeed...")
                self.saveRandomToCurrentUser()
            }
        }
    }
}

func saveRandomToCurrentUser() {
    if let user = PFUser.current() {
        user["random"] = "string"
        user.saveEventually {
            (success, error) in
            if let error = error {
                print("save error: \(error)")
            } else {
                print("save successful!")
            }
        }
    }
}

I haven't determined if this is a parse-server bug or Parse iOS SDK bug.

In beforeSave(Parse.User) you should access the user with req.object

@flovilmart req.object will contain the User data that is being saved (not the problem being discussed). The problem is that the user making the request should populate req.user. In my example, req.user is valid in one case and undefined in another even though a valid user has made both requests.

I'll add some tests checking if that's reproductible all the times.

I suspect it to be an issue with the Parse iOS SDK. I haven't interrogated the headers yet (haven't had time today), but I suspect something isn't being persisted correctly for the logged-in user between launches. Resulting in parse-server not associating the request with the logged-in user.

That is also possible, we infer the user on the session header

I found a closed (yet unresolved) issue here https://github.com/ParsePlatform/Parse-SDK-iOS-OSX/issues/609 which describes the problem I'm having above. I see the error 'PFKeychainStore failed to set object for key 'currentUser', with error: -34018' which is describe here https://github.com/ParsePlatform/Parse-SDK-iOS-OSX/issues/437 as being fixed with 9.3, but I'm running iOS 10.0 and the problem persists. So I'll dive into those issues.

I can confirm that the issue is resolved by following @takomborerwa 's suggestion in https://github.com/ParsePlatform/Parse-SDK-iOS-OSX/issues/437. Turning on Keychain Sharing for an app built against iOS 10 allows Facebook to store the user's credentials properly and send the proper headers to Parse Server.

I've tried what @phuna suggested above, and it worked, but sometimes it returned undefined in the Cloud Function as well.

Worked for me when enabling Keychain Sharing, as suggested by @mooshee in @takomborerwa's suggestion.

Enabled Keychain Sharing and didn't help.

If anyone runs into this, I turned on keychain sharing and still had the issue. I had to clean, delete the app, and reinstall to get things to work properly.

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

Was this page helpful?
0 / 5 - 0 ratings