okta-react-native icon indicating copy to clipboard operation
okta-react-native copied to clipboard

`fetch` polyfill is broken in iOS release builds when `react-query` is installed

Open ryanjwessel opened this issue 2 years ago β€’ 22 comments

Describe the bug?

fetch does not work on iOS when @okta/okta-react-native is installed in a project that also uses react-query.

Having react-query as a dependency without Okta installed does not break fetch.

Once you install @okta/okta-react-native and import createConfig from @okta/okta-react-native, fetch is defined as false while not in debug mode, and all functions calling it fail to execute as a result.

This repository provides a reproducible example.

Running yarn ios from this commit showcases how fetch is improperly overwritten as soon as react-query is added as a dependency.

There are two solutions.

  1. Remove the call to createConfig a. This is obviously not viable if you want to use Okta.
  2. Import the whatwg-fetch polyfill a. This is not ideal either as we're using a polyfill that is not meant for React Native, and could interfere with how other libraries intend to interact with fetch.

I don't think this issue is limited to react-query, as we also noticed app crashes for @sentry/react-native that only surfaced after upgrading Okta.

This was working when we were on Okta React Native version 1.11.1, but once we upgraded beyond 1.13.0 we noticed this problem.

What is expected to happen?

Developers should be able to issue network requests using fetch in React Native.

What is the actual behavior?

As described in the above section. fetch is defined as false while not in debug mode on iOS only.

Reproduction Steps?

Open this project's commit.

Run yarn to install dependencies.

Run yarn ios to open the project on an iOS Simulator.

The Simulator should immediately show the following error:

Render Error
fetch is not a function. (In 'fetch("https://mockapi.io/data")', 'fetch' is false)

Additional Information?

No response

SDK Version

"@okta/okta-react-native": "^2.4.0",
"react-native": "0.64.3",
"react-query": "^3.35.0",
"whatwg-fetch": "^3.6.2"
"react": "17.0.1",
"react-dom": "17.0.1",

Build Information

No response

ryanjwessel avatar Apr 21 '22 21:04 ryanjwessel

Thanks for posting!

@jaynewstrom-okta Can you please help take a look?

arvindkrishnakumar-okta avatar Apr 22 '22 00:04 arvindkrishnakumar-okta

Thanks @arvindkrishnakumar-okta. I can't seem to get this reproducible example working with @okta/[email protected], but that is the last known working version I have seen.

Once I upgraded to 1.13.x, this issue surfaced.

I'm working on getting an example commit that shows this as working at that version. Hope to have that available for you soon.

ryanjwessel avatar Apr 26 '22 14:04 ryanjwessel

I had someone from our JS team take a look, and nothing stood out to them as being obviously wrong. I created a story on our backlog to take a deeper look into this. OKTA-493072

JayNewstrom avatar Apr 26 '22 15:04 JayNewstrom

I found something that is a bit more concerning in this commit.

That example only includes @okta/okta-react-native, react, and react-native as dependencies, and this issue is present. So, it seems like this issue doesn't even require a conflicting dependency on later versions of React Native (0.68).

ryanjwessel avatar Apr 26 '22 16:04 ryanjwessel

@ryanjwessel Can you provide the output of yarn why @okta/okta-auth-js in this repo?

jaredperreault-okta avatar Apr 26 '22 16:04 jaredperreault-okta

Sure thing @jaredperreault-okta , here it is:

oktaFetchTest on ξ‚  fetch-failure-okta-only via πŸ€– v16.13.0 via πŸ’Ž v2.7.5 
⚑️yarn why @okta/okta-auth-js
yarn why v1.22.18
[1/4] πŸ€”  Why do we have the module "@okta/okta-auth-js"...?
[2/4] 🚚  Initialising dependency graph...
[3/4] πŸ”  Finding dependency...
[4/4] 🚑  Calculating file sizes...
=> Found "@okta/[email protected]"
info Reasons this module exists
   - "@okta#okta-react-native" depends on it
   - Hoisted from "@okta#okta-react-native#@okta#okta-auth-js"
info Disk size without dependencies: "8.79MB"
info Disk size with unique dependencies: "24.25MB"
info Disk size with transitive dependencies: "46.82MB"
info Number of shared dependencies: 26
=> Found "@okta/configuration-validation#@okta/[email protected]"
info This module exists because "@okta#okta-react-native#@okta#configuration-validation" depends on it.
info Disk size without dependencies: "8.98MB"
info Disk size with unique dependencies: "27.55MB"
info Disk size with transitive dependencies: "50.13MB"
info Number of shared dependencies: 32
✨  Done in 0.52s.

ryanjwessel avatar Apr 26 '22 16:04 ryanjwessel

Have there been any developments on this Issue? We are still running into this behavior. It is pretty difficult to debug and impacts our other dependencies' functionality.

ryanjwessel avatar May 23 '22 14:05 ryanjwessel

Seeing this as well in my project - any suggestions or solutions being worked on?

This is the only way I can figure to get an accessToken after obtaining a sessionToken from the authn API. I really need this solution to work

salorsino avatar Aug 16 '22 18:08 salorsino

@ryanjwessel @salorsino you can try pass custom httpClient implementation as an option via oktaAuthConfig

Refs:

  • https://github.com/okta/okta-auth-js#httprequestclient
  • https://github.com/okta/okta-react-native/blob/master/index.js#L69

shuowu-okta avatar Aug 17 '22 13:08 shuowu-okta

@shuowu-okta in my project, just having @okta/okta-react-native in my dependencies makes fetch unusable. API calls made before ever using the Okta SDK are failing due to this issue.

salorsino avatar Aug 17 '22 14:08 salorsino

Facing this same issue as well. Simply including the library is causing fetch to not work with android and crashes the app.

brycnguyen avatar Aug 23 '22 23:08 brycnguyen

Screen Shot 2022-08-23 at 4 21 26 PM

I am using @sentry/react-native along with using @okta/okta-react-native

brycnguyen avatar Aug 23 '22 23:08 brycnguyen

We are also seeing this when upgrading to any version greater than 1.10.0. This is blocking our ability to upgrade our version of react native.

jdcataldo avatar Sep 22 '22 21:09 jdcataldo

@ryanjwessel @salorsino you can try pass custom httpClient implementation as an option via oktaAuthConfig

Refs:

  • https://github.com/okta/okta-auth-js#httprequestclient
  • https://github.com/okta/okta-react-native/blob/master/index.js#L69

@shuowu-okta I did try passing in a different http client such as axios.

On Android the app still will not load while including this library with @sentry/react-native. It still crashes with the error undefined is not a function

Sentry React Native also relies on the fetch api, but seems to work fine with okta-react-native on iOS with axios as the http client.

brycnguyen avatar Oct 05 '22 18:10 brycnguyen

I'm currently seeing this as well.

vincecoleman avatar Nov 23 '22 16:11 vincecoleman

any update from the okta team on this? @JayNewstrom

brycnguyen avatar Dec 05 '22 22:12 brycnguyen

I was able to resolve this by using whatwg-fetch and importing it at the top of my app.

// index.ts
import { fetch as fetchPolyfill } from 'whatwg-fetch'
global.fetch = fetchPolyfill

iOS and Android no longer crash on release or debug mode.

brycnguyen avatar Dec 13 '22 21:12 brycnguyen

The solution @brycnguyen mentioned is what we had to use to get this to work.

ryanjwessel avatar Jan 19 '23 14:01 ryanjwessel

Logging for discovery, I believe this also affects users of the main graphql client @apollo/client. I get error: ApolloError: false is not a function in a react native application; tried to implement the call outside apollo with plain fetch which threw the same error and realized fetch itself was broken.

Has anyone bisected to confirm what version this starts happening? There was ostensibly some work done in cross-fetch which okta-auth-js uses to fix this, but when forcing okta-auth-js onto the latest version in overrides and in turn using the latest version of cross-fetch we're still seeing this. https://github.com/lquixada/cross-fetch/pull/39

TiKevin83 avatar Feb 16 '23 14:02 TiKevin83

It looks like something is causing the import of cross-fetch in okta-auth-js to pull the browser-ponyfill instead of react-native-ponyfill, you can see the setting of fetch to false here in the version intended for the browser, line 4 in dist/browser-ponyfill.js

https://www.npmjs.com/package/cross-fetch/v/3.1.5?activeTab=explore

TiKevin83 avatar Feb 16 '23 18:02 TiKevin83

I removed cross-fetch in okta-auth-js and React Native's Fetch works fine in the build with the polyfill removed.

https://github.com/okta/okta-auth-js/compare/master...TiKevin83:okta-auth-js:remove-fetch-polyfill

I've created the above mentioned issue now since it's clearly a bug in the underlying okta-auth-js library.

TiKevin83 avatar Mar 20 '23 21:03 TiKevin83

fixed in #360

TiKevin83 avatar Jun 20 '23 16:06 TiKevin83