firebasereact-nativewebviewfirebase-authenticationstripe-payments

React Native - How to persist a Firebase authenticated user session from react-native app to a (react-native-webview) webview component?


I have a react-native app which uses Firebase (with "@react-native-firebase/auth": "^6.0.1").
In the app there is one Webview (with "react-native-webview": "^7.5.2").
The user logs in, then I have access to its jwt by using:

auth().currentUser.getIdTokenResult()
  .then(jwtToken => {
    console.log('jwtToken: ', jwtToken.token);
  })

Now I need the user to open the Webview and still being connected because the webview points to my firebase hosting page.

<WebView
  source={{
    uri: 'my-firebase-hosting-url',
    headers: {
      Authorization: jwtToken,
    },
  }}
  renderLoading={this.renderLoadingView}
  startInLoadingState={true}
  sharedCookiesEnabled={true}
  thirdPartyCookiesEnabled={true}
  domStorageEnabled={true}
  ref={ref => {
    this.webview = ref;
  }}
/>

On the server side, I have setup express and cookie-session.
The user doesn't seems to be logged in the webview: on the server side, when I console.log(req.session) it shows an empty object {}.

I've tried multiple options but nothing seems to work in iOS (not tried on Android yet)
What am I missing? Are there extra steps on the frontend/backend? (I am still new to programming)
Thank you for your help.


Solution

  • I finally solved it and hope it will help others:

    1. Design your state

      state = {
          shouldRenderWebview: false,
          authorization: ''
      ...
      
    2. In your constructor, get a refreshed token from firebase

      auth()
            .currentUser.getIdTokenResult()
            .then(result => {
              this.setState({
                authorization: result.token,
                shouldRenderWebview: true,
              });
            })
      
    3. Design your main component to either show a loading view (while it's getting the token) or render the webview

    4. Your webview (and add 'Bearer' to the code)

      const Authorization = 'Bearer ' + this.state.authorization;
      <WebView
         source={{
           uri: this.state.urlToGo,
           headers: {
             Authorization,
           },
         }}
         ....
      
    5. In your backend, check if the authentication code is valid

      firebase.auth().verifyIdToken(req.headers.authorization.substr(7));
      

    Then do your stuff depending on the result.