Перенаправление в мобильное приложение из веб-представления самого приложения в React Native

Я создаю приложение для Android, которое требует аутентификации у внешнего поставщика auth. Так что я использую react-native-oauth пакет для обработки этого.

Определенная redirect_uri - это глубокая ссылка, которая должна идеально открывать мое приложение после успешной проверки подлинности. Но WebView, похоже, не обрабатывает это перенаправление, и я получаю ответ, поскольку 404-страница не найдена.

Это служба, которую я написал для обработки auth:

    const manager = new OAuthManager('<app_name>')

    manager.addProvider({
         'provider': {
                  auth_version: '2.0', 
                  authorize_url:'<auth-url>',
                  access_token_url: '<auth-url>/token',
                  callback_url: 'http://localhost/provider',
         }
    });

    manager.configure({
       provider: {
           client_id: '<id>',
           client_secret: '<secret>',
           redirect_uri: '<redirect-uri>' //DEEP LINK HERE
      }
    });
   module.exports = {
      authManager: () => {
      manager.authorize('<provider>')
                        .then(resp => console.log(resp))
                        .catch(err => console.log(err));    
                    }
   }

Также я определил свой фильтр намерений, как указано в документах Android на как объявить глубокие ссылки для ваших приложений. отлично работает при открытии с помощью Linking.openURL() из компонентов приложения.

Любая помощь в этом очень ценится.

Ответы

Ответ 1

Вы не можете напрямую перенаправить redirect_uri в свое мобильное приложение (потому что большинство провайдеров auth не поддерживают обычную схему OAuth).

Но вы можете создать некоторую веб-страницу, которая будет принимать перенаправление от поставщиков OAuth и откроет ваше приложение (и отправьте все параметры перенаправления, например token).

Например, вы создаете страницу https://example.com/oauth/ и устанавливаете callback_url на https://example.com/oauth/XXXXX_provider, поэтому, когда пользователь будет перенаправлен на страницу https://example.com/oauth/XXXXX_provider&token=xxx, он откроет вам приложение, используя appName://example/oauth/google?token=xxx

Вы можете обрабатывать appName://example/oauth/google?token=xxx с помощью Deeplink (он откроет ваше мобильное приложение, когда оно будет установлено на устройстве)

Пример страницы для обработки перенаправления:

<html><head></head><body>
<p>Please wait while we redirect you to Your APP NAME...</p>
<p><a href="javascript:redirectToApp()">Open appname</a></p>
<script>
  var redirectToApp = function() {
    var scheme = "appnameapp";
    var openURL = "appname" + window.location.pathname + window.location.search + window.location.hash;
    var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent);
    var Android = /Android/.test(navigator.userAgent);
    var newLocation;
    if (iOS) {
      newLocation = scheme + ":" + openURL;
    } else if (Android) {
      newLocation = "intent://" + openURL + "#Intent;scheme=" + scheme + ";package=com.appnameapp;end";
    } else {
      newLocation = scheme + "://" + openURL;
    }
    console.log(newLocation)
    window.location.replace(newLocation);
  }
  window.onload = redirectToApp;
</script>


</body></html>

Ответ 2

WebView по умолчанию не передает данные cookie/сеанса с помощью Safari/Chrome. Поэтому он не идеален для потока входа, поскольку он не использует существующий сеанс входа в Chrome/Safari.

Экспо предоставляет WebBrowser api, который откроет Safari/Chrome вместо webview. Обратите внимание, что он открывает Safari/Chrome внутри приложения, вместо перенаправления браузера с помощью Linking. Таким образом, пользователи всегда имеют кнопку в браузере, чтобы вернуться в ваше приложение.

Вы можете использовать WebBrowser.openAuthSessionAsync(url), чтобы открыть безопасный сеанс, который совместно использует информацию cookie/session с собственным браузером на устройстве.

Экспо также предоставляет еще один api, называемый AuthSession, который упрощает множество шаблонов и обеспечивает простой api.