npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@arnagos/redux-saga-oauth

v2.0.18

Published

A Keycloak OAuth module for Redux Saga powered applications

Readme

redux-saga-oauth

NPM Build Status

👮 An OAuth module for Redux Saga powered applications

What does it do?

Redux Saga OAuth provides a reducer and a saga to handle authentication within any JavaScript application that uses Redux and Redux Saga.

Key features

  • Has Flow support for easier integration
  • Handles all HTTP requests with axios
  • Allows for any grant types and extra data to be passed during login
  • Automatically handles token refresh following the standard flow
  • Handles failures during the refresh flow and will retry until it succeeds
  • Allows the refresh token to be expired on the server and log users out

Getting started

Install

You can install this via yarn or npm, however, yarn is the preferred method.

yarn add @simpleweb/redux-saga-oauth
npm install --save @simpleweb/redux-saga-oauth

It also has a peer dependency of redux-saga, please make sure this is installed before hand.

Usage

Add the provided reducer to your store

Within your existing Redux store, bring in the provided reducer. It’s key (auth in the example below) can be customised to anything you like.

import { Reducer } from "@simpleweb/redux-saga-oauth";


const store = createStore(
  combineReducers({
    auth: Reducer,
  })
);

Add the provided saga to your root saga

Create the provided auth saga and add it to your root saga. These are the required options you must pass. The reducerKey should match the key from the step above.

import { createOAuthSaga } from "@simpleweb/redux-saga-oauth";

const authSaga = createOAuthSaga({
  reducerKey: "auth",
  OAUTH_URL: "http://localhost:3000/oauth/token.json",
  OAUTH_CLIENT_ID: "<CLIENT ID>",
  OAUTH_CLIENT_SECRET: "<CLIENT SECRET>",
});

const sagas = function* rootSaga() {
  yield all([
    fork(authSaga),
  ]);
}

Login and logout

To login, simply import the provided actions, pass through your API’s corresponding credentials and dispatch the action.

import { login, logout } from "@simpleweb/redux-saga-oauth";

const params = {
  username: "[email protected]",
  password: "mysecurepassword",
  grant_type: "password",
};

store.dispatch(
  login(params)
);

store.dispatch(
  logout()
);

Actions

The module does expose all it’s internal Redux actions and constants should you need them. They are exposed like so.

import { Actions } from "@simpleweb/redux-saga-oauth";

Actions.authLoginRequest()
Actions.AUTH_LOGIN_REQUEST

Authenticated requests

This will something you will want to do after having got this working, while the code is not directly provided in the module, it's worth moving this into your own codebase as some sort of helper function to make authenticated requests using the access token in the store.

Please note any import’s are missing from the code below.

App/Sagas/AuthenticatedRequest.js

// Custom error type to be thrown from this saga
// e.g. throw new AuthenticationSagaError('Some message');
function AuthenticationSagaError(message) {
  this.message = message;
  this.name = "AuthenticationSagaError";
}

// Helper function to get the authentication state from the store
// the "authentication" key will be unique to your code
const getAuthentication = state => state.auth;

// Helper function to check if the token has expired
export const tokenHasExpired = ({ expiresIn, createdAt }) => {
  const MILLISECONDS_IN_MINUTE = 1000 * 60;

  // Set refreshBuffer to 10 minutes
  // so the token is refreshed before expiry
  const refreshBuffer = MILLISECONDS_IN_MINUTE * 10;

  // Expiry time
  // multiplied by 1000 as server time are return in seconds, not milliseconds
  const expiresAt = new Date((createdAt + expiresIn) * 1000).getTime();
  // The current time
  const now = new Date().getTime();
  // When we want the token to be refreshed
  const refreshAt = expiresAt - refreshBuffer;

  return now >= refreshAt;
};

// Helper function to get the access token from the store
// if the token has expired, it will wait until the token has been refreshed
// or an authentication invalid error is thrown
function* getAccessToken() {
  const authentication = yield select(getAuthentication);

  // Expires_in, created_at

  // If the token has expired, wait for the refresh action
  if (
    tokenHasExpired({
      expiresIn: authentication.expires_in,
      createdAt: authentication.created_at,
    })
  ) {
    yield race({
      refreshError: take(AUTH_INVALID_ERROR),
      tokenRefreshed: take(AUTH_REFRESH_SUCCESS),
    });
  }

  // Return the latest access token
  const latestAuthentication = yield select(getAuthentication);
  return latestAuthentication.access_token;
}

// Finally the function you’ll use inside your sagas to make requests
export default function* AuthenticatedRequest(...args) {
  // Get the current access token, wait for it if it needs refreshing
  const accessToken = yield getAccessToken();

  if (accessToken) {
    const config = {
      headers: {
        Authorization: `Bearer ${accessToken}`,
      },
    };

    try {
      return yield call(...args, config);
    } catch (error) {
      if (error.response && error.response.status === 401) {
        yield put(authInvalidError(error.response));
        throw new AuthenticationSagaError("Unauthorized");
      } else {
        throw error;
      }
    }
  } else {
    throw new AuthenticationSagaError("No access token");
  }
}
Usage

The AuthenticatedRequest function simply wraps your normally API calls so additional headers can be passed down to add in the access token.

import axios from "axios";
import AuthenticatedRequest from "App/Sagas/AuthenticatedRequest";

function* MakeRequest() {
  try {
    const response = yield AuthenticatedRequest(axios.get, "/user");
  } catch(error) {

  }
}

Development

You can test this locally by installing it’s dependencies and linking it as a local module.

git clone [email protected]:simpleweb/redux-saga-oauth.git
cd redux-saga-oauth
yarn && yarn link

Deployment

Increment the version inside of the package.json and create a commit stating a new version has been created, e.g. "🚀 Released 1.0.0".

On Github, draft a new release , set the version and release title to "vX.X.X" (the version number that you want to release) and add a description of the new release.

Now run yarn publish --access=public to deploy the code to npm.

TL;DR