Simplify your Auth flow when working with React apps
This React package allows you to streamline the integration of user authentication flows in any React app by providing a single unified interface
npm install @forward-software/react-authCreate a new object that implements the AuthClient interface provided by this library. The interface includes several lifecycle methods, some of which are optional:
import type { AuthClient } from '@forward-software/react-auth';
// The type for your credentials
type AuthCredentials = {
username: string;
password: string;
};
// The type for your tokens
type AuthTokens = {
authToken: string;
refreshToken: string;
};
const authClient: AuthClient<AuthTokens, AuthCredentials> = {
// Optional: Called when the AuthClient gets initialized
onInit: async (): Promise<AuthTokens | null> => {
// Implement the initialization logic for your client
return null;
},
// Optional: Called after initialization completes
onPostInit: async (): Promise<void> => {
// Implement any post-initialization logic
},
// Optional: Called before login starts
onPreLogin: async (): Promise<void> => {
// Implement any pre-login logic
},
// Required: Called when login is requested
onLogin: async (credentials?: AuthCredentials): Promise<AuthTokens> => {
// Implement the logic required to exchange the provided credentials for user tokens
return {
authToken: '...',
refreshToken: '...'
};
},
// Optional: Called after login completes
onPostLogin: async (isSuccess: boolean): Promise<void> => {
// Implement any post-login logic
},
// Optional: Called before refresh starts
onPreRefresh: async (): Promise<void> => {
// Implement any pre-refresh logic
},
// Optional: Called when refresh is requested
// The current tokens are passed as the first argument
onRefresh: async (currentTokens: AuthTokens, minValidity?: number): Promise<AuthTokens> => {
// Implement the logic required to refresh the current user tokens
return {
authToken: '...',
refreshToken: '...'
};
},
// Optional: Called after refresh completes
onPostRefresh: async (isSuccess: boolean): Promise<void> => {
// Implement any post-refresh logic
},
// Optional: Called before logout starts
onPreLogout: async (): Promise<void> => {
// Implement any pre-logout logic
},
// Optional: Called when logout is requested
onLogout: async (): Promise<void> => {
// Implement the logic required to invalidate the current user tokens
},
// Optional: Called after logout completes
onPostLogout: async (isSuccess: boolean): Promise<void> => {
// Implement any post-logout logic
}
};The AuthClient instance can be used directly with the createAuth function:
import { createAuth } from '@forward-software/react-auth';
export const { AuthProvider, useAuthClient, authClient: enhancedAuthClient } = createAuth(authClient);The createAuth function returns:
AuthProvider, the context Provider component that should wrap your app and provide access to your AuthClientuseAuthClient, the hook to retrieve and interact with your AuthClientauthClient, the enhanced authentication client instance
The context Provider component that should wrap your app and provide access to your AuthClient, this component also accepts 2 additional props
ErrorComponent, displayed when the AuthClient initialization failsLoadingComponent, displayed while the AuthClient is being initialized
The createAuth function wraps your AuthClient implementation with an EnhancedAuthClient that provides additional functionality:
isInitialized, a boolean indicating if the AuthClient has been initializedisAuthenticated, a boolean indicating if the login process has been successful and the user is authenticatedtokens, the current tokens returned by theloginor therefreshprocess
init(), initialize the AuthClient (N.B. this shouldn't be called if usingAuthProvider- see above)login(credentials), start the login processrefresh(), refresh the current tokenslogout(), logout and invalidate the current tokenson(eventName, listenerFn), subscribe toeventNameevents emitted by the AuthClientoff(eventName, listenerFn), unsubscribe fromeventNameevents emitted by the AuthClientsubscribe(() => { }), subscribe to AuthClient state changesgetSnapshot(), returns the current state of the AuthClient
When your app needs to support multiple authentication providers simultaneously (e.g. username/password alongside Google Sign-In), use createMultiAuth:
import { createMultiAuth } from '@forward-software/react-auth';
export const { AuthProvider, authClients, useAuth } = createMultiAuth({
credentials: credentialsAuthClient,
google: googleAuthClient,
});The createMultiAuth function accepts a map of { id: AuthClient } pairs and returns:
AuthProvider, the context Provider component that initialises all clients and provides access to themauthClients, a map of enhanced authentication clients keyed by the IDs you provideduseAuth, a hook that accepts a client ID and returns the corresponding enhanced auth client
The same LoadingComponent and ErrorComponent props are supported. LoadingComponent is shown until all clients finish initializing. ErrorComponent is shown if any client's initialization fails.
<AuthProvider
LoadingComponent={<Spinner />}
ErrorComponent={<ErrorPage />}
>
<App />
</AuthProvider>The useAuth hook is generic — the return type is automatically narrowed to the exact EnhancedAuthClient type for the key you provide:
function MyComponent() {
// Each call is fully typed based on the key
const credentialsClient = useAuth('credentials');
const googleClient = useAuth('google');
return (
<>
<button onClick={() => credentialsClient.login({ username, password })}>
Sign in with credentials
</button>
<button onClick={() => googleClient.login()}>
Sign in with Google
</button>
</>
);
}Each client provides the same EnhancedAuthClient interface described above.
The examples folder in the repository contains some examples of how you can integrate this library in your React app.
Contributions are welcome! Please read the Contributing Guide and the Code of Conduct before submitting a pull request.
This library has been inspired by react-keycloak and similar libraries.
MIT
Made with ✨ & ❤️ by ForWarD Software and contributors
If you found this project to be helpful, please consider contacting us to develop your React and React Native projects.