Install & Compatibility
Where this runs
tested against v? · npm install
Install × environment matrix
Each cell = how many times install + import succeeded across repeated harness runs. Partial = flaky.
glibc = Debian/Ubuntu slim · musl = Alpine Linux
muslnode 18–226 runs
build_error
glibcnode 18–226 runs
build_error
Code
Verified usage
Verified import paths — ran on the pinned version, not inferred.
makeAuthReducer
✓ import { makeAuthReducer } from 'eazy-auth'
✗ const makeAuthReducer = require('eazy-auth').makeAuthReducer;
Used to create the authentication reducer for your Redux store.
makeAuthFlow
✓ import { makeAuthFlow } from 'eazy-auth'
✗ const { authFlow, authCall } = require('eazy-auth').makeAuthFlow;
Function to configure and retrieve `authFlow` (the main saga) and `authCall` (an authenticated saga `call` effect). Parameters (`loginCall`, `refreshTokenCall`, `meCall`) are critical for custom API integration.
login
✓ import { login } from 'eazy-auth'
✗ import login from 'eazy-auth/actions/login';
Action creator for initiating the login process with credentials.
getAuthUser
✓ import { getAuthUser } from 'eazy-auth'
✗ import { selectors } from 'eazy-auth'; selectors.getAuthUser;
Selector to retrieve the authenticated user object from the Redux state.
AuthRoute
✓ import { AuthRoute } from 'eazy-auth'
✗ import AuthRoute from 'eazy-auth/components/AuthRoute';
React Router component (for v4.x) to protect routes, redirecting unauthenticated users. Not compatible with React Router v6 directly.
This quickstart demonstrates the full integration of `eazy-auth` into a React, Redux, and Redux-Saga application. It sets up the Redux reducer and saga middleware, configures the `authFlow` with mock API calls for login, refresh, and user data, shows how to initiate a login, and protects a route using `AuthRoute` for authenticated users. The `authCall` effect is also demonstrated for making authenticated API requests within sagas.
import React from 'react';
import ReactDOM from 'react-dom';
import { createStore, combineReducers, applyMiddleware } from 'redux';
import { Provider } from 'react-redux';
import createSagaMiddleware from 'redux-saga';
import { fork, call, put } from 'redux-saga/effects';
import { BrowserRouter as Router, Switch } from 'react-router-dom';
import { makeAuthReducer, makeAuthFlow, AuthRoute, login, getAuthUser } from 'eazy-auth';
// 1. Redux Reducer Setup
const rootReducer = combineReducers({
auth: makeAuthReducer(),
// ... other reducers
});
// 2. Redux Saga Setup
const loginMockCall = async (credentials) => {
console.log('Attempting login with:', credentials);
if (credentials.username === 'test' && credentials.password === 'password') {
return { access_token: 'fake-access-token', refresh_token: 'fake-refresh-token' };
}
throw new Error('Invalid credentials');
};
const refreshTokenMockCall = async (refreshToken) => {
console.log('Attempting token refresh with:', refreshToken);
if (refreshToken === 'fake-refresh-token') {
return { access_token: 'new-fake-access-token', refresh_token: 'new-fake-refresh-token' };
}
throw new Error('Invalid refresh token');
};
const meMockCall = async (token) => {
console.log('Fetching user data with token:', token);
if (token && token.startsWith('fake-')) {
return { id: 'user-123', username: 'testuser', email: 'test@example.com' };
}
throw new Error('Unauthorized');
};
const { authFlow, authCall } = makeAuthFlow({
loginCall: loginMockCall,
refreshTokenCall: refreshTokenMockCall,
meCall: meMockCall,
});
function* mainSaga() {
yield fork(authFlow);
// Example of using authCall for an authenticated API call
try {
const userData = yield authCall(async (token) => {
console.log('Authenticated API call with token:', token);
// Simulate an API call
return new Promise(resolve => setTimeout(() => resolve({ message: `Data for ${token}` }), 100));
});
yield put({ type: 'API_CALL_SUCCESS', payload: userData });
} catch (error) {
yield put({ type: 'API_CALL_FAILURE', error: error.message });
}
}
const sagaMiddleware = createSagaMiddleware();
const store = createStore(rootReducer, applyMiddleware(sagaMiddleware));
sagaMiddleware.run(mainSaga);
// 3. React UI Setup
import { connect } from 'react-redux';
const LoginPage = ({ login, user }) => {
const handleSubmit = (e) => {
e.preventDefault();
login({ username: 'test', password: 'password' });
};
return (
<div>
<h2>Login</h2>
{user ? (
<p>Logged in as: {user.username}</p>
) : (
<form onSubmit={handleSubmit}>
<button type="submit">Log In (test/password)</button>
</form>
)}
</div>
);
};
const ConnectedLoginPage = connect(
(state) => ({ user: getAuthUser(state) }),
{ login }
)(LoginPage);
const ProfilePage = ({ user }) => (
<div>
<h2>Profile</h2>
{user ? (
<p>Welcome, {user.username}!</p>
) : (
<p>Please log in to view your profile.</p>
)}
</div>
);
const App = () => (
<Provider store={store}>
<Router>
<ConnectedLoginPage />
<Switch>
<AuthRoute path="/profile" component={ProfilePage} exact />
{/* Other routes */}
</Switch>
</Router>
</Provider>
);
ReactDOM.render(<App />, document.getElementById('root'));
Errors
Common errors & fixes
Error: Invalid credentials (or similar network error during login)
The `loginCall` provided to `makeAuthFlow` rejected its promise due to incorrect credentials or a network issue with your authentication API.
fixVerify the `loginCall` function logic, ensuring it correctly handles credentials and communicates with your backend. Check network requests in the browser developer tools for API errors. Ensure the backend returns the `access_token` and `refresh_token` in the expected format.
TypeError: Cannot read properties of undefined (reading 'access_token') or similar when makeAuthFlow is called
The `loginCall` or `refreshTokenCall` functions did not return an object with `access_token` and `refresh_token` keys as expected by `eazy-auth`.
fixReview your `loginCall` and `refreshTokenCall` implementations. Ensure they return a Promise that resolves to an object like `{ access_token: 'your_token', refresh_token: 'your_refresh_token' }`. React Router caught an unhandled error: You used a <Route> outside of a <Routes> context. Or 'AuthRoute' is not a <Route> component.
The `AuthRoute` component is being used with `react-router-dom` v6 or later, which has a different API compared to v4.x, or it's not wrapped within a `<Routes>` (v6) or `<Switch>` (v4/5) component.
fixIf using `react-router-dom` v4 or v5, ensure `AuthRoute` is nested inside `<Switch>`. If using `react-router-dom` v6, the `AuthRoute` component from `eazy-auth` is incompatible. You will need to create a custom protected route component or use the `use-eazy-auth` library which is hooks-based.
Audit
Dependencies
reactrequiredPeer dependency for UI components and HOCs.
react-reduxrequiredPeer dependency for Redux integration in React components.
react-router-domrequiredPeer dependency for `AuthRoute` component to protect routes (targets v4.1.x).
reduxrequiredPeer dependency for Redux store integration, specifically `makeAuthReducer`.
redux-sagarequiredPeer dependency for managing side effects, specifically `makeAuthFlow`.
reselectrequiredPeer dependency for efficient selector creation.