Я работаю над приложением, которое аутентифицирует пользователей, используя AWS Cognito, используя UserPools. Я прочитал, скомпилировал и попытался понять примеры , предоставленные Amazon на GitHub.
В базовой архитектуре моего приложения используются шаблоны MVVM и Coordinator. Это то, что я чувствую уверенно, и мне бы хотелось, чтобы все было так.
Возможно, у меня есть некоторые пробелы в использовании этого SDK, но есть вещи, которые не работают, и я не знаю почему.
AFAIK SDK предполагает, что пользователь вошел в систему при запуске приложения. Теперь ваша очередь выполнить аутентификацию и подтвердить, вошел ли пользователь в систему или нет. Как я видел в приведенном примере, они делают это в AppDelegate
. Как мне реализовать это с помощью координаторов? Проверьте статус входа в AppDelegate
или AppCoordinator
? . В настоящее время весь код находится внутри AppDelegate
следующим образом:
import UIKit
import ReactiveSwift
import AWSCognitoIdentityProvider
// MARK: Undesranding how AWS Cognito works
// 1. The app assumes it is logged in and then triggers the delegate which triggers authenticatino of the login screens if it's not
// 2. The authentication delegate is triggered with pool.getUser().getDetails()
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow? = UIWindow(frame: UIScreen.main.bounds)
var rememberDeviceCompletionSource: AWSTaskCompletionSource<NSNumber>?
lazy var appCoordinator: AppCoordinator = {
guard let window = self.window else { fatalError() }
let coordinator = AppCoordinator(window: window)
return coordinator
}()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
AWSDDLog.sharedInstance.logLevel = .verbose
let serviceConfiguration = AWSServiceConfiguration(region: cognitoIdentityUserPoolRegion, credentialsProvider: nil)
let poolConfiguration = AWSCognitoIdentityUserPoolConfiguration(clientId: cognitoIdentityUserPoolAppClientId,
clientSecret: cognitoIdentityUserPoolAppClientSecret,
poolId: cognitoIdentityUserPoolId)
AWSCognitoIdentityUserPool.register(with: serviceConfiguration, userPoolConfiguration: poolConfiguration, forKey: AWSCognitoUserPoolsSignInProviderKey)
let pool = AWSCognitoIdentityUserPool(forKey: AWSCognitoUserPoolsSignInProviderKey)
let currentUser = pool.currentUser()
dump(currentUser)
if let currentUser = currentUser {
// I have some doubts here whether is correct or not
if currentUser.isSignedIn {
appCoordinator.presentHomeViewController()
} else {
let user = pool.getUser()
let details = user.getDetails()
appCoordinator.start()
}
}
return true
}
}
// MARK: - AWSCognitoIdentityInteractiveAuthenticationDelegate protocol delegate
extension AppDelegate: AWSCognitoIdentityInteractiveAuthenticationDelegate {
func startPasswordAuthentication() -> AWSCognitoIdentityPasswordAuthentication {
let compositeDisposable = CompositeDisposable()
let logInViewModel = LogInViewModel(compositeDisposable: compositeDisposable)
let logInViewController = LogInViewController(viewModel: logInViewModel, compositeDisposable: compositeDisposable)
return logInViewController
}
}
AppDelegate
правильно показывает мой UIViewController
когда пользователь не вошел в систему. Презентация V C выполняется в AppCoordinator
. Моя проблема возникает сейчас, когда я построил экран входа в систему, и когда я нажимаю кнопку входа в систему, никаких действий не выполняется, и я не знаю почему. Мой LogInViewController
- вот этот,
import Foundation
import UIKit
import ReactiveSwift
import ReactiveCocoa
import AWSCore
import AWSCognito
import AWSCognitoIdentityProvider
class LogInViewController: UIViewController {
var pool: AWSCognitoIdentityUserPool?
var user: AWSCognitoIdentityUser?
var passwordAuthenticationCompletion: AWSTaskCompletionSource<AWSCognitoIdentityPasswordAuthenticationDetails>?
// Define the views and elements to be added to the View Controller
let compositeDisposable: CompositeDisposable
let viewModel: LogInViewModel
init(viewModel: LogInViewModel, compositeDisposable: CompositeDisposable) {
self.viewModel = viewModel
self.compositeDisposable = compositeDisposable
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func loadView() {
// Add AutoLayout constraints for the views
}
override func viewDidLoad() {
super.viewDidLoad()
setUpBindings()
}
func setUpBindings() {
compositeDisposable += logInButton.reactive.controlEvents(.touchUpInside).observe({ [weak self] (_) in
// I can see this printed in the console but no further action is performed
print("Tapped LOG IN button")
guard let self = self else { fatalError() }
guard let email = self.emailTextField.text else { return }
guard let password = self.passwordTextField.text else { return }
let authDetails = AWSCognitoIdentityPasswordAuthenticationDetails(username: email, password: password)
self.passwordAuthenticationCompletion?.set(result: authDetails)
// At this point nothing happens, not even shows an error or a call to the didCompleteStepWithError function
let user = self.pool?.getUser(email)
user?.getDetails()
})
}
func configureAwsIdentity() {
let serviceConfiguration = AWSServiceConfiguration(region: cognitoIdentityUserPoolRegion, credentialsProvider: nil)
let poolConfiguration = AWSCognitoIdentityUserPoolConfiguration(clientId: cognitoIdentityUserPoolAppClientId,
clientSecret: cognitoIdentityUserPoolAppClientSecret,
poolId: cognitoIdentityUserPoolId)
AWSCognitoIdentityUserPool.register(with: serviceConfiguration, userPoolConfiguration: poolConfiguration, forKey: AWSCognitoUserPoolsSignInProviderKey)
// Fetch the user pool client we initialized in above step
self.pool = AWSCognitoIdentityUserPool(forKey: AWSCognitoUserPoolsSignInProviderKey)
self.pool!.delegate = self
self.pool?.currentUser()?.getDetails()
self.pool?.getUser().getDetails()
}
deinit {
compositeDisposable.dispose()
}
}
// MARK: AWS Cognito Identity Interactive Authentication Delegate
extension LogInViewController: AWSCognitoIdentityInteractiveAuthenticationDelegate {
func startPasswordAuthentication() -> AWSCognitoIdentityPasswordAuthentication {
return self
}
}
extension LogInViewController: AWSCognitoIdentityPasswordAuthentication {
public func getDetails(_ authenticationInput: AWSCognitoIdentityPasswordAuthenticationInput, passwordAuthenticationCompletionSource: AWSTaskCompletionSource<AWSCognitoIdentityPasswordAuthenticationDetails>) {
self.passwordAuthenticationCompletion = passwordAuthenticationCompletionSource
DispatchQueue.main.async {
print("> Last known username: \(String(describing: authenticationInput.lastKnownUsername))")
}
}
public func didCompleteStepWithError(_ error: Error?) {
DispatchQueue.main.async {
if let error = error as NSError? {
guard let alertTitleString = error.userInfo["__type"] as? String else { return }
guard let alertBodyString = error.userInfo["message"] as? String else { return }
self.presentAlertViewWithError(title: alertTitleString, body: alertBodyString)
} else {
// Successful authentication, do whatever's needed!
self.viewModel.presentTabBarControllerAfterSuccessfulAuthentication()
}
}
}
}
Я не знаю, почему ничего не происходит после нажатия logInButton
. Мне удалось заставить это работать несколько дней go, но оно внезапно перестало работать, и я не вижу, где это не так.