maxmantz / redux-oidc

A package for managing OpenID Connect authentication in ReactJS / Redux apps
MIT License
400 stars 111 forks source link

Update UserManager authority after creation? #190

Open slutske22 opened 3 years ago

slutske22 commented 3 years ago

I have a scenario where my application makes a call to the server to get more information about the OIDC client to be used. Specifically, what port the OIDC can be found at. This call does not happen until the app is loaded and the store was created. I create and use my userManager as described in the docs:

// UserManager.tsx:

const userManagerConfig: UserManagerSettings = {
  authority: defaultAuthorityUrl,
  ...
};

export const userManager = createUserManager(userManagerConfig);
// index.tsx:

import { userManager } from './UserManager';

const store = createStore(args);
loadUser(store, userManager);

ReactDOM.render(
  <Provider store={store}>
    <App />
  </Provider>,
  document.getElementById("root")
);
// App.tsx

const App: React.FC<StateProps> = (props: StateProps) => {
  const dispatch = useDispatch();

  useEffect(() => {
    dispatch(requestAuthSettings());
  }, []);

  return (
    <OidcProvider userManager={userManager} store={store}>
      <ArrivalPage />
    </OidcProvider>
  );
};

The the App is created with the userManager and whatever default authority in there. However, when App mounts, it calls requestAuthSettings, which is a redux action creator that triggers an api call. When the call returns, I use sagas to process the response. They response contains a port where the OIDC authority can be found. Based on the user's installation of the application, this may be different from the default.

Is there a way to update the authority after creation? While examining the userManager object, there is the _settings property which contains the _authority string. Once the response comes back, I'm tempted to just do this:

// sagas.ts

import { userManager } from './UserManager';

function* handleRequestAuthSettings(): Generator {
  try {
    const response = yield call(axios.get, "/api/authSettings");
    userManager._settings._authority = `http://myoidc.provider:${response.data.port}`;
  } catch (e) { ... } 
}

But I have a feeling that directly settings the ._settings._authority property like that is a very bad idea, and will not create consistent results. I'm bending over backwards trying to come up with ways to only create the userManager and call loadUser after the store is created, but its causing various refresh / flickering problems. Is there a better way to do this?

anto-pt commented 3 years ago

@maxmantz Is there a way to load the sso configurations from API call response in the UserManagerSettings. (issuer url, client id, client secret). The api call function is not waiting to load the config. Already got struggled for 2 days. Any help would be appreciated.

I already saw this link. But it doesn't help.

https://stackoverflow.com/questions/58979818/react-populate-usermanagersettings-using-external-configuration