kuzzleio / kuzzle-plugin-auth-passport-oauth

Authentication plugin with oauth services
Apache License 2.0
5 stars 6 forks source link

Unable to authenticate with Facebook strategy #36

Closed jgrocott closed 4 years ago

jgrocott commented 4 years ago

Expected Behavior

User should be able to successfully authenticate using the facebook strategy.

Current Behavior

Multiple error responses depending on configuration ranging from 400 to 404.

Possible Solution

Currently, based on the example configuration, request fails with a 400 BadRequestError due to the identifierAttribute being undefined in the verify method.

The documentation isn't very clear on this however the only way I can overcome this error is by adding "id" to the "persist" configuration which then means the identifierAttribute is no longer undefined in the verify method.

{
 ...
            "persist": [
                "id",
                "login",
                "avatar_url",
                "name",
                "email"
            ],
 ...
}

With this change however, it results in a 404 error when attempting to create the user here

Steps to Reproduce

  1. Configure Kuzzle for OAUTH using the kuzzle-plugin-auth-passport-oauth plugin;
{
...
  "plugins": {
   ...
    "kuzzle-plugin-auth-passport-oauth": {
      "strategies": {
        "facebook": {
            "passportStrategy": "facebook",
            "credentials": {
                "clientID": "MY_CLIENT_ID",
                "clientSecret": "MY_CLIENT_SECRET",
                "callbackURL": "http://localhost:7512/_login/facebook",
                "profileFields": ["id", "name", "picture", "email"]
            },
            "persist": [
                "login",
                "avatar_url",
                "name",
                "email"
            ],
            "scope": [
                "email",
                "public_profile"
            ],
            "kuzzleAttributesMapping": {
              "userMail": "email" // will store the attribute "email" as "userEmail" into Kuzzle
            },
            "identifierAttribute": "id"
        }
    },
    "defaultProfiles": [
        "default"
    ]
    }
  },
...
  1. Navigate to http://localhost:7512/_login/facebook and authenticate with Facebook.

Context (Environment)

At present, i cannot use Kuzzle as the local Passport strategy does not fit the requirements for any of my projects. I haven't tried other strategies just yet however I fully intend of integrating Google and potentially Twitter as well once this can be successfully setup.

Kuzzle: 2.1.4 OAuth Plugin: 5.0.1 Node: 12.16.3

jgrocott commented 4 years ago

I know very little about Kuzzle at the moment however here's some insights into what I've found while spending far too many hours debugging this issue;

It seems that for me that when "id" exists in the persist collection, the error seems to occur when attempting to create the user after a successful login.

In Kuzzle, the controller security and function createUser calls persistUser. The persistUser function seems to fail when calling the validate method for the strategy (facebook). The validate method for kuzzle-plugin-auth-passport-oauth throws an exception because it can't find the user. If i catch the exception within this function, the login attempt succeeds.

    if (!isUpdate && !credentials[this.config.strategies[provider].identifierAttribute]) {
      return Promise.reject(new this.context.errors.BadRequestError(''));
    }
    return this.getProviderRepository(provider).get(credentials[this.config.strategies[provider].identifierAttribute])
      .then(result => {
        if (result === null) {
          return Promise.resolve(true);
        }

        if (kuid !== result.kuid) {
          return Promise.reject(new this.context.errors.BadRequestError(`Id '${credentials[this.config.strategies[provider].identifierAttribute]}' is already used.`));
        }
        return Promise.resolve(true);
      }).catch(error => console.log('[Passport][OAUTH][validate] ERROR: ', error));  <--- Added Catch here
  }

Since adding this catch method, the user has been created in Kuzzle and I can see my user from the console. I can also now successfully login for this user.

Aschen commented 4 years ago

Hi @jgrocott ,

First, this configuration cannot work since you use id for the identifierAttribute but you don't persist the id in the strategy.facebook.persist array.

Then by investigating your bug, I found another issue and I fixed it here: https://github.com/kuzzleio/kuzzle-plugin-auth-passport-oauth/pull/37

jgrocott commented 4 years ago

Hi @Aschen , I can confirm that it's functioning correctly for me now if I checkout the fix branch. The only issue I can see at present is the picture.data.url does not persist. I can see the object exists within the verify parameter that is passed to the verify method. So i can confirm that a valid value exists for picture.data.url however it doesn't seem to ever get persisted.

jgrocott commented 4 years ago

I think i've fixed the issue. I'll create a PR to this branch to demonstrate the fix

Aschen commented 4 years ago

Are you sure ? Because I already used lodash for this https://github.com/kuzzleio/kuzzle-plugin-auth-passport-oauth/pull/37/files#diff-6d186b954a58d5bb740f73d84fe39073R207

I can see picture.data.url under the credentials.facebook object image

jgrocott commented 4 years ago

@Aschen confirmed this is working as expected. Thank you :)