Primary WebView vs OAuth WebView - forem/ForemWebView-android GitHub Wiki

What is WebView?

WebView is the main view which allows us to load web content inside our activity/fragment but it is not as powerful as a browser. With WebViews we can do following tasks:

  • track each URL before and after calls
  • inject JS code
  • override some url and its functionality

Why are we using two WebView's?

Each WebView has a property called UserAgent which helps identity which browser, device, version, os is using the web content. A typical UserAgent can look something like this:

Mozilla/5.0 (Linux; U; Android 2.2.1; en-us; Nexus One Build/FRG83) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1

From this UserAgent we can easily see that the website is getting used in Mobile, Android, Nexus One device, etc.

Now to connect custom android functions to our web codebase we need to set our own custom UserAgent. For example, copyToClipboard function in our code is defined in android but is getting called from web codebase and to make this connection we use custom UserAgent. For our project the value of that custom UserAgent is ForemWebView/<version_name>.

Setting this custom UserAgent helps us control the entire WebView fully with calling functions of android from web and also calling functions of web from android. For this we are using webView or primaryWebView defined in xml code with its respective kotlin code in which you can see we are setting our custom UserAgent i.e. ForemWebView/<version_name>.

Problem: Now because of this custom UserAgent which provides us the control over our android and web code, the OAuth2.0 based authentication urls used by Sign In Google, Signup with Facebook, etc do not working properly. Basically android OS does not allow OAuth2.0 based URLs to be open directly in a WebView with custom UserAgent.

Why?: As mentioned earlier with custom user agent we can easily control android and web code and can also inject JS code anywhere which means that there is huge security vulnerability and during sign-in/sign-up process some critical information can be hacked.

How does Android OS solve this problem?: In such cases where there is custom UserAgent, the android OS will open the OAuth2.0 urls in browser or a separate tab basically out of the scope of our android app control, which in turn means that our app cannot know if the sign-in was successful, with what information sign-in was done, etc. So basically Sign-In with Google/Facebook becomes useless for us.

Solution: The solution that we have done is not recommended by Android but that's the best we can do because of security concerns as well as keeping our app working. Here comes secondaryWebView or oAuthWebView which can be setup using createNewOAuthWebViewInstance function where we can notice that the UserAgent is not tied to Forem web code but instead to the android os. Basically in primaryWebView we track all the URLs and as soon as it hit any OAuthURLs we hide the primaryWebView and load secondaryWebView with the url where authentication process can take place. Once the authentication is finished we again track that URL in secondaryWebView and destroy the secondaryWebView and load the primaryWebView. Now we share cookies between both the webview instances and as a result the user gets signed-in in the primaryWebView too.

Alternative solution (Best Solution) The alternative solution can be to use official approach i.e. to use Google and Facebook SDK's in android app for authentication but that is a bit more resource intensive as it will mean that there will be changes needed in web codebase and android codebase. But we are going we above approach because for our specific case and the way we have solved the problem there are actually not much security concerns and also we never take data of user except there name and email which does not possess any security threats.

Another problem

Although the solution mentioned above is a bit hacky but works really well with Google authentication BUT it fails for Facebook authentication and the only solution to make Facebook authentication work was to use Facebook SDK and therefore as a team we decided to not use Facebook authentication option for now as we already provide a wide range of options to our users. In future if the demand of Facebook authentication is seen then we can definitely revisit this.