oidc-client
oidc-client copied to clipboard
Questions about migrating from `@axa-fr/react-oidc-redux` v3 to `@axa-fr/react-oidc` v5
Issue and Steps to Reproduce
I'm currently migrating a project which was using @axa-fr/react-oidc-redux
v3 to @axa-fr/react-oidc
v5 and I have troubles understanding the migration guide.
My project was using the notAuthorized
and UserStore
props on the provider component but they do not exist anymore on last version. By which new props should I replace them?
Same in the configuration
prop of the provider, the fields automaticSilentReview
, loadUserInfo
, post_logout_redirect_url
and response_type
were used but do not exist anymore. Which fields should I now used instead?
Thanks in advance for your responses.
Hi @ulrik59 , do you have a sample of your old redux code?
You have to compose your redux mapping with the new hook.
import { useOidcUser, UserStatus } from '@axa-fr/react-oidc';
const DisplayUserInfo = () => {
const{ oidcUser, oidcUserLoadingState } = useOidcUser();
switch (oidcUserLoadingState){
case UserStatus.Loading:
return <p>User Information are loading</p>;
case UserStatus.Unauthenticated:
return <p>you are not authenticated</p>;
case UserStatus.LoadingError:
return <p>Fail to load user information</p>;
default:
return (
<div className="card text-white bg-success mb-3">
<div className="card-body">
<h5 className="card-title">User information</h5>
<p className="card-text">{JSON.stringify(oidcUser)}</p>
</div>
</div>
);
}
};
response_type does not exist anymore only code with pcke is supported automaticSilentReview does not exist any more. If you do not set silent_redirect_uri, you won't have silent auto renew.
post_logout_redirect_url has been replaced by a property inside logout function
Hello @guillaume-chervet , thanks for your answer.
I can then safely remove response_type
and automaticSilentReview
. I assume I can also safely remove the loadUserInfo
field.
On my app, there is really few code used:
// src\layout\App\App.tsx
import React from 'react';
import { BrowserRouter } from 'react-router-dom';
import { InMemoryWebStorage, Oidc, OidcSecure } from '@axa-fr/react-oidc-redux';
import store from '../../store';
import NotAuthorized from '../NotAuthorized';
import Footer from '../Footer';
import Header from '../Header';
import Routes from '../Routes';
interface AppAuthConfig {
automaticSilentRenew: true;
loadUserInfo: true;
authority: string;
client_id: string;
post_logout_redirect_uri: string;
redirect_uri: string;
response_type: 'code';
silent_redirect_uri: string;
scope: string;
}
const App: React.VFC<{ configuration: AppAuthConfig }> = ({ configuration }) => (
<Oidc store={store} configuration={configuration} UserStore={InMemoryWebStorage} notAuthorized={NotAuthorized}>
<BrowserRouter>
<OidcSecure>
<div className="app">
<div className="app__sub-container">
<Header />
<Routes />
</div>
<Footer />
</div>
</OidcSecure>
</BrowserRouter>
</Oidc>
);
// src\store\rootReducer.ts
import { reducer as oidc } from '@axa-fr/react-oidc-redux';
import { combineReducers } from 'redux';
const rootReducer = combineReducers({ oidc });
// src\store\oidc\selectors.ts
import { RootState } from '../rootReducer';
export const selectOidcUser = (state: RootState): User | undefined => state?.oidc?.user;
// src\store\oidc\selectors.ts
import { RootState } from '../rootReducer';
export const selectOidcUser = (state: RootState): User | undefined => state?.oidc?.user;
// src\pages\AccountEdit\AccountEditForm.tsx
import { withAuthentication } from '@axa-fr/react-oidc-redux-fetch';
import React from 'react';
import { useDispatch } from 'react-redux';
import { useParams } from 'react-router-dom';
import {
preloadAccountToEdit,
} from '../../store/accountSearch/reducer/result/accountsReducer';
type AccountEditFormProps = {
fetch: typeof window.fetch;
};
const AccountEditForm: React.FC<AccountEditFormProps> = ({ fetch }) => {
const { accountId } = useParams<{ accountId: string }>();
const dispatch = useDispatch();
useEffect(() => {
dispatch(preloadAccountToEdit({ fetch, accountId }));
}, [accountId]);
return (
<form aria-label="form">
{/* ... */}
</form>
);
};
export default withAuthentication(fetch)(AccountEditForm);
As you can see there is absolutely no logout. I did a bit of retro engineering and it seems that the field post_logout_redirect_uri
was only used on logout. So can I assume I can totally remove it?
About the provider, I assume I can safely remove the store
and UserStore
props but I did some investigation about the notAuthorized
one and find out only one use case.
As you can see, we are using the withAuthentication
HOC which is wrapping the fetch
function to add the tokens in the headers. But it is also redirecting to a route where this NotAuthorized
component will be used when response status is 403. There is also a tentative of silent authentication and retry when response status is 401.
See it here: https://github.com/AxaGuilDEv/react-oidc/blob/v3.1.7/packages/redux-fetch/src/withAuthentication.ts
The problem is these mecanisms are missing in the last version:
https://github.com/AxaGuilDEv/react-oidc/blob/v5.10.1/packages/react/src/oidc/FetchToken.tsx
I tried to reimplement it myself:
// src\hooks\useFetchWithAuthentication.ts
import { useOidcFetch, useOidc } from '@axa-fr/react-oidc';
import { useCallback } from 'react';
import { useNavigate } from 'react-router-dom';
const useFetchWithAuthentication = (prevFetch?: typeof window.fetch) => {
const navigate = useNavigate();
const { login } = useOidc();
const { fetch } = useOidcFetch(prevFetch);
const fetchWithAuthentication = useCallback(
async (url: RequestInfo, options?: RequestInit, isRetry = true) => {
let response = await fetch(url, options);
if (response.status === 403) {
navigate('/not-authorized');
}
if (isRetry) {
if (response.status === 401) {
await login();
response = await fetchWithAuthentication(url, options, false);
}
}
return response;
},
[fetch, navigate, login],
);
return fetchWithAuthentication;
};
export default useFetchWithAuthentication;
But I have only access to a login
function from useOidc
hook and and I don't have access to any functions to silently login unless I use some "hacks" where I get directly the Oidc
singleton from the dist/
files.
How could I solve that?
Thx in advance
Hi @ulrik59 ,
sorry for the delay.
I think you are in the good direction. I have added comment to the code bellow :
// src\hooks\useFetchWithAuthentication.ts
import { useOidcFetch, useOidc } from '@axa-fr/react-oidc';
import { useCallback } from 'react';
import { useNavigate } from 'react-router-dom';
const useFetchWithAuthentication = (prevFetch?: typeof window.fetch) => {
const navigate = useNavigate();
const { login } = useOidc();
const { fetch } = useOidcFetch(prevFetch);
const fetchWithAuthentication = useCallback(
async (url: RequestInfo, options?: RequestInit, isRetry = true) => {
let response = await fetch(url, options);
if (response.status === 403) {
navigate('/not-authorized');
}
// you also do not need retry, the new version assume the token is always up to date
// silent sign is done in background if require
/*if (isRetry) {
if (response.status === 401) {
// await login(); you do not need that
response = await fetchWithAuthentication(url, options, false);
}
}*/
return response;
},
[fetch, navigate],
);
return fetchWithAuthentication;
};
export default useFetchWithAuthentication;
Hi @ulrik59 did you succed your migration?
Hey @guillaume-chervet , yes I did. My PR is in code review for now and we will test it as soon as possible on our staging environment. Removing the silent retry part solved a lot of issues. I will let you know if tests are successful Thanks for the help!
Hi @ulrik59 may you describe your problem with silentsign. It is interresting. I suppose you use Wac an Maam at AXA France.
Hi @ulrik59 , was you tests successfull?
Hi @ulrik59 , do you have some feedback to help other?
I close the issue @ulrik59 , feel free to reopen it if you need.