Open caralin3 opened 6 months ago
One thing that could be causing this is that you are not setting the webkit boolean to true here: await CookieManager.set('https://' + cookie.domain, cookie); In resetCookies function you are reading those cookies from WebKit WKHTTPCookieStore storage. Also, you should turn sharedCookiesEnabled off for ios when using WebKit.
Thanks @karel-suchomel-ed! That fixed it for the initial Webview load, but when I leave the webview and then return to it, the cookies are not being synced and I am back to the sign in screen.
Any ideas on why re-entering the Webview, the cookies don't work?
<WebView
style={styles.webview}
source={{ uri: url }}
javaScriptEnabled
domStorageEnabled
startInLoadingState={false}
injectedJavaScript={script}
onLoad={synchronizeCookiesiOS}
onMessage={() => {
// nothing
}}
onNavigationStateChange={handleNavigationStateChange}
thirdPartyCookiesEnabled={true}
/>
I think that for your use case you could use something similar that I used for sharing sessions between RN and WebView. In our app we had a PHPSESSID cookie encoded in a JWT token and this worked for me (not 1:1 code):
const Example = () => {
...
const [isReady, setIsReady] = useState(false)
useFocusEffect(
useCallback(() => {
const getCookieHeaderString = async () => {
const token = getUserAccessToken()
if (token) {
const cookie = getCookieFromToken(token)
if (Platform.OS === 'android') {
await CookieManager.clearAll(useWebKit)
}
await CookieManager.set(
url,
{
name: 'PHPSESSID',
value: cookie.sub,
httpOnly: true,
secure: true
},
useWebKit
)
}
setIsReady(true)
}
if (customer) {
getCookieHeaderString()
} else {
setIsReady(true)
}
return () => {
setIsReady(false)
}
}, [customer])
)
if (isReady) {
return null
}
return (
<Webview
...
/>
)
}
The key was to set the cookie before every webview mount. I didn't experience any false positives this way, even tho the documentation warns about this. If you need to persist browser history between WebView mounts, you could write your own logic and handle the URL with state. I was using this hook for managing the history stacks:
export default function useBrowserHistory(homepage: string) {
const [backStack, setBackStack] = useState<string[]>([homepage])
const [forwardStack, setForwardStack] = useState<string[]>([])
const visit = useCallback(
(url: string) => {
if (!backStack.includes(url)) {
setForwardStack([])
setBackStack((prev) => [...prev, url])
}
},
[backStack]
)
const back = useCallback(
(steps: number = 0) => {
let i = steps
const tempBackStack = [...backStack]
const tempForwardStack = [...forwardStack]
while (tempBackStack.length > 1 && i-- > 0) {
tempForwardStack.push(tempBackStack[tempBackStack.length - 1])
tempBackStack.pop()
}
setForwardStack(tempForwardStack)
setBackStack(tempBackStack)
return tempBackStack[tempBackStack.length - 1]
},
[backStack, forwardStack]
)
const forward = useCallback(
(steps: number = 0) => {
let i = steps
const tempBackStack = [...backStack]
const tempForwardStack = [...forwardStack]
while (tempForwardStack.length > 0 && i-- > 0) {
tempBackStack.push(tempForwardStack[tempForwardStack.length - 1])
tempForwardStack.pop()
}
setForwardStack(tempForwardStack)
setBackStack(tempBackStack)
return tempBackStack[tempBackStack.length - 1]
},
[backStack, forwardStack]
)
const resetHistory = useCallback(() => {
setBackStack([])
setForwardStack([])
}, [])
return {
visit,
back,
forward,
backStack,
forwardStack,
resetHistory
}
}
I only reset the cookies for Android, because I had some issues overwriting other cookies there.
You should also store that session cookie in secure storage (MMKV for example), so you can set it before WebView load, because session cookies are wiped. I took inspiration from this: https://stackoverflow.com/questions/62057393/how-to-keep-last-web-session-active-in-react-native-webview but instead of passing the cookie through cookie header in source I set it via the CookieManager.
Bug description:
Web view should be rendering a web page that has a cookie authentication. Instead it is rendering sign in page. This is happening on iOS after I upgraded to react native 0.73+. It was working properly before the upgrade. Android is working fine.
I have both
thirdPartyCookiesEnabled={true}
andsharedCookiesEnabled={true}
enabled. Also inhandleNavigationStateChange
I reset the cookies for iOS:I also tried to sync the cookies manually with this in the
onLoad
and theonNavigationStateChange
of<WebView />
, but it still didn't work.Expected behavior:
Web view should render account page, not sign in page
Environment: