Microsoft login cookies Android vs iOS
Bug description: Share cookies between webview and fetch under iOS is not working properly. Under android I dont have any issues and it is working as expected.
I have a webview to allow users to authenticate to microsoft online and after that use the same cookies to fetch data using axios.
Simplified my application looks like this
const [isMicrosoftLoggedIn, setIsMicrosoftLoggedIn] = useState(false);
if (!isMicrosoftLoggedIn) {
return <LoginWebview setIsMicrosoftLoggedIn={setIsMicrosoftLoggedIn} />;
}
return <MainScreen />;
export default function LoginWebview({setIsMicrosoftLoggedIn}) {
const [display, setDisplay] = useState(false);
async function onLoad(event) {
console.log("WebView onLoad:", event.nativeEvent.url);
if (event.nativeEvent.url.startsWith(myappurl)) {
setIsMicrosoftLoggedIn(true);
setDisplay(false);
} else {
setDisplay(true);
}
}
return (
<Layout style={{ flex: 1 }}>
<LoadingScreen
text={"Checking Login Status..."}
style={{ display: display ? "none" : "block" }}
/>
<View style={{ flex: 1, display: display ? "block" : "none" }}>
<WebView
source={{ uri: myappurl }}
userAgent="Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36 Edg/119.0.2151.97"
sharedCookiesEnabled={true}
thirdPartyCookiesEnabled={true}
onLoad={(event) => {
onLoad(event);
}}
/>
</View>
</Layout>
);
}
In my MainScreen I use axios.get to fetch data.
On android this works. On iOS I get a redirect back to login.microsoftonline.com because of incorrect cookies.
If I remove my app and reinstall on the first time it will work properly. Killing the app and restarting will break it. The webview will have the correct cookies and pass the microsoft login and redirect back to myappurl, but the axios request will not have the correct cookies and will redirect back to login.microsoftonline.com.
I found several other similar issues, but no solution yet. Any idea what could cause this and how to solve?
To Reproduce:
Should be reproducible with code above.
Expected behavior:
iOS and Android working the same.
Screenshots/Videos:
Environment:
- OS: iOS using Expo
- OS version:
- react-native version: 0.72.6
- react-native-webview version: 13.2.2
Comparing CookieManager.getAll() to CookieManager.getAll(true) it turns out that for some reason not all WK cookies are synced to NS. Cant figure out the reason for the cookies not syncing.
As a workaround I have updated my onLoad to sync the missing cookies. Not the nicest solution, but it works.
async function onLoad(event) {
console.log("WebView onLoad:", event.nativeEvent.url);
if (event.nativeEvent.url.startsWith(myappurl)) {
setDisplay(false);
// Fix for ios cookie sync.
if (Platform.OS === "ios") {
let [nsCookies, wkCookies] = await Promise.all([
CookieManager.getAll(),
CookieManager.getAll(true),
]);
let onlyInWK = cookieOnlyInLeft(wkCookies, nsCookies);
for (i = 0; i < onlyInWK.length; i++) {
let element = onlyInWK[i];
await CookieManager.set(
"https://" + element.domain.replace(/^\.+/, ""),
element
);
}
}
setIsMicrosoftLoggedIn(true);
} else {
setDisplay(true);
}
}
Hello 👋, this issue has been opened for more than 2 months with no activity on it. If the issue is still here, please keep in mind that we need community support and help to fix it! Just comment something like still searching for solutions and if you found one, please open a pull request! You have 7 days until this gets closed automatically
Still using the workaround
@rklomp What does your cookieOnlyInLeft function look like?
Are you experiencing the same issue? Bellw is my code. Let me know if this helps :)
import { type Cookie } from '@react-native-cookies/cookies'
export const isSameCookie = (a: Cookie, b: Cookie): boolean =>
a.domain === b.domain &&
a.name === b.name &&
a.value === b.value &&
a.expires === b.expires
// Get items that only occur in the left array,
// using the compareFunction to determine equality.
export const onlyInLeft = <T>(
left: T[],
right: T[],
compareFunction: (a: T, b: T) => boolean
): T[] =>
left.filter(
(leftValue) =>
!right.some((rightValue) => compareFunction(leftValue, rightValue))
)
export function cookieOnlyInLeft(
left: Record<string, Cookie>,
right: Record<string, Cookie>
): Cookie[] {
return onlyInLeft(Object.values(left), Object.values(right), isSameCookie)
}
@rklomp Thanks for sharing. Yes I am facing a similar issue since upgrading to:
react-native version: 0.73.6
react-native-webview version: 13.8.1
Android is working for me, but iOS is not. I am getting redirected to my site's login screen instead of using the cookies to authenticate and render the proper page. Tried your workaround and still didn't work. I think it's not working because I get redirected to the login page so quickly.
Hello 👋, this issue has been opened for more than 2 months with no activity on it. If the issue is still here, please keep in mind that we need community support and help to fix it! Just comment something like still searching for solutions and if you found one, please open a pull request! You have 7 days until this gets closed automatically
Still using this workaround
Hello 👋, this issue has been opened for more than 2 months with no activity on it. If the issue is still here, please keep in mind that we need community support and help to fix it! Just comment something like still searching for solutions and if you found one, please open a pull request! You have 7 days until this gets closed automatically
Still the same...