@videsk/front-auth-handler

3.2.2 • Public • Published

Front Authorization Handler

A Javascript frontend authorization tokens handler that works with JWT to check expiration and token transactions with the server.

Handle authorization tokens as sessions, based on accessToken and refreshToken, that will save it in local or session storage, and create an automatic renew when tokens expire and can integrate with request interceptors.

license size sizesrc issues rank version downloads DeepScan grade

Use the latest version! Previous version < 3.0.0 are insecure
and has not been tested.

Features

  • Automatic save tokens in session or local storage
  • Automatic storage for remember a session or not
  • Expiration observer
  • Server side validation
  • Automatically and manually renew the access token with the refresh token
  • Events for expiration, renewed, empty and errors

Installation

From NPM

npm i @videsk/front-auth-handler

Self hosted

<script src="/dist/web-auth.min.js"></script>

How to use

For start you need instance WebAuth.

const auth = new WebAuth(options);

Options

The class receive one argument as object. That object contains the following keys:

const options = { keys, config };

keys

This key, have the "key name" that will store in local or session storage. By default, are auth-key and auth-key-refresh, for access and refresh token respectively.

const keys = {
    accessToken: 'auth-key',
    refreshToken: 'auth-key-refresh'
};

config

In case of config, this key has the major of configuration of WebAuth, so we recommend go to index.js file and copy the default object.

In previous versions, use server side validation was optional, now from version 3.0.0 is mandatory, so this decision was took by security concerns. Please not send PR or issue requesting that.

Start to handle

After you pass the options that is optional (but you will work in http://localhost:3000, by default) can start to handle with the following code:

// Set empty, auto handle existing saved tokens
auth.set();
// Set with accessToken only
auth.set(accessToken);
// Set with accessToken and refreshToken
auth.set(accessToken, refreshToken);
// Also can set if you want "remember session"
auth.set(accessToken, refreshToken, true);

This automatically start to observe the expiration of access and/or refresh token. Also check validity of access token by the server and when expire automatically will try to get a new one, only if you set a refresh token.

Force renew

This property allows you to force renew the access token with the refresh token, so this is relevant when you integrate with interceptors. In case a request returns 401 Unauthorized (typically token expire or blacklisted) you can force renew.

auth.renew();

This is very useful not only when user do a request, seconds before the observer can check that access token was expired, also when access and/or refresh token was invalidated by the server in a blacklist by security reasons (ex. password reset).

So, is important use it directly in your interceptors when you know that access token was expired, blacklisted or invalidated by the server.

Events

WebAuth from version 3.0.0 was added events, can help to know when access and refresh token was expired, renewed or something not works.

The available events are:

const events = {
    expired: () => {}, 
    error: () => {}, 
    renewed: () => {}, 
    empty: () => {},
    load: () => {},
};

To set them, you can do it with this elegant way:

auth.on('name-event', callback);

// Example
auth.on('expired', function () {
    // Do something
});

// Or less elegant
auth.events.expired = () => {
    // Do something
};

Remember that both method will override the default empty function. So, define a callback per event only one time on your code.

In case of expired event, returns the name of token was expired that will be accessToken or refreshToken. So, you can difference like this:

auth.on('expired', function (tokenName) {
    if (tokenName === 'accessToken') return; // Set function when not use refreshToken
    // Is refreshToken
    logoutUser();
});

The load events is useful to set in the base of HTML or template app to know when the accessToken is valid or was renewed. Example:

auth.on('load', function() {
    // The accessToken and/or refreshToken are valid
    // Or accessToken is expired, WebAuth will try to renew, then if the renovation is successful the event will be triggered
});

So, is recommended to add the load event to the base of the app. With that, you can ensure that load event will be triggered only if accessToken and/or refreshToken are been valid. Inclusive if was valid from the first time the app was loaded or need to be renewed. Both cases ensure that the app can load with valid accessToken.

Stop and clean

This two properties allows you to clean tokens from storage and stop the observer. The stop also clean the tokens, so use stop when you want to reactivate observer manually with .set().

// Only clean tokens
auth.clean();
// Stop all and clean tokens
auth.stop();

We recommend to use .stop() when the user logout from the web app.

Server side validation

When you start WebAuth, try to check validity to the endpoint, in case the server returns an expired response, WebAuth will try to get a new one with the refreshToken.

In the config key, you will see that the two endpoints have status and attempts. These keys help to handle the response of the server, so in case of status = { ok: 200, expired: 401 } tells to WebAuth when the server returns a new one or validate correctly the accessToken. And in case of attempts in when the server returns other code that is not specified on the status and give the possibility to try again, also when the user does not have Internet connection.

When WebAuth detects issues trying to get a response of the server, automatically start to try N times you set on attempts, as a number of intervals and factor. That means:

setTimeout(() => recursive(attempts + 1), 1000 * attempts + 1);

// Example with the 3 attempts by default

// First attempt
setTimeout(() => recursive(1), 1000);
// Second attempt
setTimeout(() => recursive(2), 2000);
// Third attempt
setTimeout(() => recursive(3), 3000);
// ...

// So in a period of 6 seconds WebAuth will try to get a ok or expired response from server with 3 attempts

In case exceed the attempts the event error will throw, and the tokens will remove from the session or local storage. That behavior is by security reasons, to avoid store tokens without server validation, so you can override calling to method stop().

This is really helpful when user lose connection, also in that cases you can complement with manually Internet connection check, so you can call stop() method to avoid WebAuth remove tokens.

Lifecycle

This is the lifecycle of WebAuth, when use accessToken and refreshToken.

    Instance WebAuth
            ↓
set(accessToken, refreshToken) → observer start → (if empty, no tokens) → fire empty()
            ↓
server side accessToken validate
            ↓                           
    (accessToken expire) → fire expire('accessToken')
            ↓                       
    renew automatically ⇿ (if fails) ← try renew x times → fire error(error)
            ↓
        save tokens → observer start → fire renewed()
            ↓
    refreshToken expire
            ↓
fire expired('refreshToken')
            ↓
  end (here request login)

If you don't use a refreshToken, the lifecycle will be like this:

    Instance WebAuth
            ↓
server side accessToken validate
            ↓
set(accessToken, refreshToken) → observer start → (if empty, no tokens) → fire empty()
            ↓
(accessToken expire) → fire expire('accessToken')
            ↓
           end

Debugging

We recommend to use event error to check all issues with server side validations. This library was tested so should not throw unhandled errors related to observer.

// Development environment
auth.on('error', function (error) {
    debugger;
    console.log(error);
});

// Production
auth.on('error', function (error) {
    // Here can integrate with error monitoring like Sentry
});

We strongly recommend use error event with error monitoring like Sentry, Bugsnag, LogRocket, etc. The cases when error event should be fired are a malformed JWT and server error response.

Testing

This library was tested with Mocha, chai and chai-http. Also was created a polyfill of window to test with localStorage and sessionStorage in Node, check here.

For coverage was used nyc.

Changelog

See changelog here.

License

This library was developed by Videsk with license LGPL-2.1.

Package Sidebar

Install

npm i @videsk/front-auth-handler

Weekly Downloads

0

Version

3.2.2

License

LGPL-2.1

Unpacked Size

110 kB

Total Files

22

Last publish

Collaborators

  • francor
  • noheliajoeliana
  • matiaslopezd