react-native-keycloak
react-native-keycloak copied to clipboard
Keycloack instance not init
Describe the bug Hi team, at some point my instance of keycloak goes back to default (token: undefined, etc...) so I never go into the onTokenExpired function and the token refresh never happens, which forces my users to reconnect while I have a refreshToken which has a lifespan of 3 months which I save via my store. There may be something I'm doing wrong on the lib implementation.
To Reproduce To reproduce the bug unfortunately it's quite random, but it often happens when the user leaves the app in the background, I had to add a hook to force the keycloak init because it didn't work if you kill the app and come back to it
Smartphone on android and iOS "@react-keycloak/native": "^0.6.0",
Additional context my setup keycloak instance
import { RNKeycloak } from '@react-keycloak/native';
import config from '.';
// Setup Keycloak instance as needed
// Pass initialization options as required
const keycloak = new RNKeycloak({
url: config.keycloak.url,
realm: config.keycloak.realm,
clientId: config.keycloak.clientId,
});
export default keycloak;
my setup keycloak provider
<ReactNativeKeycloakProvider
authClient={keycloak}
initOptions={{
redirectUri: `${prefix}Home`,
inAppBrowserOptions: {
ephemeralWebSession: true,
},
}}>
my interceptor
apiRestInstance.interceptors.request.use(config => {
let token = store.getState().user.user.tokens.accessToken;
keycloak.onTokenExpired = async () => {
try {
// if the token expires within 30 seconds
// update token
const refreshed = await keycloak?.updateToken(30);
if (refreshed) {
token = keycloak?.token;
// set new user token in store
store.dispatch(
setKeycloakUser({
accessToken: token,
refreshToken: keycloak?.refreshToken,
}),
);
}
} catch {
// failed to refresh the token
token = undefined;
}
};
if (token) {
config.headers.Authorization = `Bearer ${token}`;
} else {
config.headers.Authorization = '';
}
return config;
});
my hook for init keycloak instance
const useInitKeycloak = () => {
const dispatch = useDispatch();
const { tokens: userTokens } = useSelector(
(state: RootState) => state.user.user,
);
const { keycloak } = useKeycloak();
useEffect(() => {
(async () => {
if (userTokens?.accessToken && keycloak) {
// Init KC to auto log user if possible. Should be automatically handled by Keycloak, but does not seem to work as expected.
keycloak
.init({
token: userTokens.accessToken,
refreshToken: userTokens.refreshToken,
})
// refresh user access once keycloak token is available
.then(() => {
dispatch(
setKeycloakUser({
accessToken: keycloak?.token,
refreshToken: keycloak?.refreshToken,
type: TypeConnection.PERSISTENT_LOG,
}),
);
});
} else if (!userTokens.accessToken) {
dispatch(
setKeycloakUser({
accessToken: '',
refreshToken: '',
type: TypeConnection.LOG_OUT,
}),
);
}
})();
// eslint-disable-next-line react-hooks/exhaustive-deps
}, []);
};
export default useInitKeycloak;