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

throw Parse.Error in Custom Authentication Module doesn't get treated as Parse.Error #6467

Closed
appxplore-tech opened this issue Mar 5, 2020 · 15 comments
Labels
type:bug Impaired feature or lacking behavior that is likely assumed

Comments

@appxplore-tech
Copy link

Issue Description

I write my own custom Authentication Module due to some features that are not available here and I did throw some Parse.Error in the custom Authentication Module and I expect that I did receive the ParseError in my client instead of Internal server error code.

Steps to reproduce

  1. Create a Latest Parse-Server using Parse-Express-Example(I tried those version before: 4.1.0, 3.10.0, 3.8.0, 3.6.0)
  2. import my npm package with command : npm install parse-server-auth-google
  3. in the index.js, replace the default google auth module with my auth module:
    "google":{module:"parse-server-auth-google"}
  4. start the parse-server
  5. call the post request as below to trigger the function:
    url: https://<>/parse/users
    method: POST
    Body: {"authData":{"google":{"id":"111"}}}
    Headers: (Normal Headers as usual to call parse-server, for eg. X-Parse-Application-Id, Content-Type)

Expected Results

Receive a response with HTTP-Status: 404 with Body as below:

{
    "code": 101,
    "error": "Facebook auth is invalid for this user."
}

Actual Outcome

Receive a response with HTTP-Status: 500 with Body as below:

{
    "code": 1,
    "message": "Internal server error."
}

Environment Setup

  • Server

    • parse-server version (Be specific! Don't say 'latest'.) : [3.6.0,3.8.0,3.10.0,4.1.0]
    • Operating System: [Ubuntu Server 16.04.6]
    • Hardware: [AWS r4.large]
    • Localhost or remote server? (AWS, Heroku, Azure, Digital Ocean, etc): [AWS]
  • Database

    • MongoDB version: [4.0.13]
    • Storage engine: [WiredTiger]
    • Hardware: [2 Replica Set]
    • Localhost or remote server? (AWS, mLab, ObjectRocket, Digital Ocean, etc): [AWS EC2]

Logs/Trace

Below are the logs that shown in my pm2. I found that during my own module file, the error i throw is still a Parse.Error type, but when it comes to middlewares.js, the function handleParseErrors will not treated it as a Parse.Error type.

48|appxplo | {"method":"POST","url":"/parse/users","headers":{"x-parse-application-id":"SICXfgOJNhYtBZUiM6Ua5IP1Pxwo4qJfgn8rJ7yS","x-parse-rest-api-key":"57y6F7BZwyaqn9YWYdKJgLeGTItAKukIrpOYYipL","content-type":"application/json","x-parse-installation-id":"c8cf2c87-3341-41c1-b386-25ab1b11839f","user-agent":"PostmanRuntime/7.22.0","accept":"*/*","cache-control":"no-cache","postman-token":"84f5dc58-bed3-4e94-99a8-89facb2e83d2","host":"xxxx.xxxx.xxxx.xxxx:xxxx","accept-encoding":"gzip, deflate, br","content-length":"36","connection":"keep-alive"},"body":{"authData":{"google":{"id":"111"}}},"level":"verbose","message":"REQUEST for [POST] /parse/users: {\n  \"authData\": {\n    \"google\": {\n      \"id\": \"111\"\n    }\n  }\n}"}
48|appxplo | google error:  { ParseError: 101 Google auth is invalid for this user.
48|appxplo |     at Object.validateAuthData (/mnt/data/parse/appxplore-testapp/node_modules/parse-server-auth-google/index.js:45:17)
48|appxplo |     at /mnt/data/parse/appxplore-testapp/node_modules/parse-server/lib/Adapters/Auth/index.js:93:20
48|appxplo |     at Object.keys.map.provider (/mnt/data/parse/appxplore-testapp/node_modules/parse-server/lib/RestWrite.js:361:12)
48|appxplo |     at Array.map (<anonymous>)
48|appxplo |     at RestWrite.handleAuthDataValidation (/mnt/data/parse/appxplore-testapp/node_modules/parse-server/lib/RestWrite.js:350:45)
48|appxplo |     at findUsersWithAuthData.then (/mnt/data/parse/appxplore-testapp/node_modules/parse-server/lib/RestWrite.js:496:17)
48|appxplo |     at <anonymous>
48|appxplo |     at process._tickDomainCallback (internal/process/next_tick.js:228:7) message: 'Google auth is invalid for this user.', code: 101 }
48|appxplo | is error instanceof Parse.Error:  true
48|appxplo | [handleParseErrors], error:  { ParseError: 101 Google auth is invalid for this user.
48|appxplo |     at Object.validateAuthData (/mnt/data/parse/appxplore-testapp/node_modules/parse-server-auth-google/index.js:45:17)
48|appxplo |     at /mnt/data/parse/appxplore-testapp/node_modules/parse-server/lib/Adapters/Auth/index.js:93:20
48|appxplo |     at Object.keys.map.provider (/mnt/data/parse/appxplore-testapp/node_modules/parse-server/lib/RestWrite.js:361:12)
48|appxplo |     at Array.map (<anonymous>)
48|appxplo |     at RestWrite.handleAuthDataValidation (/mnt/data/parse/appxplore-testapp/node_modules/parse-server/lib/RestWrite.js:350:45)
48|appxplo |     at findUsersWithAuthData.then (/mnt/data/parse/appxplore-testapp/node_modules/parse-server/lib/RestWrite.js:496:17)
48|appxplo |     at <anonymous>
48|appxplo |     at process._tickDomainCallback (internal/process/next_tick.js:228:7) message: 'Google auth is invalid for this user.', code: 101 }
48|appxplo | [handleParseErrors], err instanceof _node.default.Error:  false
48|appxplo | {"message":"Uncaught internal server error.Google auth is invalid for this user.","code":101,"level":"error","stack":"ParseError: 101 Google auth is invalid for this user.\n    at Object.validateAuthData (/mnt/data/parse/appxplore-testapp/node_modules/parse-server-auth-google/index.js:45:17)\n    at /mnt/data/parse/appxplore-testapp/node_modules/parse-server/lib/Adapters/Auth/index.js:93:20\n    at Object.keys.map.provider (/mnt/data/parse/appxplore-testapp/node_modules/parse-server/lib/RestWrite.js:361:12)\n    at Array.map (<anonymous>)\n    at RestWrite.handleAuthDataValidation (/mnt/data/parse/appxplore-testapp/node_modules/parse-server/lib/RestWrite.js:350:45)\n    at findUsersWithAuthData.then (/mnt/data/parse/appxplore-testapp/node_modules/parse-server/lib/RestWrite.js:496:17)\n    at <anonymous>\n    at process._tickDomainCallback (internal/process/next_tick.js:228:7)"}

Please let me know if I'm doing it wrong. thank you.

@davimacedo
Copy link
Member

Can you share the code (or at least a piece) of your custom adapter throwing the error?

@appxplore-tech
Copy link
Author

appxplore-tech commented Mar 6, 2020

actually the code are already in the npm package. but if you need let me share you here the simplified version:


'use strict';

// Helper functions for accessing the google API.
var https = require('https');
var Parse = require('parse/node').Parse;

// Returns a promise that fulfills if this app id is valid.
function validateAppId() {
  return Promise.resolve();
}

function validateAuthData(authData, authOptions) {
    let error = new Parse.Error(
        Parse.Error.OBJECT_NOT_FOUND,
        'Google auth is invalid for this user.'
    );
    console.log("google error: ", error)
    console.log("is error instanceof Parse.Error: ", error instanceof Parse.Error)
    throw error
}

module.exports = {
  validateAppId: validateAppId,
  validateAuthData: validateAuthData
};

The error occurs only when i make my module as an npm package. if you straight away put it inside the Parse-Server/src/Adapters/Auth/, it will work as expected. But since Custom Authentication is allowed here I think there should be some problem here that doesn't accept the Parse.Error i throw as an Error object.

Extra Explanation: When i try to throw the ParseError in the script here, it still shows that it is an instance of Parse.Error. But once it went to middlewares.js handleParseErrors function, it treat it as undefined situation and become uncaught server error.

@appxplore-tech
Copy link
Author

Here i also attach a trace indicates the path from where until the middlewares.js handleParseErrors function, hope it helps:

[object Object]
48|appxplo |     at handleParseErrors (/mnt/data/parse/appxplore-testapp/node_modules/appxplore-parse-server/lib/middlewares.js:324:11)
48|appxplo |     at Layer.handle_error (/mnt/data/parse/appxplore-testapp/node_modules/appxplore-parse-server/node_modules/express/lib/router/layer.js:71:5)
48|appxplo |     at trim_prefix (/mnt/data/parse/appxplore-testapp/node_modules/appxplore-parse-server/node_modules/express/lib/router/index.js:315:13)
48|appxplo |     at /mnt/data/parse/appxplore-testapp/node_modules/appxplore-parse-server/node_modules/express/lib/router/index.js:284:7
48|appxplo |     at Function.process_params (/mnt/data/parse/appxplore-testapp/node_modules/appxplore-parse-server/node_modules/express/lib/router/index.js:335:12)
48|appxplo |     at next (/mnt/data/parse/appxplore-testapp/node_modules/appxplore-parse-server/node_modules/express/lib/router/index.js:275:10)
48|appxplo |     at /mnt/data/parse/appxplore-testapp/node_modules/appxplore-parse-server/node_modules/express/lib/router/index.js:635:15
48|appxplo |     at next (/mnt/data/parse/appxplore-testapp/node_modules/appxplore-parse-server/node_modules/express/lib/router/index.js:260:14)
48|appxplo |     at next (/mnt/data/parse/appxplore-testapp/node_modules/appxplore-parse-server/node_modules/express/lib/router/route.js:127:14)
48|appxplo |     at promiseHandler.then.error (/mnt/data/parse/appxplore-testapp/node_modules/appxplore-parse-server/lib/PromiseRouter.js:217:9)

@davimacedo
Copy link
Member

try with the following and let me know:

    let error = {
        code: Parse.Error.OBJECT_NOT_FOUND,
        message: 'Google auth is invalid for this user.'
    };

@appxplore-tech
Copy link
Author

Hi @davimacedo

The code doesn't work for me.

Currently what i temporary do is to modify the function handleParseErrors in middlewares.js to check not only ParseError but also if the err thrown has the structure of code & message.

I'm not sure if this is proper or not. But the weird thing is some parts in the parse-server change the error i throw from ParseError to unknown object type with the structure totally same as ParseError. This is something that I feel like might need investigation?

@dplewis
Copy link
Member

dplewis commented Mar 9, 2020

Error handling is weird. There is a PR open for this issue. I think it would fix it. If not can you open a PR?

@davimacedo
Copy link
Member

I thunk it happens probably because your adapter is using parse-server in its dependencies but with a version different from the one you are using in your main project, causing npm to duplicate parse-server so your have two versions of Parse.Error. In your adapter project's package.json, try to move parse-server from dependencies to peerDependencies. You can learn more about this problem here: https://lexi-lambda.github.io/blog/2016/08/24/understanding-the-npm-dependency-model/

@appxplore-tech
Copy link
Author

Hi @davimacedo ,

Hereby i attached my package.json. I did try to use the peerDependencies but it doesn't seems help.

{
  "name": "parse-server-auth-google",
  "version": "1.0.9",
  "description": "Parse Server Authentication Addition for Google Login using refresh_token",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [
    "parse",
    "parse-server",
    "auth",
    "google",
    "refresh_token"
  ],
  "author": "Appxplore",
  "license": "MIT",
  "peerDependencies": {
    "parse-server": "^3.6.0"
  }
}

@davimacedo
Copy link
Member

Can you also share the package.json of your main project?

@appxplore-tech
Copy link
Author

appxplore-tech commented Mar 10, 2020

@davimacedo , sure. Here is my main project package.json

{
  "name": "parse-server-example",
  "version": "1.4.0",
  "description": "An example Parse API server using the parse-server module",
  "main": "index.js",
  "repository": {
    "type": "git",
    "url": "https://github.com/ParsePlatform/parse-server-example"
  },
  "license": "MIT",
  "dependencies": {
    "express": "~4.11.x",
    "kerberos": "0.0.24",
    "parse": "2.1.0",
    "parse-server": "^3.6.0",
    "parse-server-auth-gcenter": "^1.0.0",
    "parse-server-auth-google": "^1.0.9",
    "parse-server-auth-gpgames": "^2.0.0",
    "parse-server-auth-signinwithapple": "^1.0.1",
    "parse-server-auth-xiaomi": "1.0.0",
    "parse-server-push-adapter": "^2.0.2",
    "request-promise-native": "1.0.7"
  },
  "scripts": {
    "start": "node index.js"
  },
  "engines": {
    "node": ">=4.3"
  }
}

@dplewis dplewis added the type:bug Impaired feature or lacking behavior that is likely assumed label Mar 29, 2020
@gunhaxxor
Copy link
Contributor

I have the exact same issue. Trying to create a custom auth module. Can't respond properly to invalid authentication attempts.

@gunhaxxor
Copy link
Contributor

@appxplore-tech Did you find a way to resolve this?

@davimacedo
Copy link
Member

@Dealerpriest could you share your adapter code and the error that you have?

@gunhaxxor
Copy link
Contributor

gunhaxxor commented Nov 6, 2020

I eventually got it to work now. My solution was to not add any dependency from parse in my custom auth adapters package.json. Instead rely on parse being available for it when injected into the parse config.

So the top of my custom auth code currently looks like this:

// DON'T ADD THIS DEPENDENCY TO PACKAGE.JSON. IT WILL BE AVAILABLE WHEN THIS FILE IS INJECTED IN THE PARSE CONFIG
const Parse = require('parse/node').Parse;

const {verify, decode} = require('jsonwebtoken');
const getPem =  require('rsa-pem-from-mod-exp');
const axios = require('axios').default;

and my package.json looks like this:

{
  "name": "custom-auth",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "gunnar oledal",
  "license": "ISC",
  "dependencies": {
    "axios": "^0.21.0",
    "jsonwebtoken": "^8.5.1",
    "rsa-pem-from-mod-exp": "^0.8.4"
  }
}

Note that there is no dependency of parse or parse-server in the package.json

@davimacedo
Copy link
Member

Yes. I think that's the right way to do. Add parse only as a peerDependency but not as a dependency nor a devDependency. I'm closing this issue.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type:bug Impaired feature or lacking behavior that is likely assumed
Projects
None yet
Development

No branches or pull requests

4 participants