OpenID Connect & OAuth2 authentication using react context api as state management
npm install react-oidc-context


Lightweight auth library using the
oidc-client-ts library for React
single page applications (SPA). Support for
hooks and
higher-order components (HOC).
- Documentation
- Installation
- Getting Started
- Contributing
- Influences
- License
This library implements an auth context provider by making use of theoidc-client-ts library. Its configuration is tight coupled to that library.
TheUser
andUserManager
is hold in this context, which is accessible from the
React application. Additionally it intercepts the auth redirects by looking at
the query/fragment parameters and acts accordingly. You still need to setup a
redirect uri, which must point to your application, but you do not need to
create that route.
To renew the access token, the
automatic silent renew
feature of oidc-client-ts can be used.
Using npm
``bash`
npm install oidc-client-ts react-oidc-context --save
Using yarn
`bash`
yarn add oidc-client-ts react-oidc-context
Configure the library by wrapping your application in AuthProvider:
`jsx
// src/index.jsx
import React from "react";
import ReactDOM from "react-dom";
import { AuthProvider } from "react-oidc-context";
import App from "./App";
const oidcConfig = {
authority: "
client_id: "
redirect_uri: "
// ...
};
ReactDOM.render(
document.getElementById("app")
);
`
Use the useAuth hook in your components to access authentication stateisLoading
(, isAuthenticated and user) and authentication methodssigninRedirect
(, removeUser and signOutRedirect):
`jsx
// src/App.jsx
import React from "react";
import { useAuth } from "react-oidc-context";
function App() {
const auth = useAuth();
switch (auth.activeNavigator) {
case "signinSilent":
return
if (auth.isLoading) {
return
if (auth.error) {
return
if (auth.isAuthenticated) {
return (
return ;
}
export default App;
`
You must provide an implementation of onSigninCallback to oidcConfig to remove the payload from the URL upon successful login. Otherwise if you refresh the page and the payload is still there, signinSilent - which handles renewing your token - won't work.
A working implementation is already in the code here.
Use the withAuth higher-order component to add the auth property to class
components:
`jsx
// src/Profile.jsx
import React from "react";
import { withAuth } from "react-oidc-context";
class Profile extends React.Component {
render() {
// this.props.auth has all the same properties as the useAuth hook
const auth = this.props.auth;
return Hello {auth.user?.profile.sub};
}
}
export default withAuth(Profile);
`
As a child of AuthProvider with a user containing an access token:
`jsx
// src/Posts.jsx
import React from "react";
import { useAuth } from "react-oidc-context";
const Posts = () => {
const auth = useAuth();
const [posts, setPosts] = React.useState(Array);
React.useEffect(() => {
(async () => {
try {
const token = auth.user?.access_token;
const response = await fetch("https://api.example.com/posts", {
headers: {
Authorization: Bearer ${token},
},
});
setPosts(await response.json());
} catch (e) {
console.error(e);
}
})();
}, [auth]);
if (!posts.length) {
return
return (
export default Posts;
`
As not a child of AuthProvider (e.g. redux slice) when using local storageWebStorageStateStore
() for the user containing an access token:
`jsx
// src/slice.js
import { User } from "oidc-client-ts"
function getUser() {
const oidcStorage = localStorage.getItem(oidc.user:)
if (!oidcStorage) {
return null;
}
return User.fromStorageString(oidcStorage);
}
export const getPosts = createAsyncThunk(
"store/getPosts",
async () => {
const user = getUser();
const token = user?.access_token;
return fetch("https://api.example.com/posts", {
headers: {
Authorization: Bearer ${token},`
},
});
},
// ...
)
Secure a route component by using the withAuthenticationRequired higher-order component. If a user attempts
to access this route without authentication, they will be redirected to the login page.
`jsx
import React from 'react';
import { withAuthenticationRequired } from "react-oidc-context";
const PrivateRoute = () => (
export default withAuthenticationRequired(PrivateRoute, {
OnRedirecting: () => (
$3
UserManagerEvents instance can be imperatively managed with the useAuth hook.`jsx
// src/App.jsx
import React from "react";
import { useAuth } from "react-oidc-context";function App() {
const auth = useAuth();
React.useEffect(() => {
// the
return is important - addAccessTokenExpiring() returns a cleanup function
return auth.events.addAccessTokenExpiring(() => {
if (alert("You're about to be signed out due to inactivity. Press continue to stay signed in.")) {
auth.signinSilent();
}
})
}, [auth.events, auth.signinSilent]); return ;
}
export default App;
`$3
Automatically sign-in and silently reestablish your previous session, if you close the tab and reopen the application.
`jsx
// index.jsx
const oidcConfig: AuthProviderProps = {
...
userStore: new WebStorageStateStore({ store: window.localStorage }),
};
``jsx
// src/App.jsx
import React from "react";
import { useAuth, hasAuthParams } from "react-oidc-context";function App() {
const auth = useAuth();
const [hasTriedSignin, setHasTriedSignin] = React.useState(false);
// automatically sign-in
React.useEffect(() => {
if (!hasAuthParams() &&
!auth.isAuthenticated && !auth.activeNavigator && !auth.isLoading &&
!hasTriedSignin
) {
auth.signinRedirect();
setHasTriedSignin(true);
}
}, [auth, hasTriedSignin]);
if (auth.isLoading) {
return
Signing you in/out...;
} if (!auth.isAuthenticated) {
return
Unable to log in;
} return ;
}
export default App;
`#### useAutoSignin
Use the
useAutoSignin hook inside the AuthProvider to automatically sign in.`jsx
// src/App.jsx
import React from "react";
import { useAutoSignin } from "react-oidc-context";function App() {
// If you provide no signinMethod at all, the default is signinRedirect
const { isLoading, isAuthenticated, error } = useAutoSignin({signinMethod: "signinRedirect"});
if (isLoading) {
return
Signing you in/out...;
} if (!isAuthenticated) {
return
Unable to log in;
} if(error) {
return
An error occured
} return
Signed in successfully;
}export default App;
``We appreciate feedback and contribution to this repo!
This library is inspired by oidc-react,
which lacks error handling and
auth0-react, which is focused on auth0.
This project is licensed under the MIT license. See the
LICENSE file
for more info.