
Security News
AGENTS.md Gains Traction as an Open Format for AI Coding Agents
AGENTS.md is a fast-growing open format giving AI coding agents a shared, predictable way to understand project setup, style, and workflows.
@arnagos/redux-saga-oauth
Advanced tools
A Keycloak OAuth module for Redux Saga powered applications
👮 An OAuth module for Redux Saga powered applications
Redux Saga OAuth provides a reducer and a saga to handle authentication within any JavaScript application that uses Redux and Redux Saga.
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.
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,
})
);
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),
]);
}
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: "ben@simpleweb.co.uk",
password: "mysecurepassword",
grant_type: "password",
};
store.dispatch(
login(params)
);
store.dispatch(
logout()
);
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
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");
}
}
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) {
}
}
You can test this locally by installing it’s dependencies and linking it as a local module.
git clone git@github.com:simpleweb/redux-saga-oauth.git
cd redux-saga-oauth
yarn && yarn link
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.
FAQs
A Keycloak OAuth module for Redux Saga powered applications
The npm package @arnagos/redux-saga-oauth receives a total of 22 weekly downloads. As such, @arnagos/redux-saga-oauth popularity was classified as not popular.
We found that @arnagos/redux-saga-oauth demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Security News
AGENTS.md is a fast-growing open format giving AI coding agents a shared, predictable way to understand project setup, style, and workflows.
Security News
/Research
Malicious npm package impersonates Nodemailer and drains wallets by hijacking crypto transactions across multiple blockchains.
Security News
This episode explores the hard problem of reachability analysis, from static analysis limits to handling dynamic languages and massive dependency trees.