Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Android/iOS app. Torified webview in react-native. #42

Closed
Reckless-Satoshi opened this issue Feb 1, 2022 · 14 comments · Fixed by #247
Closed

Android/iOS app. Torified webview in react-native. #42

Reckless-Satoshi opened this issue Feb 1, 2022 · 14 comments · Fixed by #247
Assignees
Labels
⚡Eligible for Sats ⚡ This issue or pull request rewards bitcoin enhancement 🆙 New feature or request help needed Looking for someone with skills or bright mind
Milestone

Comments

@Reckless-Satoshi
Copy link
Collaborator

Reckless-Satoshi commented Feb 1, 2022

It might be a low hanging fruit to create a tiny react-native webview app wrapping the current webapp. It might also be possible to use react-native-tor https://github.com/Sifir-io/react-native-tor, so the user does not need TOR Browser nor Orbot, but only the .apk.

This could be a good start towards something more versatile and smartphone friendly.

@Reckless-Satoshi Reckless-Satoshi self-assigned this Feb 1, 2022
@Reckless-Satoshi Reckless-Satoshi added this to the v0.2.0 alpha milestone Feb 1, 2022
@Reckless-Satoshi Reckless-Satoshi added the help wanted Extra attention is needed label Feb 1, 2022
@Reckless-Satoshi Reckless-Satoshi removed their assignment Feb 1, 2022
This was referenced Jun 24, 2022
@Reckless-Satoshi
Copy link
Collaborator Author

Reckless-Satoshi commented Jun 27, 2022

Currently under development:
#170

Encountering issues that require help from more experienced developers:

  • Fix react-router of main.js when included in bundled app. The webapp does not seem to work well (router is not working?) when the main.js is loaded from the local bundle. The bottom bar shows correctly, yet the URL routing (e.g. /book, /order, etc) seem to not be recognized. ⚡300,000 Sats⚡
  • Fix react-native-tor crashes the app at start up. It might not be compatible with current version of react-native, or some dependency might be missing. It is not well maintained.
  • Torify requests in Webview. Hint: maybe JS injection of a snippet to perform TORsocks requests. Or some sort of communication using Webview Messages to TORsocks requests in react-native. ⚡1,700,000 Sats⚡ (watch out, there seems to be reasons why this might not work and proposed alternatives in Android/iOS app. Torified webview in react-native. #42 (comment))

Special thanks and compensation (Sats) available to anyone that can help the embedded Android app work well with native tor.

For JS injection and message handling we could learn of what Hampus did for WebLN in Webview apps. https://github.com/hsjoberg/react-native-webln maybe even build a wrapper package "react-native-torified-webview" that can be helpful for other projects and be better maintained.

Other things that must be done for a functional and useful Android App:

  • Implement push notifications.
  • Fix copy buttons (webview does not copy to clipboard when "copy" buttons are pressed)

@Reckless-Satoshi Reckless-Satoshi added enhancement 🆙 New feature or request help needed Looking for someone with skills or bright mind ⚡Eligible for Sats ⚡ This issue or pull request rewards bitcoin and removed help wanted Extra attention is needed labels Jun 27, 2022
@Reckless-Satoshi Reckless-Satoshi moved this to Stuck (need help!) 🍪 in ⚡Developer Rewards Panel ⚡ Jul 19, 2022
@Reckless-Satoshi Reckless-Satoshi linked a pull request Jul 19, 2022 that will close this issue
7 tasks
@Reckless-Satoshi Reckless-Satoshi changed the title Android/Iphone app Android/iOS app. Torified webview in react-native. Jul 19, 2022
@Reckless-Satoshi
Copy link
Collaborator Author

Bumping total rewards on this task x2 (from 1M to 2M Sats)

@KoalaSat
Copy link
Member

KoalaSat commented Sep 6, 2022

Hello @Reckless-Satoshi ,I think I can start with fixing react-router

@Reckless-Satoshi
Copy link
Collaborator Author

Reckless-Satoshi commented Sep 6, 2022

Hello @Reckless-Satoshi ,I think I can start with fixing react-router

Assigned you. This task is pretty hard for a newbie like me. Ongoing work with everything needed to build/develop the Android App is in this branch https://github.com/Reckless-Satoshi/robosats/tree/android-webview-app-ts check /mobile/setup.md for my findings on how to setup a react-native development environment and build the webview app.

Will leave here some hints that @hsjoberg left on the Blixt wallet group to achieve a torified webview:

I don't know how react-native-webview does it, but in general, react-native uses OkHttp to handle web traffic. It's used by for example the Javascript fetch function.

So OkHttp has to be re-configured to run via the SOCKS proxy. Here is some code that I started working on before I ran into other things

 class CustomNetworkModule implements OkHttpClientFactory {
   public OkHttpClient createNewNetworkModuleClient() {
     return new OkHttpClient.Builder()
             .cookieJar(new ReactCookieJarContainer())
             .setProxy$okhttp(new Proxy(null, null))
             .build();
   }
 }

This would be done in MainActivity.java for the application in question, not in a react-native-torified-webview lib

I never got it to work properly but you should be able to set a new client with:

com.facebook.react.modules.network.OkHttpClientProvider.setOkHttpClientFactory();
...or something like that.

I'm not sure the JS injection path you are taking about on GitHub is feasible because of security policies and whatnot that browsers often have. But yes I've had that thought too.

I think the proper fix has to be to take control over the traffic and make sure it's proxied via SOCKS.

OkHttp is used in react-native. But. Actually it's probably not true for the react-native-webview, because it makes use of the Android WebView component

@KoalaSat
Copy link
Member

KoalaSat commented Sep 11, 2022

@Reckless-Satoshi I think the main point on loading the local bundle is based on this line https://github.com/Reckless-Satoshi/robosats/pull/170/files#diff-c92a46984ef937c6501f1fa10feebdf928270c5f2fbd7fe7b24aee34812a9c2cR24, but the URL doesn't seem to exist anymore 😅 Any other suggestion? do you think should I just start from scratch?

@Reckless-Satoshi
Copy link
Collaborator Author

@Reckless-Satoshi I think the main point on loading the local bundle is based on this line https://github.com/Reckless-Satoshi/robosats/pull/170/files#diff-c92a46984ef937c6501f1fa10feebdf928270c5f2fbd7fe7b24aee34812a9c2cR24

I think this URL only was interesting because it was a general solution that would work in both Android and iOS. I managed to access the content on that URL exported as PDF here

@KoalaSat
Copy link
Member

I have been working on this and I would like to share what I have learned so far and expose the actual situation I'm facing. I explored 2 different ways for doing this, each of them with their own issues, so I'll try to expose them here the best I can:

Loading the JS through Tor

I have been trying to make this work, but looks like webview doesn't really likes to deal with directly Tor, there is still the possibility to overwrite the Http2 calls but as far I have seen, there is no clear solution for that.

The JS load is something unrelated to the Tor API requests, so far it's working fine and I found way less problems than expected.

That lead us to 2 posibilities:

Load the JS from clearnet, call back-end through Tor

This was the original approach. It actually works pretty well because I designed the Tor calls on a way it's independent from the JS source location.

PROS

  • Simple implementation on the Android side. It's just a web browser with steroids.
  • Easy to keep updated with the latest features

CONS

  • Android's WebView has certain special situations where it doesn't always works as a web browser, I had a lot of issues specially when the JS uses window.location
  • Related with that, potentially, a release to the Web might cause unexpected issues with the App, so it'll always require his won testing on every release.
  • We are doing calls to clearnet, from the privacy perspective doesn't sound good.
  • I didn't find a way to make it work locally together with the front-end

Build the JS inside the App

Webpack can be configured to deploy the front-end to the /mobile folder so the JS code will stay inside of the App, that will help to create specific conditions on the code to deal better with the special cases on Android.

PROS

  • The same way is happening with Umbrel, Android will have his own controlled versions and releases.
  • Easy to deal with future problems and to run locally
  • All calls and loads can be forced/implemented to use either internal storage or Tor, never clearnet.

CONS

  • Android will have his own controlled versions and releases, which lead us to be careful on the back-end and be retro-compatible and news featres won't appear automatically.
  • The specific configuration and implementations for Android are there as part of the main JS build
  • Working locally has his own issues on WebView

Let's have a talk! I would love to hear different oppinions

@Reckless-Satoshi
Copy link
Collaborator Author

Reckless-Satoshi commented Sep 18, 2022

Thanks a lot for this update and the work you are putting into getting the Android app done!

Build the JS inside the App

CONS

  • Android will have his own controlled versions and releases, which lead us to be careful on the back-end and be retro-compatible and news featres won't appear automatically.

  • The specific configuration and implementations for Android are there as part of the main JS build

  • Working locally has his own issues on WebView

I believe bundling the react.JS app inside the Android app is the way to go.

The fact that backend and Android app will have to be versioned and updated at the same time is already contemplated #241 . We will hardcode the version of the react.JS app, and fetch from /api/info the version of the backend. If there is a mistmatch on major+minor (x.x.0), a Dialog will show with an explanation on how to keep RoboSats android client updated. We can release small patches (-.-.x) that won't trigger the Update dialog (can be done whenever the Backend API is still fully compatible).

What are the issues this approach has with the WebView? I was able to bundle the main.js with the app.apk, it worked except for the react-router (the bottom bar was there, but the UserGenPage did not render. What I did was to place main.js into /mobile/html/Web.bundle/frontend/main.js and in App.tsx set source={{ html: htmlPath }} on <WebView/>

@KoalaSat
Copy link
Member

KoalaSat commented Sep 19, 2022

For the record and answering @Reckless-Satoshi I'll leave here the issues I'm working on:

Cookies not available on local files

react-native-webview/react-native-webview#2643 (comment) It seems to be an issue on react-native-webview. When loading the build using Web.bundle, cookies are not available.

Working on

Using https://github.com/Reckless-Satoshi/robosats/pull/247/files#diff-167fc1803bf1acdbd0d427666ac0f21ada0aecdae06acca7029fc8495c49fa7eR3 we can send and obtain the cookies information from Android's local storage.

MUI Avatar not loading

https://github.com/Reckless-Satoshi/robosats/pull/247/files#diff-d051bd00dd2196f76966e30471e3d9d9644b5026ef8d30e7f0b1bbe6113eebe9R206
while the avatar image loads properly everywhere, when loading it with MUI Avatar doesn't work, so it doesn't triggers and set avatarLoaded to true. It also fails even loading the JS from https://robosats.onion.moe .

Working on

Stop using MUI Avatar and use https://github.com/Reckless-Satoshi/robosats/blob/1771b4d18a4826f5aa36ece7953aeaa7d80138e2/frontend/src/components/Robots/RobotAvatar/index.tsx, which seems to work. We can do a fetch to the avatar URL and set avatarLoaded to true once the request succeeds.

External sources

https://github.com/Reckless-Satoshi/robosats/pull/247/files#diff-a3ab21f543adced6d1570ef4288a66c0f02a7f1d606265b398a5c8bc5ec97f76R83
Some external sources requires dynamic calculations so I have to find a way to obtain this throught Tor

Working on

Didn't tried yet but probably with Tor we can just obtain the Blob.

Fetching internal files

Related with previous issue, as an example the i18n json files, which also requires a specific configuration to deal with the i18n library. Looks like the fetch action does not allow access to urls with files:// protocol

Fetch API cannot load file:///android_asset/my_wasm_file.wasm. URL scheme "file" is not supported.

react-native-webview/react-native-webview#1560

Working on

So far the only case is i18n so I'm considering configuring webpack to bundle the json files only for the android build.

react-native-tor does not implement PUT

😅 https://github.com/Sifir-io/react-native-tor/blob/ed9dc6f1c474c3aa1ae7512f7437343159a46480/android/src/main/java/com/reactnativetor/TorBridgeRequest.kt#L69

Working on

This is complicated, I can only figure out 2 solutions:

  • Check and create a PR for react-native-tor to include PUT actions
  • Change our only PUT request to POST (I don't like this one)

@KoalaSat
Copy link
Member

I also found this Sifir-io/react-native-tor#30 (comment), which is true for my local, I just thought it was related to my connection.

@Reckless-Satoshi
Copy link
Collaborator Author

Reckless-Satoshi commented Sep 19, 2022

Excellent work! This "torification" is certainly proving to be way more challenging than expected (... and the expectation was for it to be very hard).

This is complicated, I can only figure out 2 solutions:

* Check and create a PR for react-native-tor to include PUT actions
* Change our only PUT request to POST (I don't like this one)

Ha! We can simply open an issue in react-native-tor repo and do nothing to fix it for the moment: Android app users won't be able to disable Stealth Invoices, not a big deal. However, we wanted to use more PUT on API v1, it's good to know this is a limitation.

I also found this Sifir-io/react-native-tor#30 (comment), which is true for my local, I just thought it was related to my connection.

Nasty, it reads as if BlueWallet devs gave up on react-native-tor ?

The MUI Avatar component onLoad is basically a plain html tag <img onLoad={}/> it should be very generic so it is weird it is not working. In any case, it seems like no image is going to load and all of them will have to be fetch via TOR request as a blob as you suggested....

As for the cookies issues I see you have some clue leading to possible solutions, awesome! 🚀

@KoalaSat
Copy link
Member

Sifir-io/react-native-tor#51

@Reckless-Satoshi Reckless-Satoshi moved this from Needs help! 🙏 to In Progress 🚧 in ⚡Developer Rewards Panel ⚡ Sep 22, 2022
@Reckless-Satoshi Reckless-Satoshi moved this from In Progress 🚧 to Done 🚀 in ⚡Developer Rewards Panel ⚡ Sep 28, 2022
@Reckless-Satoshi Reckless-Satoshi linked a pull request Sep 28, 2022 that will close this issue
6 tasks
@Reckless-Satoshi
Copy link
Collaborator Author

Closing this issue. Current steps towards Android torified app in #258 and #257

@5eeman
Copy link

5eeman commented Oct 27, 2023

@Reckless-Satoshi I've found solution for Fetching internal files described above. I've had same problem with getting .wasm files.
In short - use XMLHttpRequest instead of fetch.
Full solution described here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
⚡Eligible for Sats ⚡ This issue or pull request rewards bitcoin enhancement 🆙 New feature or request help needed Looking for someone with skills or bright mind
Projects
None yet
3 participants