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

NotAuthenticated: jwt expired #633

Closed
sarkistlt opened this Issue Feb 1, 2018 · 7 comments

Comments

Projects
None yet
2 participants
@sarkistlt
Copy link

sarkistlt commented Feb 1, 2018

some weird thing is going on, when using in app routing everything works fine, on first page load I'm checking if customer is logged in:

client.authenticate()
    .then(res => dispatch({ type: 'FULFILLED_USER', payload: res.user }));

then during navigating between pages if I will trigger any service client.service('some service').find(), I will get error in API console that I'm not authenticated and my hook prevents from executing that method. and If I will refresh page one time it will redirect me back to login because it doesn't pass authentication, error in API console is NotAuthenticated: jwt expired, then If I will refresh second time from login page it will pass authentication and will redirect me pack to home page.

Why is it happening? I'm storing JWT in the cookie, and I'm checking that it always persist there.
I use Next.js and SSR, but all calls to API server and authentication executed on client side.
I even tried manually pass JWT:

  const accessToken = client.storage.getItem('feathers-jwt'); // which is cookie in my case
  console.log(accessToken); // token exist, and it's exactly the same as it was on prev. call
  return client.authenticate({ accessToken, strategy: 'jwt' })
    .then(res => dispatch({ type: 'FULFILLED_USER', payload: res.user }));

it doesn't help, tried, different storages, nothing help, have no idea what it could be

Module versions
"@feathers-plus/cache": "^1.4.0",
"@feathersjs/authentication": "^2.1.0",
"@feathersjs/authentication-jwt": "^1.0.1",
"@feathersjs/authentication-local": "^1.0.2",
"@feathersjs/configuration": "^1.0.1",
"@feathersjs/errors": "^3.2.0",
"@feathersjs/express": "^1.1.2",
"@feathersjs/feathers": "^3.0.2",
"@feathersjs/socketio": "^3.0.1",
"@sendgrid/mail": "^6.1.4",

NodeJS version:
8.9.1

@sarkistlt

This comment has been minimized.

Copy link
Author

sarkistlt commented Feb 1, 2018

on client side added those options:

cookie: 'some-custome-name-jwt',
storageKey: 'some-custome-name-jwt',

and seams to work, for some reason in the cooke I have to jwt with the same key feathers-jwt.

@sarkistlt sarkistlt closed this Feb 1, 2018

@sarkistlt

This comment has been minimized.

Copy link
Author

sarkistlt commented Feb 3, 2018

reopening because for some reason this issue came back... and now I don't have duplicated jwt in the cookie

@sarkistlt sarkistlt reopened this Feb 3, 2018

@daffl

This comment has been minimized.

Copy link
Member

daffl commented Feb 5, 2018

We will need a minimal reproducible example to be able to look into what is happening.

@sarkistlt

This comment has been minimized.

Copy link
Author

sarkistlt commented Feb 6, 2018

sure. API server and client running on separate ports

client:

import feathers from '@feathersjs/feathers';
import auth from '@feathersjs/authentication-client';
import Cookies from 'universal-cookie';
import io from 'socket.io-client';
import socketio from '@feathersjs/socketio-client';
import logger from './logger';

const expires = new Date();
expires.setMonth(expires.getMonth() + 12);
const client = feathers();
const storage = new Cookies({
  expires,
  domain: 'mydomain.com',
  secure: true,
});

storage.getItem = storage.get;
storage.setItem = storage.set;
storage.removeItem = storage.remove;

const config = {
  storage,
  cookie: 'mydomain-jwt',
  storageKey: 'mydomain-jwt',
};

const socket = io(API);

client
  .configure(socketio(socket))
  .configure(auth(config));

socket.on('connect', () => {
  return client.authenticate()
    .catch(() => { /* ignore if not auth. */ });
});

client.logger = logger;
client.storage = storage;

export default client;

API server:

...
  .configure(auth(app.get('auth')))
  .configure(jwt({ Verifier: VerifierJWT }))
  .configure(local())
...

app.get('auth'):

  "auth": {
    "service": "crud/users",
    "secret": "secret",
    "strategies": ["jwt"],
    "jwt": {
      "header": {
        "type": "access"
      },
      "audience": "https://www.mydomain.com",
      "subject": "anonymous",
      "issuer": "feathers",
      "algorithm": "HS256",
      "expiresIn": "1y"
    }
  }

even without setting on client side:

  cookie: 'mydomain-jwt',
  storageKey: 'mydomain-jwt',

it works perfectly fine on first start, then we can stop/restart client or server, everything works as expected, but after restarting my computer or next day, if I will try to use app it will trigger behavior that I mentioned on the first post, we can fix it by setting every-time when this issue appears, different client token configs, like:

  cookie: 'mydomain1-jwt',
  storageKey: 'mydomain1-jwt',

probably we won't have this issue on production but anyway it doesn't seam as correct behavior.

Thanks!

@daffl

This comment has been minimized.

Copy link
Member

daffl commented Feb 7, 2018

Sorry, I meant a complete GitHub repository that can be cloned down with the steps to reproduce the issue. The code snippets still don't have enough information (e.g. what's VerifierJWT? Does it work with localStorage instead of Cookie?). What is the decoded JWTs expiry date?

@sarkistlt

This comment has been minimized.

Copy link
Author

sarkistlt commented Feb 7, 2018

I see, sure, here is example.
on production API and store-front is separate projects.
so first you need to run API npm run start:api then store front start:front.
after first run it will work fine, you can loggin, logout, when you refresh on home page it will stay there, but then for unknown reason in a day or so, if we ware logged in, (jwt in a cookie) it will redirect you to home page, then when you refresh page it will redirect you back to login (error: jwt is expired), after that if you will refresh on login page it will generate new jwt and redirect back to home page.

in the prevues example VerifierJWT is just to extend payload with external id.
it works with Cookie.

@sarkistlt

This comment has been minimized.

Copy link
Author

sarkistlt commented May 11, 2018

I'm gonna close this ticket because I found a solution and the cause of this issue.
Basically to many different projects where I'm using feathersjs hah, so lets say if you have more then one project that could run on the same local port, and (in my case because of storage is the cookie), for some reason it was creating duplicated keys with different values to store JWT, so it was possible to end up with having in the cookie 2 keys feathers-jwt with different values from 2 different project, and that's where this glitch was coming from.

Solution is to use custom name for each project, like so:

const authConfig = {
  storage,
  cookie: `${projectName}-jwt_${NODE_ENV}`,
  storageKey: `${projectName}-jwt_${NODE_ENV}`,
};

@sarkistlt sarkistlt closed this May 11, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.
You signed in with another tab or window. Reload to refresh your session. You signed out in another tab or window. Reload to refresh your session.