web icon indicating copy to clipboard operation
web copied to clipboard

Web Auth Flow

Open tonypee opened this issue 6 years ago • 5 comments

Hi guys,

Im finding that following the normal react-navigation 'Auth Flow' as per the docs breaks when targetting web - as the url deep linking will bypass that route, and therefore the nested screen is loaded without the auth being inited.

has anyone experienced this - what are you thoughts on how to address this problem?

tonypee avatar Jun 26 '19 18:06 tonypee

so I'm currently getting around this using nested AppContainer's. I'm not sure if this is valid as I'm just getting started, but at the top level of my app I have a normal app container:

import { createSwitchNavigator, createAppContainer } from 'react-navigation'

import { Startup } from './Startup'
import { App } from './App'
import { Auth } from './Auth'

export default createAppContainer(
  createSwitchNavigator(
    {
      Startup,
      Auth,
      App,
    },
    {
      initialRouteName: 'Startup',
    },
  ),
)

then within App I have another:

import React from 'react'
import { Platform } from 'react-native'
import { createBrowserApp } from '@react-navigation/web'
import { createAppContainer, createSwitchNavigator } from 'react-navigation'

import { Screen } from './Screen'
import { Screen2 } from './Screen2'

const createApp = Platform.select({
  web: createBrowserApp,
  default: createAppContainer,
})

const AppContainer = createApp(
  createSwitchNavigator(
    {
      Screen,
      Screen2,
    },
    {
      initialRouteName: 'Screen',
    },
  ),
)

This seems to work well, even if you visit /Screen2 when not authed you'll see my auth screen. Once logged in /Screen2 will be shown as expected.

The only thing I can't seem to figure out is how to make /Screen my index view and work as /. Visiting / shows the correct view, but I don't know how to get back to that view without it ending up as /Screen in the url bar.

chrisdrackett avatar Jul 06 '19 23:07 chrisdrackett

@tonypee got this working using the following code for App:

import React from 'react'
import { Platform } from 'react-native'
import { createBrowserApp } from '@react-navigation/web'
import { createAppContainer, createSwitchNavigator } from 'react-navigation'

import { Screen } from './Screen'
import { Screen2 } from './Screen2'

const createApp = Platform.select({
  web: createBrowserApp,
  default: createAppContainer,
})

const AppContainer = createApp(
  createSwitchNavigator(
    {
      Screen: {
          screen: Screen,
          path: '',
      },
      Screen2,
    },
    {
      initialRouteName: 'Screen',
    },
  ),
)

chrisdrackett avatar Jul 07 '19 00:07 chrisdrackett

So I was able to (almost) get this working without two navigators. The issue I'm running into is that if you open the app with a deep URL that is within App it seems that the Startup will be skipped. I found workarounds for this in a native context: https://stackoverflow.com/questions/54350991/react-navigation-deep-linking-with-authentication

but I don't feel these work in a web context.

For now I'm going to keep my nested navigators, but I'm curious if there is a way to support auth without having to "break the rules" :)

chrisdrackett avatar Sep 08 '19 00:09 chrisdrackett

@chrisdrackett, thank you!

Does some body from react navigation team have recommendations for the 'right' way to accomplish this part of auth flow?

proof666 avatar Oct 01 '19 19:10 proof666

Hello, any news/advice regarding the "Web Auth" flow in web? In my Expo project I'm using a Switch Navigator, however in web, as @tonypee said one can go to the "protected" screens without any type of checks. In my project:

const AppSwitchNavigator = createSwitchNavigator(
  {
    AuthLoading: { screen: AuthLoadingScreen, path: "" },
    Auth: { screen: AuthStack, path: "auth" },
    Main: { screen: MainStack, path: "main" },
    Error: ErrorScreen
  },
  {
    initialRouteName: "AuthLoading"
  }
);

And then, my App Container:

const createApp = Platform.select({
  // web: config => createBrowserApp(config, { history: "hash" }),
  web: config => createBrowserApp(config), 
  default: config => createAppContainer(config)
});

export default createApp(AppSwitchNavigator);

I have tried both ways (with history "hash"). I haven't found a lot of documentation about it. I would like to know how to handle this in the web. Thank you!

anatula avatar Nov 06 '19 14:11 anatula