Step 8. Enable authentication
This section describes how to use the abstraction layer to authenticate and how to write the required UI elements to handle nodes and callbacks.
To initiate authentication with FRUser
-
Use the
FRUser
class to initiate the authentication tree when the user presses the login button:@IBAction func loginButtonPressed(sender: UIButton) { print("Login button is pressed") FRUser.login {(user: FRUser?, Node, Error) in } }
In this example,
FRUser.login()
initiates an authentication tree flow and returns one of the following values:FRUser
-
If the credentials already exist to authenticate the user session.
Node
-
If the authentication tree requires user input. For example, "Username/Password".
Error
-
If an error occurs during the authentication flow.
The first step in the authentication tree is to collect the username and password. Therefore, the first object returned here is a
Node
object that allows the authentication process to continue. -
Create a helper method to handle node processing.
Since the authentication process is iterative and continues until it returns the
FRUser
object, you need to write a lot of repetitive code. A helper method makes this task easier.The following example helper method expects whatever the node returns:
func handleNode(user: FRUser?, node: Node?, error: Error?) { }
-
You can then pass the returned node (and any subsequent nodes) to this helper method:
FRUser.login {(user: FRUser?, node, error) in self.handleNode(user: user, node: node, error: error) }
When the user presses the login button, the SDK initiates the authentication tree and passes the returned object to the
handleNode()
method. -
The
handleNode()
method needs to do the following:-
Complete the process when the
user
object is returned. -
Handle any callbacks in the node.
-
Handle any errors.
These aspects are covered in the following code:
-
If a
user
object is returned (the user exists), authenticate the user.Note that the main thread must handle any UI changes:
if let _ = user { print("User is authenticated") DispatchQueue.main.async { self.updateStatus() } }
-
If a
node
object is returned, handle the node object:else if let node = node { print("Node object received, handle the node") }
-
If an error is returned, print the error:
else { print ("Something went wrong: \(String(describing: error))") }
-
Your complete
ViewController.swift
file should now resemble the following:// // ViewController.swift // DemoApp // import UIKit import FRAuth class ViewController: UIViewController { @IBOutlet weak var statusLabel: UILabel? @IBOutlet weak var loginButton: UIButton? override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view. FRLog.setLogLevel([.error, .network]) do { try FRAuth.start() print ("SDK initialized successfully") } catch { print (error) } updateStatus() } func updateStatus() { if let _ = FRUser.currentUser { statusLabel?.text = "User is authenticated" } else { statusLabel?.text = "User is not authenticated" } } func handleNode(user: FRUser?, node: Node?, error: Error?) { if let _ = user { print("User is authenticated") DispatchQueue.main.async { self.updateStatus() } } else if let node = node { print("Node object received, handle the node") } else { print ("Something went wrong: \(String(describing: error))") } } @IBAction func loginButtonPressed(sender: UIButton) { print("Login button is pressed") FRUser.login {(user: FRUser?, node, error) in self.handleNode(user: user, node: node, error: error) } } }
-
-
Save changes to the
ViewController.swift
file. -
Run the application, and click the Login button.
The application output shows the node object in the response data that AM returns.
The
handleNode()
function now needs to handle thenameCallback
callback and thepasswordCallback
.