Firebase UI Email Link открывает приложение и обрабатывается соответствующим методом, но не выполняет вход в систему - PullRequest
0 голосов
/ 08 октября 2019
  • Цель для iOS: 12,2
  • Язык: Swift
  • Версия Firebase SDK: 6.3.0
  • Версия интерфейса Firebase: 8.1.0
  • Firebase Dynamic Links версия: 4.0.5
  • Устройство: iPad Air под управлением iOS 12.4.2

В настоящее время я сталкиваюсь с проблемой использования FirebaseUI на iOS (swift), когда япопытайтесь обработать ссылку электронной почты, она не будет входить в систему.

У меня есть пользователь, использующий поток ссылок электронной почты FirebaseUI, который успешно отправляет электронную почту на свою электронную почту. Когда я открываю ссылку из электронного письма, она открывается по методу

AppDelegate.swift

func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
    print(self.TAG, "GOT TO RESTORATION HANDLER!", userActivity, userActivity.webpageURL)
    guard let webUrl = userActivity.webpageURL else {
        return false
    }
    let handled = DynamicLinks.dynamicLinks().handleUniversalLink(webUrl) { (link, err) in
        print(self.TAG, "HANDLING UNIVERSAL LINK!", link, err)
    self.handlePasswordlessSignIn(with: link?.url)
    }
    return handled
}

Это делается в соответствии с Шагом 6. из https://firebase.google.com/docs/dynamic-links/ios/receive#open-dynamic-links-in-your-app

Затем я пытаюсь обработать вход следующим образом:

if let link = link, let auth = FUIAuth.defaultAuthUI(), let del = delegate {
    let actionCodeSettings = ActionCodeSettings()
        actionCodeSettings.url = URL(string: websiteContinueURL )
    actionCodeSettings.handleCodeInApp = true
    actionCodeSettings.setIOSBundleID(Bundle.main.bundleIdentifier!)
    actionCodeSettings.setAndroidPackageName(bundleIdentifier, installIfNotAvailable: true, minimumVersion: "12")
    let provider = FUIEmailAuth(authAuthUI: auth, signInMethod: EmailLinkAuthSignInMethod, forceSameDevice: true, allowNewEmailAccounts: true, actionCodeSetting: actionCodeSettings)

    auth.providers = [provider, FUIGoogleAuth(), FUIFacebookAuth()]
    print(self.TAG, "TRYING TO SIGN IN EMAIL LINK!!!")

    if auth.handleOpen(link, sourceApplication: Bundle.main.bundleIdentifier!) {
        // if it handled it, which it does, I callback from here
        // but the auth state at this point, or at any other point after this,
        // even after the "signed in" modal, is unchanged
    }
}

, который затем предоставляет модальное всплывающее окно с надписью "Signed In!"но состояние аутентификации пользователя не меняется. Я использую этот метод для обработки URL-адреса, в частности, потому что а) из-за использования FirebaseUI у меня нет доступа к электронной почте пользователя, с которой они регистрируются, пока они не вошли в систему, и б) это метод, который мне сказали использовать черездокументация https://firebase.google.com/docs/auth/ios/firebaseui#email_link_authentication (здесь написано Auth.defaultAuthUI, но должно быть FUIAuth.defaultAuthUI (), у Auth нет свойства / метода defaultAuthUI, так как это компонент FirebaseUI)

я пробовалследующее:

  • В методе приложения, куда отправляется ссылка при открытии приложения, я попытался отправить исходный userActivity.webpageURL. Не работает.
  • До этого я пытался выйти из системы, чтобы до обработки URL-адреса не было ни одного существующего пользователя. Не работает.
  • Попытка перехватить URL-адрес в других методах приложения, который не работает, поскольку он отправляется только этому методу с помощью обработчика восстановления.

This только происходит на iOS, так как я могу завершить один и тот же поток в Android без проблем каждый раз. Я также не смог воспроизвести это в своем собственном проекте, так как для проверки ссылки на электронную почту требуется развертывание приложения в магазине приложений, поскольку у меня была более ранняя проблема, заключающаяся в том, что динамическая ссылка не открывала приложение вообще. Однако, как только эта проблема была решена, эта проблема всплыла.

Примечание. Я перешел и отследил метод входа в код, который МОЖЕТ увидеть, и поле sourceApplication, кажется, не имеет значения, поэтому даже еслиЯ использую идентификатор пакета, метод, в котором он получен, никогда не использует его. Просто чтобы подтвердить:

FUIAuth.m

- (BOOL)handleOpenURL:(NSURL *)URL
    sourceApplication:(NSString *)sourceApplication {
  // Complete IDP-based sign-in flow.
  for (id<FUIAuthProvider> provider in _providers) {
    if ([provider handleOpenURL:URL sourceApplication:sourceApplication]) {
      return YES;
    }
  }
  // The URL was not meant for us.
  return NO;
}

FUIEmailAuth.m (класс, в котором это реализовано, расширяет протокол FUIAuthProvider)

- (BOOL)handleOpenURL:(NSURL *)URL sourceApplication:(nullable NSString *)sourceApplication {
  self.emailLink = URL.absoluteString;

  // Retrieve continueUrl from URL
  NSURLComponents *urlComponents = [NSURLComponents componentsWithString:URL.absoluteString];
  NSString *continueURLString;
  for (NSURLQueryItem *queryItem in urlComponents.queryItems) {
    if ([queryItem.name isEqualToString:@"continueUrl"]) {
      continueURLString = queryItem.value;
    }
  }
  if (!continueURLString) {
    NSLog(@"FUIEmailAuth unable to handle url without continue URL: %@", URL);
    return NO;
  }

  // Retrieve url parameters from continueUrl
  NSMutableDictionary *urlParameterDict= [NSMutableDictionary dictionary];
  NSURLComponents *continueURLComponents = [NSURLComponents componentsWithString:continueURLString];
  for (NSURLQueryItem *queryItem in continueURLComponents.queryItems) {
    urlParameterDict[queryItem.name] = queryItem.value;
  }
  // Retrieve parameters from local storage
  NSMutableDictionary *localParameterDict = [NSMutableDictionary dictionary];
  localParameterDict[kEmailLinkSignInEmailKey] = [GULUserDefaults.standardUserDefaults
                                                  stringForKey:kEmailLinkSignInEmailKey];
  localParameterDict[@"ui_sid"] = [GULUserDefaults.standardUserDefaults stringForKey:@"ui_sid"];

  // Handling flows
  NSString *urlSessionID = urlParameterDict[@"ui_sid"];
  NSString *localSessionID = localParameterDict[@"ui_sid"];
  BOOL sameDevice = urlSessionID && localSessionID && [urlSessionID isEqualToString:localSessionID];

  if (sameDevice) {
    // Same device
    if (urlParameterDict[@"ui_pid"]) {
      // Unverified provider linking
      [self handleUnverifiedProviderLinking:urlParameterDict[@"ui_pid"]
                                      email:localParameterDict[kEmailLinkSignInEmailKey]];
    } else if (urlParameterDict[@"ui_auid"]) {
      // Anonymous upgrade
      [self handleAnonymousUpgrade:urlParameterDict[@"ui_auid"]
                             email:localParameterDict[kEmailLinkSignInEmailKey]];
    } else {
      // Normal email link sign in
      [self handleEmaiLinkSignIn:localParameterDict[kEmailLinkSignInEmailKey]];
    }
  } else {
    // Different device
    if ([urlParameterDict[@"ui_sd"] isEqualToString:@"1"]) {
      // Force same device enabled
      [self handleDifferentDevice];
    } else {
      // Force same device not enabled
      [self handleConfirmEmail];
    }
  }

  return YES;
}

, поэтому я неЯ считаю, что это проблема.

1 Ответ

0 голосов
/ 10 октября 2019

ОБНОВЛЕНИЕ

ВКЛ IOS ответ на попытка выйти из системы, прежде чем представлять начальный поток регистрации / отправки электронной почты из FirebaseUI,так что ссылка, которая получает отправлено на их электронную почту, не содержит поле анонимного UID

(подробнее о том, почему это работает (см. ниже), см. ниже)


Некоторые детали:

Я работаю над отладкой этого безостановочно со вчерашнего дня. Итак, для всех, кто сталкивался с этой очень специфической проблемой, я хотел бы рассказать больше о контексте выше:

  1. Аутентификация действительно работала нормально, если я удалил учетную запись из Firebase, но только на первая попытка входа / выхода.
  2. В общем, я всегда выполняю вход пользователя как анонимного до тех пор, пока он не зарегистрируется (в этом случае я позволяю FirebaseUI либо выполнять автоматическое обновление, либообычный вход в систему).

Проблема заключалась в том, что я сделал предположение из (2), что FirebaseUI правильно обработает ситуацию для всех методов аутентификации. Для аутентификации ссылки электронной почты, когда пользователь первоначально вводит свою электронную почту в поток FirebaseUI, если он в то время является анонимным, он отправляет ссылку электронной почты с полем / параметром, который указывает его идентификатор анонимного пользователя. Если это поле присутствует, когда приложение снова открывается через динамическую ссылку, и эта ссылка, полученная приложением, затем отправляется этому методу:

FUIAuth.defaultAuthUI()!.handleOpen(link, sourceApplication: bundleIdentifier)

, что произойдет, если оно попытается автоматическиобновить анонимного пользователя до учетной записи электронной почты.

Теперь, при первой попытке создания новой учетной записи, это работает нормально. Но для последующих попыток использовать поток пользовательского интерфейса firebase для аутентификации той же электронной почты, он попытается автоматически обновить анонимного пользователя в учетную запись, которая уже существует, или что-то в этом духе (специфика, вероятно, будет определять, действительно ли это проблема FirebaseUI,или если это проблема FirebaseAuth, или она работает так, как задумано и т. д.).

Очевидно, что если вы полагаетесь на данные, привязанные к определенному UID, этот метод не будет работать для вас, так как UIDникогда не сохраняется при авторизации электронной почты, если вы выходите из анонимного пользователя, а затем создаете / входите с учетной записью электронной почты.

Если вам нужно сохранить UID до и после аутентификации или вы не можете выйти из системы безпроблема, и вы ДОЛЖНЫ использовать FirebaseUI, тогда я бы порекомендовал запретить пользователю выходить из системы после аутентификации внутри вашего приложения. Это не очень хорошее решение, поэтому удаление аутентификации электронной почты в качестве поставщика для FirebaseUI на iOS и использование других поставщиков аутентификации может быть лучшим временным решением.

Все вышеперечисленное является временным решением

Команда FirebaseUI уже должна знать о проблеме через https://github.com/firebase/FirebaseUI-iOS/issues/741 (которую я выяснил на самом деле точнопроблема, с которой я столкнулся, но я изначально проигнорировал это, потому что я вообще не думал, что это повторная аутентификация). Надеемся, что в скором времени им удастся еще кое-что исправить. Если бы у меня была идея, как лучше это исправить в их потоке, я бы сам сделал пиар, но так как я не собираюсь, то просто положусь на это и подожду.


Как насчет shouldAutoUpgradeAnonymousUsers = false ?

Получается, после просмотра кода для FirebaseUI / Auth / FUIAuth.m, FirebaseUI / Email / FUIEmailAuth.m и FirebaseUI/Email/FUIEmailEntryViewController.m, установив для этого флага значение false в течение всего этого процесса (регистрация / вход, отправка ссылки, открытая ссылка, обработка ссылки), ничего не изменит. Во всяком случае, это приведет к тому, что весь поток будет всегда не работать. Поскольку пользователь является анонимным при первоначальной отправке ссылки по электронной почте, он по-прежнему будет включать анонимный uid в ссылку, что, в свою очередь, приведет к тому, что метод, обрабатывающий URL, будет запускать метод, который обрабатывает обновление анонимного пользователя (поскольку существует одинчто, по-видимому, «необходимо» обновить).

FUIEmailAuth.m

- (BOOL)handleOpenURL:(NSURL *)URL sourceApplication:(nullable NSString *)sourceApplication {

...

 } else if (urlParameterDict[@"ui_auid"]) {
   [seld handleAnonymousUpgrade:urlParameterDict[@"ui_auid"] email:localParameterDict[kEmailLinkSignInEmailKey]];
 } else {

...

}

Этот метод, который обрабатывает, затем пропускает начальную проверку, потому что мы не обновляем анонимных пользователей, которая затем пытается обработать ситуацию, как если бы пользователь открыл ссылку надругое устройство (неверно, по крайней мере, в этом случае). Что просто не позволяет пользователю войти в систему.

FUIEmailAuth.m

- (void)handleAnonymousUpgrade:(NSString *)anonymousUserID email:(NSString *)email {
  // Check for the presence of an anonymous user and whether automatic upgrade is enabled.
  if (self.authUI.auth.currentUser.isAnonymous &&
      self.authUI.shouldAutoUpgradeAnonymousUsers &&
      [anonymousUserID isEqualToString:self.authUI.auth.currentUser.uid]) {

  ...

  } else {
    [self handleDifferentDevice];
  }
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...