codeburst

Bursts of code to power through your day. Web Development articles, tutorials, and news.

Follow publication

Webviews and social authentication with React Native

Finally a workaround!

Luis Felipe Zaguini
codeburst
Published in
5 min readDec 10, 2017

--

TL;DR: The solution is to implement a communication bridge between the Webview and React Native (via postMessage/onMessage), so when the user clicks on Login, it will trigger the native social login and send the result back to the Webview. There are a few things to note in this solution, so please don't be lazy/too anxious and read the article.

Think about the following scenario: you have a web app and you want to "turn that in a mobile app". Your budget is low — or you don't even have one — , so there is no way you can hire an Android/iOS developer to do the job. A friend told you about "React Native, a brand new stuff to build apps that runs on Android and iOS", and yeah, why not?

Then you quickly create a new project, plug in a Webview component and run the freshly created app: hell yeah. It works! Time to authenticate myself. You click on the Facebook login button and…

Nothing happens. It wouldn't be too easy, would it be? Well, there is a little gap between how Webviews work and the way that social authentication does. Basically, when you click on login, the browser instantiates a popup and the Webview doesn't show it.

The solution

In this project I will show you only the Facebook login resolution, but it's basically the same for other types of social authentication. I'll show how to fix the issue on both Android and iOS — they are a little different. Bear with me.

An overview about what are we going to do

Basically we are going to inject a variable in our webview. This variable will be encharged of notifying the web app that we are running natively. Hence, when the user presses the Facebook login button, we'll throw that request to the Native side of the app. The application will handle the user login part and send the login response back to our component.

Neat, right? Enough talk. Let's make our hands dirty!

First you'll have to install the Facebook SDK and link it to the RN project. To do this, type in the project root terminal:

react-native install react-native-fbsdk

That will grab the packages and link the brand new module to your app. Follow all the instructions in the README before keep on reading this article.

After that, it's time to shine. On your Webview component, create a new attribute called onNavigationStateChange and assign it to a function. That will be responsible for looking up to your weview's navigation state — that's crucial.

In that method's first argument, you'll receive an object with the loading property. That indicates if your page is loading. We want to inject our isNative variable when the page finishes loading. To do this:

Nothing too fancy. Now, in your web app, you'll have to insert the code to post a message from your webview to your app, so it knows when to trigger the native login part. It's fairly simple:

It's time to receive that message in the app, so let's register a listener called onMessage:

There is a lot going on here. First: we defined the handleMessage method, and the argument is an object about the message received. We destructured that to get only the nativeEvent property (which is what matters).

If the message matches what we expected, the Facebook login dialog is shown to the user and when the Promise is fullfiled (a.k.a. the user logged in or aborted the request), we post a message back to the webview with all the payload that the web app needs!

Now it's time to get the message back on the web. You'll have to register an event listener as soon as the user arrives on the login page, this way it's guarantee the webview will not miss the event. Insert this snippet on your web app:

Brilliant, isn't it? Be careful: the native response payload object differs a little bit from the web response payload (on the browser, the popup). It's your job to match the differences and provide the right experience after the authentication callback.

It should be good to go on Android.

But, but… It doesn't work on iOS!

I know. We'll get into it. The problem with iOS is that the Webview native component that React Native uses is outdated: UIWebView. It has severe limitations, which impacts directly on our mechanism. So, as a workaround, we'll install a module called react-native-wkwebview:

react-native install react-native-wkwebview-reborn

With this module in hands, it's time to make some changes. First, we'll have to load different components on different platforms. We can do this using the Platform module. Let's do it.

Ok, now we're going somewhere. It's not working yet, but at least we're rendering the correct component depending on the platform. The problem is that this iOS component works different. It has a different API: instead of posting messages to the webview, we'll need to inject JavaScript, which will fire a callback into the web application and do its job.

Now, instead of posting messages as real events, we inject Javascript, which will fire the callback in the web application, as I said earlier. What do I mean with "callback in the web application"?

Look at the top. That's how you got the final payload! The user is now authenticated in both platforms. But there is a problem. Look at the code inside facebookLoginClicked: different from the code at the start of the article. It's because of the different webview components. If you look at the last gist, you'll notice that I'm not using isNative = true anymore, I'm instead explicitly showing to the webview which platform I'm working with.

Now, obviously it will impact in our native code:

You'll have to change a bit how things work when receiving messages. In the Android webview, the postMessage sends the message as a object, and inside the data property is that "facebookLogin" string. On the other hand, the iOS webview doesn't do all of that. It's "cleaner", just the string that you posted in the webview!

A lot of complicated stuff, right? It's ok if you don't get how things work from the start. Be patient and do a little effort to understand it. With that, you're done! Now you can social authenticate inside a webview :)

You can look at the full React Native code here:

And the web application bridge code here:

I hope you liked it! If you have any (ANY) doubts, please contact me or drop a comment bellow— I'll surely help! Thanks for reading ;)

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

--

--

Published in codeburst

Bursts of code to power through your day. Web Development articles, tutorials, and news.

Responses (2)

Write a response