pusher / push-notifications-web

Beams Browser notifications
MIT License
39 stars 19 forks source link

Invalid JWT claims: Token used before issued when setUserId #93

Closed madaher-dev closed 3 years ago

madaher-dev commented 3 years ago

i am trying to publish to a specific user. I am using React for frontend and NodeJs for backend

I prepared the backend route and in the frontend i am doing the following:

const beamsClient = new PusherPushNotifications.Client({ instanceId: 'MYINSTANCE' }); const beamsTokenProvider = new PusherPushNotifications.TokenProvider({ url: '/api/v1/users/beams/token' }); useEffect(() => { beamsClient .start() .then(() => beamsClient.setUserId(user._id.toString(), beamsTokenProvider) ) .catch(console.error); }, []);

When the page mounts i am seeing the backend route is being reached and is returning a token. But i am getting a frontend error in the console Unexpected status code 401: Unauthorized, Invalid JWT claims: Token used before issued

benw-pusher commented 3 years ago

You should check the time and date (including the timezone) settings on your issuing server - the error indicates the timestamp of the token is somehow in the future.

abhagsain commented 3 years ago

@ben-pusher Hi, ben. I'm getting this error in the local environment as well 😶 Both client and server are on the same machine. Also in the dashboard, It's showing 19 connected devices even though I'm the only one testing in one browser.

So my question is Do I need to call beamClient.stop before calling it again on component mount or call .start() only if notification isn't enabled? Is there a way to check if the user has already enabled notification?

Thank you :)

Here's the code snippet.

let beamsClient: PusherPushNotifications.Client | null = null;
let beamsTokenProvider: PusherPushNotifications.TokenProvider | null = null;

if (typeof window !== "undefined" && process.env.NEXT_PUBLIC_PUSHER_ID) {
  beamsClient = new PusherPushNotifications.Client({
    instanceId: process.env.NEXT_PUBLIC_PUSHER_ID,
  });
  beamsTokenProvider = new PusherPushNotifications.TokenProvider({
    url: "http://localhost:3001/pusher/beams-auth",
    credentials: "include",
    headers: {
      "x-xsrf-token": getTokenCookie()!,
    },
  });
}

beamsClient
        .start()
        .then(() => {
          beamsClient
            ?.setUserId(user.uid!, beamsTokenProvider!)
            .then((res) => console.log("token", res))
            .catch((err) => console.log("token provider", err));
        })
        .catch(() => {
          toast.error(
            "Couldn't enable notifications. Please check your browser settings."
          );
        });
madaher-dev commented 3 years ago

Anyway i don't understand how the server timezone could be an issue. The token timestamp is in unix time so it should be timezone independent.

abhagsain commented 3 years ago

Anyway i don't understand how the server timezone could be an issue. The token timestamp is in unix time so it should be timezone independent.

Did you manage to solve this? @madaher-dev

madaher-dev commented 3 years ago

Unfortunately no. I ended up using secure channels rather than beams. Also i saw you are getting multiple connections issue. If you are using React make sure not to create a new connection every time the component mounts. Save your Pusher to a state and initiate a connection only if there is no connection already established.

benw-pusher commented 3 years ago

The token timestamp is in unix format, however the service setting the timestamp appears to have an incorrect time - this is why the error message Token used before issued is returned. You don't need to call .stop - doing so will cause the device to no longer receive notifications. You don't need to check whether the device is registered prior to calling start: when the device attempts to register the Beams service will identify it is already registered and handle accordingly.

As @madaher-dev has mentioned - for Channels you only need to create a single connection and you should reuse this connection throughout the app.