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

Authentication with 'local' strategy, does not authenticate username / password #1017

Closed
gauravdhiman opened this issue Sep 22, 2018 · 5 comments

Comments

@gauravdhiman
Copy link

gauravdhiman commented Sep 22, 2018

Here is the scenario:

  1. Following instruction given https://docs.feathersjs.com/api/authentication/client.html#complete-example, I logged in once with correct username / password.
  2. Step 1 created the accessToken successfully.
  3. Now if I try to login again with, but with wrong username / password (username does not even exist in DB) then also I get the authenticated user that was returned in step 1.

In step 3, I logged the context object in after hook of authentication service for create method.
From the logs, it looks like if request is coming with accessToken in Authorization header then feathersjs does not even look at context.data to re-validate the given username / password.

As per my understanding, JWT authentication should only kick in if the context.data.strategy is jwt and not local

Another issue can see here is that every time the token is getting refreshed -- look context.params.headers.Authorization and context.result.accessToken are different. I think its related to #960

Here are the logs:

// logged in after hook of authentication create method.
context.data :  {
  "email": "a",
  "password": "a",
  "strategy": "local"
}

context.params :  {
  "query": {},
  "provider": "socketio",
  "headers": {
    "Authorization": "eyJhbGciOiJIUzI1NiIsInR5cCI6ImFjY2VzcyJ9.eyJ1c2VySWQiOiI1YmE0YjViOWFhMWFjMzFjNjQzNjQzMjUiLCJpYXQiOjE1Mzc2MzE3MzUsImV4cCI6MTUzNzcxODEzNSwiYXVkIjoiaHR0cHM6Ly95b3VyZG9tYWluLmNvbSIsImlzcyI6ImZlYXRoZXJzIiwic3ViIjoiYW5vbnltb3VzIiwianRpIjoiODhhOWUyZGItMmZmZC00NmFjLTlhNWMtMzgxZjkyOTIyYjFmIn0.0EJTb0CWgyUyLq2WS0DB3sn0JJYHY2SyxaRqnoAi5ec"
  },
  "session": {},
  "cookies": {},
  "payload": {
    "userId": "5ba4b5b9aa1ac31c64364325"
  },
  "user": {
    "_id": "5ba4b5b9aa1ac31c64364325",
    "firstName": "Gaurav",
    "lastName": "Dhiman",
    "email": "gaur*******@*****.com",
    "password": "*********",
    "createdAt": "2018-09-21T09:11:21.900Z",
    "updatedAt": "2018-09-21T09:11:21.900Z",
    "__v": 0
  },
  "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6ImFjY2VzcyJ9.eyJ1c2VySWQiOiI1YmE0YjViOWFhMWFjMzFjNjQzNjQzMjUiLCJpYXQiOjE1Mzc2MzE3MzUsImV4cCI6MTUzNzcxODEzNSwiYXVkIjoiaHR0cHM6Ly95b3VyZG9tYWluLmNvbSIsImlzcyI6ImZlYXRoZXJzIiwic3ViIjoiYW5vbnltb3VzIiwianRpIjoiODhhOWUyZGItMmZmZC00NmFjLTlhNWMtMzgxZjkyOTIyYjFmIn0.0EJTb0CWgyUyLq2WS0DB3sn0JJYHY2SyxaRqnoAi5ec",
  "authenticated": true
}

context.result :  {
  "accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6ImFjY2VzcyJ9.eyJ1c2VySWQiOiI1YmE0YjViOWFhMWFjMzFjNjQzNjQzMjUiLCJpYXQiOjE1Mzc2MzE3OTQsImV4cCI6MTUzNzcxODE5NCwiYXVkIjoiaHR0cHM6Ly95b3VyZG9tYWluLmNvbSIsImlzcyI6ImZlYXRoZXJzIiwic3ViIjoiYW5vbnltb3VzIiwianRpIjoiZTI3NzRiNTAtMDVhYS00Y2JjLWI5ZmMtOTgxZjQ4NjU2MmExIn0.yQZoNOu8ggy6m90A6-iAfPpsKdlaX65D9_jr4tMyb7w"
}

context.path :  authentication

context.type :  after
@gauravdhiman
Copy link
Author

gauravdhiman commented Sep 22, 2018

For now I resolved the issue with below code - look at before create hook on authentication service, but I think this needs better solution in feathersjs authentication module.
Now my service hooks look like below to handle both issues:

  1. In case of local, dishonor JWT
  2. Do not regenerate JWT if existing JWT is still valid.
app.service('authentication').hooks({
    before: {
      create: [
        (ctx) => {
          // Workaround: For local stretegy, do not honor JWT accessToken and force re-authentication.
          if (ctx.data && ctx.data.strategy === 'local') {
            delete ctx.params.headers.Authorization;
            delete ctx.params.authenticated;
          }
        },
        authentication.hooks.authenticate(config.strategies)
      ],
      remove: [
        authentication.hooks.authenticate('jwt')
      ]
    },
    after: {
      create: [
        // Avoid regenerating accessToken if already exiting one is still valid
        (ctx) => {
          if (ctx.data && ctx.data.strategy === 'jwt' && ctx.result.accessToken !== ctx.data.accessToken) {
            ctx.result.accessToken = ctx.data.accessToken;
          }
          return ctx;
        }
      ],
      remove: []
    }
  });

@daffl
Copy link
Member

daffl commented Sep 23, 2018

This should only really happen if you are using the authentication client, called authenticate and then did not call logout before a subsequent authenticate and is something that can be handled by your frontend.

This behaviour will be fixed in the next version as well though.

@gauravdhiman
Copy link
Author

Fully agree that this should ideally be handled by frontend - if user is already logged in (valid accessToken) then front end should not show login option again until user logout. But at the same time, I also feel irrespective of frontend, server should always follow the request. If the request is to authenticate user for given credentials, then that should be done, than validating an existing valid token.

@petermikitsh
Copy link
Contributor

I would not have assumed I had to call the logout API before calling authenticate. Just my two cents. If you call the authenticate API with a local strategy and email/password, it doesn't warn you to even attempt to use the local strategy. If you already have a JWT, those parameters are ignored. Maybe a warning should be logged?

@daffl
Copy link
Member

daffl commented Jun 6, 2019

This should be handled properly now by the Feathers v4 authentication client. See the Migration guide for more information on how to upgrade.

@daffl daffl closed this as completed Jun 6, 2019
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants