Giter Club home page Giter Club logo

react-oidc-context's Introduction

react-oidc-context

Stable Release CI Codecov

Lightweight auth library using the oidc-client-ts library for React single page applications (SPA). Support for hooks and higher-order components (HOC).

Table of Contents

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.

The User and UserManager 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.

Installation

Using npm

npm install oidc-client-ts react-oidc-context --save

Using yarn

yarn add oidc-client-ts react-oidc-context

Getting Started

Configure the library by wrapping your application in AuthProvider:

// 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: "<your authority>",
  client_id: "<your client id>",
  redirect_uri: "<your redirect uri>",
  // ...
};

ReactDOM.render(
  <AuthProvider {...oidcConfig}>
    <App />
  </AuthProvider>,
  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):

// src/App.jsx
import React from "react";
import { useAuth } from "react-oidc-context";

function App() {
    const auth = useAuth();

    switch (auth.activeNavigator) {
        case "signinSilent":
            return <div>Signing you in...</div>;
        case "signoutRedirect":
            return <div>Signing you out...</div>;
    }

    if (auth.isLoading) {
        return <div>Loading...</div>;
    }

    if (auth.error) {
        return <div>Oops... {auth.error.message}</div>;
    }

    if (auth.isAuthenticated) {
        return (
        <div>
            Hello {auth.user?.profile.sub}{" "}
            <button onClick={() => void auth.removeUser()}>Log out</button>
        </div>
        );
    }

    return <button onClick={() => void auth.signinRedirect()}>Log in</button>;
}

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 with a Class Component

Use the withAuth higher-order component to add the auth property to class components:

// 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 <div>Hello {auth.user?.profile.sub}</div>;
    }
}

export default withAuth(Profile);

Call a protected API

As a child of AuthProvider with a user containing an access token:

// 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 <div>Loading...</div>;
    }

    return (
        <ul>
        {posts.map((post, index) => {
            return <li key={index}>{post}</li>;
        })}
        </ul>
    );
};

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:

// src/slice.js
import { User } from "oidc-client-ts"

function getUser() {
    const oidcStorage = localStorage.getItem(`oidc.user:<your authority>:<your client id>`)
    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.

import React from 'react';
import { withAuthenticationRequired } from "react-oidc-context";

const PrivateRoute = () => (<div>Private</div>);

export default withAuthenticationRequired(PrivateRoute, {
  onRedirecting: () => (<div>Redirecting to the login page...</div>)
});

Adding event listeners

The underlying UserManagerEvents instance can be imperatively managed with the useAuth hook.

// 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 <button onClick={() => void auth.signinRedirect()}>Log in</button>;
}

export default App;

Automatic sign-in

Automatically sign-in and silently reestablish your previous session, if you close the tab and reopen the application.

// index.jsx
const oidcConfig: AuthProviderProps = {
    ...
    userStore: new WebStorageStateStore({ store: window.localStorage }),
};
// 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 <div>Signing you in/out...</div>;
    }

    if (!auth.isAuthenticated) {
        return <div>Unable to log in</div>;
    }

    return <button onClick={() => void auth.removeUser()}>Log out</button>;
}

export default App;

Contributing

We appreciate feedback and contribution to this repo!

Influences

This library is inspired by oidc-react, which lacks error handling and auth0-react, which is focused on auth0.

License

This project is licensed under the MIT license. See the LICENSE file for more info.

react-oidc-context's People

Contributors

akotranza avatar bryht avatar chrisl108 avatar dennerac avatar dependabot[bot] avatar edwardsilhol avatar gitarcitano avatar jgregory-apogee avatar jrgermain avatar kherock avatar mariusflorescu avatar mikoto2000 avatar pamapa avatar pascalluginbuehl avatar perguth avatar piwysocki avatar psanetra avatar pseidemann avatar rahul-sharma-uipath avatar trollepierre avatar zwyx avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

react-oidc-context's Issues

Callback url causes 404 page to be displayed

In the documentation, it is stated

You still need to setup a redirect uri, which must point to your application, but you do not need to create that route.

I found this misleading because in the common case of using react-router-dom@6 with a 404 catch-all route, the 404 page is displayed when the code exchange callback route is navigated to.

Should we not encourage the user to set up a route like so?

 <Route path={ROUTES.CALLBACK} element={<LoadingIndicator />} />

Allow access to the underlying UserManager instance

Thanks for the great work!

Currently, you don't surface the entire UserManager object which has access to callbacks and methods unavailable from anywhere else such as:

signoutRedirectCallback
signoutPopupCallback
querySessionStatus

Ideally, you could just surface the UserManager alongside the User instance

Keycloak login sequence is not triggered

I use the component just like in the example for keycloak and I expect to be redirected to a login page or at least some kind of action but nothing happens. The app just loads the initial page without triggering any login sequence.

Any ideas what might be wrong? Maybe this is keycloak specific?

import React from 'react';
import BaseLayout from './BaseLayout';
import { QueryClientProvider } from 'react-query';
import ReactQueryClient from '../api/rq-client';
import { AuthProvider } from 'react-oidc-context';

const oidcConfig = {
  authority: 'http://192.168.0.230:8081/auth/realms/xxx',
  client_id: 'zzz',
  redirect_uri: 'http://localhost:8000/'
};

export default ({ children }) => {
  return (
    <AuthProvider {...oidcConfig}>
      <QueryClientProvider client={ReactQueryClient}>
        <BaseLayout>{children}</BaseLayout>
      </QueryClientProvider>
    </AuthProvider>
  );
};

User logout at the end of the session

Hi,

when activating monitorSession on UserManagerSettings an iframe is created to check the session and trigger events if the session is closed (it's the OIDC Session Management). The AuthProvider hides the UserManager instance and therefore the events.
It would be great to provide access to these events or to implement addUserSignedOut in order to enable Single Logout.

userManager.events.addUserSignedOut(async () => {
  console.log('OP session close: user signed out...')
  userManager.signoutRedirect()
})

Multiple instances?

Thanks for the great library, took me some time to stumble across it but looks to be exactly what I need.

There doesn't appear to be support for multiple instances of the OIDC client, where a single SPA may need to authenticate against multiple different identity servers at the same time - do you have any ideas for how this could be worked around?

Similar to how https://github.com/AxaGuilDEv/react-oidc manages this: multiple configurations can be applied and then the hook can refer to a configuration to pull out a specific client instance.

unclear how to sign out without hooks

Our project was using AppAuth-JS library before discovering this. It is much more succinct and sensible so thank you.

One of the challenges faced in using this library: we are using Apollo client to make GraphQL requests and we use a link to detect 401 errors. From the link, it's not clear how one could trigger a signout redirect. Thus, as a workaround, a boolean flag needsSignoutRedirect was created in our redux store which gets picked up by a React hook which performs the signout.

How can one halt all rendering while the page redirects though? If the network error reaches the query hook, the page will display an error message momentarily. Throwing an error in the link and catching it in the error boundary in order to halt the rendering cycles could prevent the hook from catching the needsSignoutRedirect flag.

Yarn doesn't provide oidc-client-ts (pb9389), requested by react-oidc-context

I am trying to use this package in my react+vite+yarn project

when I try to install this I get this error

➤ YN0002: │ my-client@workspace:. doesn't provide oidc-client-ts (pb9389), requested by react-oidc-context
➤ YN0000: │ Some peer dependencies are incorrectly met; run yarn explain peer-requirements <hash> for details, where <hash> is the six-letter p-prefixed code

When I ask it to explain using yarn explain peer-requirements pb9389

➤ YN0000: my-client@workspace:. doesn't provide oidc-client-ts, breaking the following requirements:
➤ YN0000: react-oidc-context@npm:2.0.0 [57633] → ^2.0.0-rc.4 ✘

As a result I can reference useAuth() in my app but it fails on compile as the oidc-client-ts package is not actually being
installed.

Edit: manually installing the package with yarn add oidc-client-ts gets the app running for now.

oidcStorage does not get any value i'm using it in right way?

"react-oidc-context": "^2.1.0",
"oidc-client-ts": "^2.0.4",

  const oidcConfig = {
    authority: `${process.env.OIDC_AUTHORITY}`,
    client_id: `${process.env.OIDC_CLIENT_ID}`,
    redirect_uri: props.location.origin,
    metadataUrl: `${process.env.OIDC_METADATA_URL}`
  };
import { User } from "oidc-client-ts"

function getUser() {
  const oidcStorage =  localStorage.getItem(
    `oidc.user:${process.env.OIDC_AUTHORITY}:${process.env.OIDC_CLIENT_ID}`
  );
  if (!oidcStorage) {
    return null;
  }

  return User.fromStorageString(oidcStorage);
}

The useAuth Working Perfect 👌

Can't perform post-login actions in event handler

I did this

useEffect(() => auth.events.addUserLoaded(() => {
    dispatch({
      type: UserActionTypes.SET_LOGGED_IN_USER,
      payload: auth,
    });
    navigate(ROUTES.LOCATION);
  }), [auth.events]);

in order to set up some post-login state and navigation changes. The state doesn't seem to update and the following warning appears in the console You should call navigate() in a React.useEffect(), not when your component is first rendered.. I don't think it is possible to use an effect for this because of how the callback routing works. (Aside: It took me some trial and error to find the right event as addUserSignedIn seems just as likely a candidate).

Unable to change redirect_uri after provider has mounted

Effectively I have a component with logic similar to:

const MyComponent = () => {
     // Hook that changes with every single page move returning the current URL 
     const path = useBrowserPath();

     const oidcConfig = {
         // ...
         redirect_uri: path,
     }

      return <AuthProvider {...oidcConfig}>
              <App />
       </AuthProvider>;
}

The problem is that changing any of the configuration does not cause the auth provider to update the settings nor does it reconstruct the user manager.

As my goal here is to just update the redirect uri periodically I did also try to set the useAuth().settings.redirect_uri etc but since the OidcClient has its own copy of the settings it does not change the redirect_uri it uses.

I believe this is a bug as it should be possible to change this configuration, however please do let me know if theres something fundamentally incorrect with attempting to change the settings/redirect_uri.

More than one Auto Renewal calls are happening in sequence

Hi team,

I am this library for oauth2.0 implementation . It has been observed that, some times it is making two successive calls to token -end point in silent renewal of access_token.
Though first call is successful, it is making the second call immediately to get the access token and refresh token,
and next time ,
when the refresh token used in the previous call is used in token rotation, I am getting the error response from server saying,

{"error_descirption":"Unknown, invalid or expired refresh token" , "error":"invalid_grant"}

Could some one please help me to sort out this issue.

Callback for loading existing credentials?

(This can be either documentation request or a new feature request, I am not sure)

My react app uses Redux to store user info, and I am trying to set it from the addUserLoaded callback and from onSigninCallback config callback. It seems to work , but only during initial signin, when no valid credentials are present.

When I reload the application, neither of those callbacks appear to be triggered. It goes straight to the authenticated state.

Is there another or more universal callback available which can be used to "catch" when user credentials are either loaded or found in the local storage? I want to avoid trying to deduce it from useAuth().user. In the past we used Amplify and did period checks for this but it seems hacky and now impossible to do without direct access to UserManager (I saw #331).


My callback in the AuthProvider config:

const oidcStateStore = new oidcClient.WebStorageStateStore({
  store: window.localStorage,
});

const oidcConfig: OidcAuthProviderProps = {
      authority: 'https://...',
      client_id: 'client1',
      redirect_uri: window.location.origin,
      loadUserInfo: true,
      userStore: oidcStateStore,
      automaticSilentRenew: false,
      onSigninCallback: (user: oidcClient.User | void): void => {
        window.history.replaceState(
          {},
          document.title,
          window.location.pathname,
        );
        // set user info in Redux store
      },
    };

My addUserLoaded callback:

const auth = useAuth();

useEffect(() => {
  return auth.events.addUserLoaded((user: User) => {
    // set user info in Redux store
  });
}, [auth.events]);

Completing login after signInRedirect

Hi,

We are trying to switch to this library instead of vanilla oidc-client.

In our previous implementation, after calling signInRedirect when the authentication is returned, our redirect_url page contains code that will complete the login by calling userManager.signinRedirectCallback() which completes the authentication by exchanging the authorization code for an access token.

I can't find an example of how this is done in the library.

I would also like to know if this library handles silentRenewal and how to implement.

Can't figure out how to handle redirect

The documentation doesn't mention what value should be put into redirect_url. Is it supposed to be to a route you create? Or does it crate it on it's own? If you have to create it, it should probably mention what to create and how to create it!

Add a variable to indicate that a navigator is active

I have an app that attempts a silent sign in immediately upon loading. It waits for isLoading to become false and then issues a silent sign in request if isAuthenticated is also false. Within this component, I have state keeping track of this request so that it doesn't duplicate the request on a subsequent rerender.

This works but it gets ugly when I want to make a sign out request elsewhere in the app. Since the component isn't aware that the application initiated a sign out request when the user unloads, the component sees that 1. isLoading is still false and 2. isAuthenticated is also false again. Therefore, to stop the silent sign in from running again, I need another variable that lets the component know that it isn't appropriate to initiate a silent sign in despite being unauthenticated.

The simplest solution that works for me would be to set isLoading: true while the promise for signInRedirect, signoutRedirect, etc. are resolving. In addition to this, I could see it also being useful to add another context variable like activeNavigator: 'redirect' | 'popup' | 'iframe'. This would allow the application to display more meaningful progress indicators, e.g.

  • display an page loading progress bar at the top of the page when activeNavigator === 'redirect'
  • display a full screen hint to retry the popup flow in case the navigator fails when activeNavigator === 'popup'
  • show an animated splash screen when activeNavigator === 'iframe'

Error: No matching state found in storage - at OidcClient.readSigninResponseState

Hi@all

When I refresh the page, I get logged out.
Reproduce:

  1. Click login button
  2. Login via keycloak/openid
  3. Redirect back (address is: https://helpme.test/de/admin/organizations?state=311b124c928e4cd3a5b282fd16dd4475&session_state=2793988e-f78f-4d42-8164-61ab7697af9e&code=4bdf7c6d-7d29-4d8c-95a9-0913b62591a7.2793988e-f78f-4d42-8164-61ab7697af9e.e1f6f519-030c-4204-beab-f4dfe064baa7)
  4. Refresh page (Command+R)
  5. Now i am logout and have follow error

Error:

Error: No matching state found in storage
    at OidcClient.readSigninResponseState (oidc-client-ts.js:1443:1)
    at async UserManager.signinCallback (oidc-client-ts.js:2312:21)
    at async react-oidc-context.js:154:1

oidc-client-ts.js:1443:1:

  async readSigninResponseState(url, removeState = false) {
    const logger2 = this._logger.create("readSigninResponseState");
    const response = new SigninResponse(UrlUtils.readParams(url, this.settings.response_mode));
    if (!response.state) {
      logger2.throw(new Error("No state in response"));
      throw null;
    }
    const storedStateString = await this.settings.stateStore[removeState ? "remove" : "get"](response.state);
    if (!storedStateString) {
=>>>>>>>>>>>>>>>>>>>>>>>      logger2.throw(new Error("No matching state found in storage"));
      throw null;
    }
    const state = SigninState.fromStorageString(storedStateString);

Does anyone have any idea what went wrong?

do not try to load user in error case

oidc-client.min.js:formatted:1 OidcClient.readSigninResponseState: No matching state found in storage
App.tsx:55 {isLoading: false, isAuthenticated: false, error: Error: No matching state found in storage
    at http://localhost:5000/static/js/vendors~main.chunk…, settings: e, clearStaleState: ƒ, …}
oidc-client.min.js:formatted:1 WebStorageStateStore.get user:https://myid-qa.siemens.com:2ca796cc-9e05-4e1b-b2e6-35b737b05778
oidc-client.min.js:formatted:1 UserManager._loadUser: no user storageString
oidc-client.min.js:formatted:1 UserManager.getUser: user not found in storage
App.tsx:55 {isLoading: false, isAuthenticated: false, error: undefined, user: null, settings: e, …}

Iff userManager.signinCallback fails userManager.getUser must not be called otherwise error state is lost.

WebStorageStateStore is not working in SSR

The intent is to use this component in Next.js app entry point:

function CustomApp({
    Component,
    pageProps
}: AppPropsWithLayout): JSX.Element {

    const oidc: AuthProviderProps = {
        authority: "http://localhost:5064",
        client_id: "front-end",
        redirect_uri: "http://localhost:3000/oauth2/callback",
        scope: 'openid profile email app',
        prompt: 'login',
        loadUserInfo: true,
        userStore: new WebStorageStateStore({
            store: localStorage
        }),
        onSigninCallback: () => {
            window.history.replaceState(
                {},
                document.title,
                window.location.pathname
            );
            const postLoginRedirectUri = sessionStorage.getItem('post_login_redirect');
            if (postLoginRedirectUri) {
                location.href = postLoginRedirectUri;
                sessionStorage.removeItem('post_login_redirect');
            } else {
                location.href = '/';
            }
        }
    };

    const withLayout = Component.layout ?? (page => page);
    return (
        <AuthProvider {...oidc}>
            {withLayout(<Component {...pageProps} />)}
        </AuthProvider>
    );
}

The problem is, localStorage is not available when the page is first rendered in server-side. Wrapping the userStore: assignment in useEffect (to wait for the component to be mounted in browser) does not seem to work either.

improve support

  • add troubleshooting section (howto get a good log, ...) in README.md
  • add issue template (versions, known working versions, logging, ...)

How to handle error during signInSilent?

I have this code

useEffect(() => {
    if (!auth.isAuthenticated && acr) {
      const config: UserManagerSettings = {
        authority: "https://test.com/identity",
        ...
        acr_values: acr
      };
  
      auth.signinSilent(config);
    }
  }, [auth.isAuthenticated])

If error is thrown by Identity Server, for example I'm getting Uncaught (in promise) ErrorResponse: login_required. I want to be able to handle this and log the user out so the user will need to re-authenticate. How do I achieve this?

remove fragment mode

once we bump to the next beta version of oidc-client-ts, it dropped the implicit flow, supporting fragment mode is no longer needed

Installation not properly

I have tried to install "react-oidc-context" but not able to install it properly.
I have removed node-module and try to install fresh but still not properly installed.
See below screen shot. When i tried to install it I am getting only this three file in node-module/react-oidc-context/...
Screenshot 2021-06-01 at 1 39 29 PM

In order to use this library , do I need to install typescript npm?
Kindly help me.
Thank you.

How to get custom claims included in JWT

I am getting a JWT token that includes a custom field in the payload called name. When I view the results of useAuth(), stored in a variable called auth, I can see the user object which contains the profile object where I would expect the name to be, except the name field is not there. When I decrypt the token stored in auth I can see the name field just fine. Am I supposed to access the name using a different method other than auth.user.profile.name?

An example of how the payload is setup is

{
    "name": "John Doe",
    ...
}

example build error

react-oidc-context\example\index.tsx: Invalid Version: undefined

cd example
npm i
npm start
results in an error

authentication upon loading(no login button)

First of all, thanks for this great library. I have a SPA that requires the users to authenticate upon loading without having to click on the login button. Is there a way to achieve this? My code pretty much looks similar to the example shared.

index.tsx


const oidcConfig = {
authority: "",
client_id: "",
redirect_uri: ""
}

ReactDOM.render(
<React.StrictMode>
<AuthProvider {...oidcConfig}>


</React.StrictMode>,
document.getElementById('root')
);

Thanks for your help.

`activeNavigator` is always `undefined`

I'm currently trying to utilize this lib in a new React project. So far it works great. The only thing I did not manage to use is the activeNavigator property.

Regardless where I put it and what I try to do, it is always undefined. Is there maybe a small hint how I can catch the signinSilent?

Maybe I should explain my problem a little bit more in detail. I want to redirect the user to a react route after login, so I created a Route in the BrowserRouter matching to the callback. In consequence this gets also triggered in case of the silent signIn. I want to avoid this 😉

I want to prevent the data to be stored in the session storage

Hello, I am facing an issue where after the user logged in using IdentityServer 4, he will be redirected to the react application and the data will be stored in session storage. I only want to receive access token from the server and to be stored in cookies as http only
Can someone help me?

The following image is what I dont want it to be like that.
image

idle time out for refresh token

Hi team,

I idle time out for refresh token is enabled on auth server side. It is said that, if the user is inactive on application for >=30 minutes, the refresh token will be revoked due to idle time out.

But it has been observed that , it is not happening when the application is idle for >=30 minutes, it is not applying , but it is applied when the system is idle for >=30 minutes.

Could you please suggest me . what could be the reason for this behaviour ? do we have any option to enable idle time out timer for refresh token ?

Error running test: "AuthProvider context is undefined, please verify you are calling useAuth() as child of a <AuthProvider> component."

Now that I have added the auth code in my Component, I am getting the above error while running the tests. Below is my test code

MyComponent.test.tsx


jest.mock('axios');
const mockedAxios = axios as jest.Mocked;

jest.mock('../../services/MyService');
const mockedMyService = MyService as jest.Mocked;

describe('App', () => {
const renderComponent = () => (render());
..........

index.tsx


import { AuthProvider } from "react-oidc-context";

const oidcConfig = {
authority: EnvConfigs['authority'],
client_id: EnvConfigs['client_id'],
redirect_uri: EnvConfigs['redirect_uri']
}

ReactDOM.render(
<React.StrictMode>
<AuthProvider {...oidcConfig}>


</React.StrictMode>,
document.getElementById('root')
);

App.tsx


import { useAuth } from "react-oidc-context";

const App = () => {
const auth = useAuth();
^

The error is on the line above. Looks like 'auth" above is always undefined.

Could you please provide some insights into why my test is failing? The app is working fine though.

automaticSilentRenew with stored data creates two Auth instances

Here is the scenario:

  • User authorizes once, the data gets stored in session storage.
  • Without closing the browser, user reloads the application.

Now, since the automaticSilentRenew is true by default, the OIDC will try to renew the token automatically. The problem is that it tries to do that TWICE, for some odd reason.

And both of the times, it sends same payload. So, the first request passes, but second one always fails, since the refresh token is obsolete now.

But, disabling the automaticSilentRenew and doing it manually works just fine:

// disable default auto-renew in config
automaticSilentRenew: false


// then down in the child component

const auth = useAuth();

useEffect(() => {
    // make renew manually
    return auth.events.addAccessTokenExpiring(() => {
	auth.signinSilent();
    });
}, [auth]);

This way only one refresh request gets called per application.

This issue doesn't appear if user closes the browser (session storage gets destroyed), and reopens it.

How do I access state.data on signinCallback.

If I want to put the url being accessed in state while the user is being sent to the OIDC provider I think I could do this.

      auth.signinRedirect({
        state: '/some/relative/url',
      })

I can see this is stored as data under the stateStorage. But when the Callback comes back I can't seem to find a way to intercept it. The onSigninCallback only gets the User object. What am I missing.

Can't enable monitorSession

There is a feature in oidc-client-js which can check session via /connect/checksession Endpoint. When the session in OP is changed, the client will raise and session Changed event.

But this feature can't enabled in react-oidc-context. It fails to auth when this feature enabled and go in infinity loop ..

authorization code with pkce?

Hello, Thank you for building and maintaining this amazing project.
I've been looking for a way to implement OIDC, especially for one that follows authorization code with PKCE flow, and found this project but I had a hard time to find information about whether it supports the authorization code with PKCE or not...
Is it something I need to implement on top of this project or is it already supported by the project?

Any comments would be appreciated! Thank you!

isLoading never 'true' with upgrade to react 18

Been using the library seamlessly up until now so many thanks for this.
Recently I upgraded to react 18 and noticed some weird render behaviour that was previously working fine.

my config is

export const oidcConfig = {
  authority: '....',
  client_id: '....',
  redirect_uri: '...',
  post_logout_redirect_uri: '....',
  scope: 'openid profile roles',
  monitorSession: true,
  loadUserInfo: true,
  userStore: new WebStorageStateStore({ store: window.localStorage }),
}

I have a button that initiates signinRedirect onClick. In the layout of my app, Im using isLoading from useAuth to render a loading page for the brief seconds before/after redirect takes place where isLoading becomes true.
After upgrading to react18, isLoading always returns as false or doesn't return anything at all.
This is a react typescript app.

Local Storage filling up with oidc.<id>

Hi there,

On each login / refresh of the page, there are 4 entries being created in the local storage that contain: oidc.<id>.
To be exact, I think this may happen because there are 4 really fast redirects going on (since the useEffect with an empty dependency array is being triggered 4 times).

This becomes a problem since the storage might fill up pretty fast. I've also read this issue, but doesn't seem to be working out.

To give you a little bit of context, I'm using Auth0 as IDP and this is the config that I'm currently using:

const authConfig = {
  authority: 'example',
  client_id: 'example',
  loadUserInfo: true,
  monitorAnonymousSession: true,
  userStore: new WebStorageStateStore({ store: new InMemoryWebStorage() }),
  filterProtocolClaims: true,
  monitorSession: true,
  extraQueryParams: { audience: 'example' },
  redirect_uri: window.location.origin
}

Documentation on how to enable `state` parameter

Hi Team,

We're trying to determine if state OAuth2 parameter can be auto-generated and verified by this library, or if this is something that the client should implement on their own. Do you have any clarifying documentation on it?

Thank you

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.