https://github.com/authts/react-oidc-context
Lightweight auth library based on oidc-client-ts for React single page applications (SPA). Support for hooks and higher-order components (HOC).
https://github.com/authts/react-oidc-context
hooks oidc oidc-client react reactjs spa typescript
Last synced: 11 days ago
JSON representation
Lightweight auth library based on oidc-client-ts for React single page applications (SPA). Support for hooks and higher-order components (HOC).
- Host: GitHub
- URL: https://github.com/authts/react-oidc-context
- Owner: authts
- License: mit
- Created: 2021-05-05T14:06:29.000Z (almost 4 years ago)
- Default Branch: main
- Last Pushed: 2025-04-09T12:51:02.000Z (12 days ago)
- Last Synced: 2025-04-09T13:01:52.294Z (12 days ago)
- Topics: hooks, oidc, oidc-client, react, reactjs, spa, typescript
- Language: TypeScript
- Homepage:
- Size: 6.27 MB
- Stars: 822
- Watchers: 11
- Forks: 80
- Open Issues: 84
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
# react-oidc-context
[](https://npm.im/react-oidc-context)
[](https://github.com/authts/react-oidc-context/actions/workflows/ci.yml)
[](https://app.codecov.io/gh/authts/react-oidc-context)Lightweight auth library using the
[oidc-client-ts](https://github.com/authts/oidc-client-ts) library for React
single page applications (SPA). Support for
[hooks](https://reactjs.org/docs/hooks-intro.html) and
[higher-order components (HOC)](https://reactjs.org/docs/higher-order-components.html).## Table of Contents
- [Documentation](#documentation)
- [Installation](#installation)
- [Getting Started](#getting-started)
- [Contributing](#contributing)
- [Influences](#influences)
- [License](#license)## Documentation
This library implements an auth context provider by making use of the
`oidc-client-ts` library. Its configuration is tight coupled to that library.- [oidc-client-ts](https://github.com/authts/oidc-client-ts)
The
[`User`](https://authts.github.io/oidc-client-ts/classes/User.html)
and
[`UserManager`](https://authts.github.io/oidc-client-ts/classes/UserManager.html)
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](https://authts.github.io/oidc-client-ts/interfaces/UserManagerSettings.html#automaticSilentRenew)
feature of `oidc-client-ts` can be used.## Installation
Using [npm](https://npmjs.org/)
```bash
npm install oidc-client-ts react-oidc-context --save
```Using [yarn](https://yarnpkg.com/)
```bash
yarn add oidc-client-ts react-oidc-context
```## Getting Started
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 state
(`isLoading`, `isAuthenticated` and `user`) and authentication methods
(`signinRedirect`, `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":
returnSigning you in...;
case "signoutRedirect":
returnSigning you out...;
}if (auth.isLoading) {
returnLoading...;
}if (auth.error) {
returnOops... {auth.error.kind} caused {auth.error.message};
}if (auth.isAuthenticated) {
return (
Hello {auth.user?.profile.sub}{" "}
void auth.removeUser()}>Log out
);
}return void auth.signinRedirect()}>Log in;
}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](https://github.com/authts/react-oidc-context/blob/f175dcba6ab09871b027d6a2f2224a17712b67c5/src/AuthProvider.tsx#L20-L30).
### Use with a Class Component
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;
returnHello {auth.user?.profile.sub};
}
}export default withAuth(Profile);
```### Call a protected API
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) {
returnLoading...;
}return (
- {post} ;
{posts.map((post, index) => {
return
})}
);
};
export default Posts;
```
As **not** a child of `AuthProvider` (e.g. redux slice) when using local storage
(`WebStorageStateStore`) 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}`,
},
});
},
// ...
)
```
### Protect a route
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: () => (
});
```
### Adding event listeners
The underlying [`UserManagerEvents`](https://authts.github.io/oidc-client-ts/classes/UserManagerEvents.html) 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 void auth.signinRedirect()}>Log in;
}
export default App;
```
### Automatic sign-in
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
}
if (!auth.isAuthenticated) {
return
}
return void auth.removeUser()}>Log out;
}
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
}
if (!isAuthenticated) {
return
}
if(error) {
return
}
return
}
export default App;
```
## Contributing
We appreciate feedback and contribution to this repo!
## Influences
This library is inspired by [oidc-react](https://github.com/bjerkio/oidc-react),
which lacks error handling and
[auth0-react](https://github.com/auth0/auth0-react), which is focused on auth0.
## License
This project is licensed under the MIT license. See the
[LICENSE](https://github.com/authts/react-oidc-context/blob/main/LICENSE) file
for more info.