Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Request.user undefined and no information in request #2104

Closed
PeterKaminski09 opened this issue Jun 19, 2016 · 21 comments
Closed

Request.user undefined and no information in request #2104

PeterKaminski09 opened this issue Jun 19, 2016 · 21 comments

Comments

@PeterKaminski09
Copy link

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

�[31merror�[39m: 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 {} }

@IntrasoftCo
Copy link

IntrasoftCo commented Jun 21, 2016

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

@zdmano
Copy link

zdmano commented Jun 24, 2016

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 .

@PeterKaminski09
Copy link
Author

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 : <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//issues/2104#issuecomment-228333713] , or mute the thread [https://github.com/notifications/unsubscribe/AFqRM8BLz8LhfF34t1M-g5ILc6tqUas2ks5qO839gaJpZM4I5Okn] .

@zdmano
Copy link

zdmano commented Jun 24, 2016

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 .

@xissburg
Copy link

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.

@phuna
Copy link

phuna commented Jul 23, 2016

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 {} }

@phuna
Copy link

phuna commented Jul 24, 2016

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' } }

@phuna
Copy link

phuna commented Jul 24, 2016

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()
  });
});

@mooshee
Copy link

mooshee commented Aug 24, 2016

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.

@flovilmart
Copy link
Contributor

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

@mooshee
Copy link

mooshee commented Aug 24, 2016

@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.

@flovilmart
Copy link
Contributor

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

@mooshee
Copy link

mooshee commented Aug 24, 2016

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.

@flovilmart
Copy link
Contributor

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

@mooshee
Copy link

mooshee commented Aug 25, 2016

I found a closed (yet unresolved) issue here parse-community/Parse-SDK-iOS-OSX#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 parse-community/Parse-SDK-iOS-OSX#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.

@mooshee
Copy link

mooshee commented Sep 8, 2016

I can confirm that the issue is resolved by following @takomborerwa 's suggestion in parse-community/Parse-SDK-iOS-OSX#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.

@ralphilius
Copy link

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

@mtrezza
Copy link
Member

mtrezza commented Sep 17, 2016

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

@talkaboutdesign
Copy link

Enabled Keychain Sharing and didn't help.

@ryanwaggoner
Copy link

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.

@stale
Copy link

stale bot commented Sep 18, 2018

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests