🧪 Test Token Refresh

Test to see that expired tokens are refreshed correctly in your middleware.

The refresh token is securely stored in an encrypted session cookie, so we'll test token refresh directly on the Express server rather than through the React frontend.


(Setup) Test Preparation

Similar to the testing of your auth middleware, ensure you have a test endpoint on your Express server available and a corresponding test component in your React frontend.


Implement Test Endpoint and Component

For this test, make sure you have some test API implemented in your Express server that is protected by the auth middleware. It could be a simple API that just returns a 204 response.

// app.ts
import { authMiddleware } from './middleware';

...

// Test endpoint
app.get('/test', [authMiddleware], (req, res) => {
  return res.status(204).send();
});

...

In your React frontend, add a test component that makes an API request to your test endpoint.

// test-component.tsx
import axios from 'axios';

import { isUnauthorized, redirectToLogin } from '@/utils/helpers';

export function ExampleComponent() {
  const handleApiCall = async () => {
    try {
      const response = await axios.get(`<your-express-server-domain>/test`);
      alert('Success!');
    } catch (error: unknown) {
      if (isUnauthorized(error)) {
        redirectToLogin();
      } else {
        console.error('Unexpected error:', error);
        alert('Something went wrong!'); 
      }
    }
  };

  return (
    <button onClick={handleApiCall}>
      Make API Call
    </button>
  );
}

Add Auth Middleware Log Statements

❗️

Never Log Token Data Outside of This Test Scenario

You should never log any token data in QA, staging, or Prod environments for security reasons.

This approach is only intended for local development. Even for local development, make sure to remove the log statements as soon as possible after testing is done.

import wristbandAuth from './wristband-auth';

const authMiddleware = async function (req, res, next) {
  const { accessToken, expiresAt, isAuthenticated, refreshToken } = req.session;
  if (!isAuthenticated) {
    return res.status(401).send();
  }

  try {
    const tokenData = await wristbandAuth.refreshTokenIfExpired(refreshToken, expiresAt);
    if (tokenData) {
      /* ***** BEGIN TEST LOGS ***** */

      // Access token and expireation time will always get new values
      console.log(`Old access token: [${accessToken}], new access token: [${tokenData.accessToken}]`);
      console.log(`Old expiresAt: [${expiresAt}], new expiresAt: [${Date.now() + tokenData.expiresIn * 1000}]`);
      
      // Refresh tokens by default will always be the same value for Backend Server integrations.
      console.log(`Old refresh token: [${refreshToken}], new refresh token: [${tokenData.refreshToken}]`);

      /* ***** END TEST LOGS ***** */
      
      req.session.accessToken = tokenData.accessToken;
      req.session.expiresAt = Date.now() + tokenData.expiresIn * 1000;
      req.session.refreshToken = tokenData.refreshToken;
    }

    // Save the session in order to "touch" it (even if there is no new token data).
    await req.session.save();
    return next();
  } catch (error) {
    console.error(`Failed to refresh token due to: ${error}`);
    return res.status(401).send();
  }
};

export default authMiddleware;




1. Test With Valid Access Token

First we'll make sure the happy path to your test endpoint works as expected.


Actions

  • After successfully logging into your application, click the button in your test component to trigger the API call to your test endpoint.

Verify Success

  • Verify that no errors occurred during the API call.
  • Verify that a success message is displayed in the UI.
  • Verify in the network requests in your browser that a 204 No Content HTTP response status was returned to your frontend.
  • Inspect the console logs printed by your Express server. You should not see any log statements since the access token was still valid.



2. Test With Expired Access Token

Next we'll simulate having an expired token by altering the code to pass in an arbitrarily low expiresAt value. For example:

import wristbandAuth from './wristband-auth';

const authMiddleware = async function (req, res, next) {
  ...

  try {
    // Pass an arbitrarily low expiresAt value to force a refresh to occur.
    const tokenData = await wristbandAuth.refreshTokenIfExpired(refreshToken, 123);

  ...
};

export default authMiddleware;


Actions

  • While still logged into your application, click the button in your test component to trigger the API call to your test endpoint.

Verify Success

  • Verify that no errors occurred during the API call.
  • Verify that a success message is displayed in the UI.
  • Verify in the network requests in your browser that a 204 No Content HTTP response status was returned to your frontend.
  • Inspect the console logs printed by your Express server. You should see log statements where:
    • The accessToken received from the SDK has a new value compared to the session value.
    • The derived expiresAt based on the expiresIn received from the SDK has a new value compared to the session value.
    • The refreshToken value received from the SDK has the exact same value compared to the session value.

❗️

Revert Your expiresAt Code Change

Once this test is verified, undo the code change from above so that the expiresAt value from your session is passed as an argument into the SDK instead of your arbitrary test value.




3. Test With A Revoked Refresh Token

Now ensure that if an admin were to revoke a token in the Wristband platform, then the token refresh attempt errors out.


Actions

  • Ensure your middleware code is correctly passing the expiresAt value from your session into the refreshTokenIfExpired() function after the previous test.

  • In the Wristband Dashboard, revoke the refresh token for the currently logged-in user:

    1. From the Wristband Dashboard home page, navigate into your Wristband Application.

    2. Select Users from the left navigation menu.

    3. In the Users table, click on the row of your test user.

    4. On that user's settings page, scroll down to the Refresh Token table. Here, you can see if the Wristband Auth Session was deleted from Wristband's backend (which is the source of auth sessions).

    5. Click the Trash Can icon for the refresh token you need to revoke. You can alternatively revoke all refresh tokens for this user using the button under the table.

      Active Refresh Tokens
  • While still logged into your application, click the button in your test component to trigger the API call to your test endpoint.


Verify Login Redirect

  • Verify that the network requests show a 401 Unauthorized HTTP response coming from your Express server's test endpoint.
  • Verify in the network requests that the browser redirects you to your Express server's Login endpoint.
  • Verify that you land on either the Tenant Discovery Page or the Tenant Login Page of your test tenant (depending on how you configured your domains).
  • Inspect the console logs printed by your Express server. You should not see any log statements since the access token was still valid.

❗️

Remove Your Log Statements

Just one more friendly reminder to remove log statements containing token data. 🙂


If all tests succeeded, then token refresh is working as expected. 🎉

Thumbs Up

You did it. Fresh tokens coming right up!


This is just the beginning -- there's so much more you can build with our platform! Let's explore.