DEV Community

Cover image for React Native: Authentication with WebView
Jason Safaiyeh
Jason Safaiyeh

Posted on • Edited on

React Native: Authentication with WebView

A more interactive tutorial: https://getleaf.app/dsps301/reactnativeau-pvopbxhp

You have a web application with all your features built out and now it is time to build your mobile app. You find yourself writing out the same business logic over again and think, "hmm maybe there is a quicker way to initially implement features, to iterate faster?"

Good news, you can! 🎉

Using the power of web views, mobile applications can wrap login flows and authenticate users without having to rewrite the logic.

React Native WebView

Let's get started with a powerful tool called react-native-webview.

Starting with a basic example that loads the login page.

import React, { FunctionComponent } from 'react';
import { WebView } from 'react-native-webview';

const LoginWebView: FunctionComponent = () => (
  <WebView
    source={{ uri: 'https://mywebapp.com/login' }}
  />
);
Enter fullscreen mode Exit fullscreen mode

Now the user can see the login page and go down any of the app's auth flows.

Features supported:
✅ Login
✅ Sign Up
✅ Forgot Password

URL Param Tokens

Some authentication flows will redirect to a URL containing the user's access token as a URL param.

Taking advantage of react-native-webview's prop onNavigationStateChange, we can watch the URL changes and act accordingly.

We will detect when the token is in the URL, then parse it out so it can be used in the mobile app.

import React, { FunctionComponent } from 'react';
import { WebView, WebViewNavigation } from 'react-native-webview';

const onNavigationStateChange = (navigationState: WebViewNavigation) => {
  const url = navigationState.url;

  // parseURLParams is a pseudo function.
  // Make sure to write your own function or install a package
  const params = parseURLParams(url);

  if (params.token) {
    // Save token for native requests & move to the next screen
  }
};

const LoginWebView: FunctionComponent = () => (
  <WebView
    source={{ uri: 'https://mywebapp.com/login' }}
    onNavigationStateChange={onNavigationStateChange}
  />
);
Enter fullscreen mode Exit fullscreen mode

Now the user is authenticated and the token can be used in your app!

Features supported:
✅ URL Param Token-based Auth

Cookies Based Auth

For more complex auth flows, you may need several cookies to authenticate a user.

Taking advantage of react-native-webview's prop onMessage, we can send the document's cookies to the native code.

Every time navigationStateChange is triggered, we will inject a script using injectJavaScript that returns cookie information for onMessage to process.

import React, { createRef, FunctionComponent } from 'react';
import { WebView, WebViewNavigation } from 'react-native-webview';

// Send the cookie information back to the mobile app
const CHECK_COOKIE: string = `
  ReactNativeWebView.postMessage("Cookie: " + document.cookie);
  true;
`;

const onNavigationStateChange = (navigationState: WebViewNavigation) => {
  ...

  // Check cookies every time URL changes
  if (webViewRef.current) {
    webViewRef.current.injectJavaScript(CHECK_COOKIE);
  }
};

const onMessage = (event: NativeSyntheticEvent<WebViewMessage>) => {
  const { data } = event.nativeEvent;

  if (data.includes('Cookie:')) {
    // process the cookies
  }
};

let webViewRef = createRef<WebView>();
const LoginWebView: FunctionComponent = () => (
  <WebView
    ref={webViewRef}
    source={{ uri: 'https://mywebapp.com/login' }}
    onNavigationStateChange={onNavigationStateChange}
    onMessage={onMessage}
  />
);
Enter fullscreen mode Exit fullscreen mode

Now the application has cookies for future requests.

Features Supported:
✅ Cookie Based Auth

iOS Quirk

WKWebView stores session cookies on the device. It will not be returned in the CHECK_COOKIE script we used above.

To get around this we need to use @react-native-community/react-native-cookies to extract the cookies from the device cookie manager.

We need to set the sharedCookiesEnabled prop to true. This tells WebView to save the cookies onto the native cookie manager.

import React, { createRef, FunctionComponent } from 'react';
import { WebView, WebViewNavigation } from 'react-native-webview';
import CookieManager from '@react-native-community/react-native-cookies';

// Send the cookie information back to the mobile app
const CHECK_COOKIE: string = `
  ReactNativeWebView.postMessage("Cookie: " + document.cookie);
  true;
`;

const onNavigationStateChange = (navigationState: WebViewNavigation) => {
  ...

  // Check cookies every time URL changes
  if (webViewRef.current) {
    webViewRef.current.injectJavaScript(CHECK_COOKIE);
  }
};

const onMessage = async (event: NativeSyntheticEvent<WebViewMessage>) => {
  const { data } = event.nativeEvent;

  if (data.includes('Cookie:')) {
    // process the cookies
    const storedCookies = await CookieManager.get(
      'https://mywebapp.com/login', 
      true
    );
};

let webViewRef = createRef<WebView>();
const LoginWebView: FunctionComponent = () => (
  <WebView
    ref={webViewRef}
    source={{ uri: 'https://mywebapp.com/login' }}
    onNavigationStateChange={onNavigationStateChange}
    onMessage={onMessage}
    sharedCookiesEnabled
  />
);
Enter fullscreen mode Exit fullscreen mode

Features:
✅ iOS Support

Conclusion

Web views can be used in very creative ways to build mobile applications; especially, if you want to iterate quick.

Let me know if there are other ways of authenticating through web views or a different type of authentication that you want to be seen done!

Leave a comment if this was helpful or have any questions!

You can find me on Twitter @safaiyeh

or maintaining react-native-webview and @react-native-community/react-native-cookies.

Keep Building!

Top comments (9)

Collapse
 
falay26 profile image
falay26

I am working on a project with react-native-webview and the web site has functions 'Login with Facebook' and 'Login with Google' but they are not working on the webview. (Works on browsers by opening a new tab.) Is this the solution i am looking for to make them work?

Collapse
 
constantintaivan profile image
constantintaivan

I'm also looking for Login with Google working inside the new webview.
It seems Google doesn't allow this anymore: developers.googleblog.com/2016/08/...

Collapse
 
rozdrigo profile image
Rozdrigo

you got answers, i'm having the same problem could you help me?

Collapse
 
kishan_bharda profile image
Kishan Bharda

How I can clear cookies?

Collapse
 
safaiyeh profile image
Jason Safaiyeh

react-native-cookies has clear functions.

Collapse
 
kishan_bharda profile image
Kishan Bharda

I checked that, but it not working in react native 0.60 or later. Any other solution?

Thread Thread
 
safaiyeh profile image
Jason Safaiyeh

Could you make an issue on the repo? I maintain it so any issues would be fixed.

Collapse
 
cuongptit profile image
CuongPTIT

Hi bro, i am a beginner. I see your code but my code don't run. I don't understand how it runs. Do you have an tutorial video? It is easy to understand when i can watch how it runs. Thanks bro.

Collapse
 
yunusunver profile image
Yunus Ünver

Hello, I want to see every request and response returned in webview. How can I access it?