In my app i have a option to login to the app using google sign in. Login is working fine. Once i click the Logout Button, I am not able to logout from google. When ever I click on login button it's not showing login page as image given below:
Instead its redirecting to authentication dialog page as image given below:
Code :
override func viewDidLoad()
{
super.viewDidLoad()
GIDSignIn.sharedInstance().uiDelegate = self
let button = GIDSignInButton(frame: CGRectMake(0, 0, 100, 100))
button.center = view.center
view.addSubview(button)
}
#IBAction func signOutButton(sender: AnyObject) {
GIDSignIn.sharedInstance().signOut()
}
1.import below
import GoogleAPIClient
import GTMOAuth2
2.declare below variable
let kKeychainItemName = "your app name"
let kClientID = "your app clinet id"
let scopes = [kGTLAuthScopeDrive]
let service = GTLServiceDrive()
3.replace this methods to your existing one
override func viewDidLoad() {
super.viewDidLoad()
if let auth = GTMOAuth2ViewControllerTouch.authForGoogleFromKeychainForName(
kKeychainItemName,
clientID: kClientID,
clientSecret: nil) {
service.authorizer = auth
}
self.tblView.tableFooterView=UIView()
// Do any additional setup after loading the view.
}
override func viewDidAppear(animated: Bool) {
if let authorizer = service.authorizer,
canAuth = authorizer.canAuthorize where canAuth {
fetchFiles()
} else {
presentViewController(
createAuthController(),
animated: true,
completion: nil
)
}
}
func fetchFiles() {
let query = GTLQueryDrive.queryForFilesList()
query.pageSize = 10
query.fields = "nextPageToken, files(id, name)"
service.executeQuery(
query,
delegate: self,
didFinishSelector: #selector(GoogleDriveVC.displayResultWithTicket(_:finishedWithObject:error:))
)
}
// Parse results and display
func displayResultWithTicket(ticket : GTLServiceTicket,
finishedWithObject response : GTLDriveFileList,
error : NSError?) {
if let error = error {
showAlert("Error", message: error.localizedDescription)
return
}
if let files = response.files where !files.isEmpty {
for file in files as! [GTLDriveFile] {
self.arrayOfNames.append(file.name)
self.arrayOfIdentifier.append(file.identifier)
}
}
self.tblView.reloadData()
}
// Creates the auth controller for authorizing access to Drive API
private func createAuthController() -> GTMOAuth2ViewControllerTouch {
let scopeString = scopes.joinWithSeparator(" ")
return GTMOAuth2ViewControllerTouch(
scope: scopeString,
clientID: kClientID,
clientSecret: nil,
keychainItemName: kKeychainItemName,
delegate: self,
finishedSelector: #selector(GoogleDriveVC.viewController(_:finishedWithAuth:error:))
)
}
// Handle completion of the authorization process, and update the Drive API
// with the new credentials.
func viewController(vc : UIViewController,
finishedWithAuth authResult : GTMOAuth2Authentication, error : NSError?) {
if let error = error {
service.authorizer = nil
showAlert("Authentication Error", message: error.localizedDescription)
return
}
service.authorizer = authResult
dismissViewControllerAnimated(true, completion: nil)
}
// Helper for showing an alert
func showAlert(title : String, message: String) {
let alert = UIAlertController(
title: title,
message: message,
preferredStyle: UIAlertControllerStyle.Alert
)
let ok = UIAlertAction(
title: "OK",
style: UIAlertActionStyle.Default,
handler: nil
)
alert.addAction(ok)
presentViewController(alert, animated: true, completion: nil)
}
at last logout using
func logout(){
//logout code
GTMOAuth2ViewControllerTouch.removeAuthFromKeychainForName(kKeychainItemName)
navigationController?.popViewControllerAnimated(true)
}
this is the full implementation
If OP is still looking (doubt it since it's been 3 years) and if anyone is still working on this I think I figured it out.
I'm using Objective C but the methodology is still the same.
I have an app that uses Google Sign In to authenticate. This work as OP has described. For our sign out I have the following:
(IBAction)didTapSignOut:(id)sender
{
GIDSignIn *gidObject = [GIDSignIn sharedInstance];
[gidObject signOut];
[gidObject disconnect];
NSString *logOutUrl = #"https://www.google.com/accounts/Logout";
[[UIApplication sharedApplication] openURL:[NSURL URLWithString: logOutUrl] options:#{} completionHandler:nil];
}
Make sure signOut is before disconnect (i originally had those two reversed and it did not sign the user out).
For our workflow I have it so that the logout url appears. This works because if the user wants to sign in again then they need to authenticate. If the user is signed in already it bypasses the authentication and goes directly into application.
Related
need your support I've been struggling with this for days. I'll appreciate any help
hi
I'm trying to learn IOS Development & No SQL Database
using Firebase
by creating a Chat app using Firebase real time database & swift
my problem is UI is not updated unless i rebuild The App
sum up
-the log out functionality will not work unless i rebuild the App again ( if i sign out i can login but i cant see the Chat Messages unless i rebuild the App)
if i want to login (to see the Chat Messages) this is my Process
A- log out from the APP
B -login to the APP (here i need to be logged in ) i rebuild the App again
so every time i add a message i need to rebuild because so the signin method will get activates
the Login Method
extension FCViewController : FUIAuthDelegate
{
func authUI(_ authUI: FUIAuth, didSignInWith authDataResult: AuthDataResult?, error: Error?)
{
if (error != nil)
{
return
}
login()
}
}
func login(
let authUI = FUIAuth.defaultAuthUI()
let googleAuthProvider = FUIGoogleAuth(authUI: authUI!)
let provider : [FUIAuthProvider] = [googleAuthProvider , FUIEmailAuth()]
authUI?.providers = provider
_authHandle = Auth.auth().addStateDidChangeListener
{
(auth : Auth , user : User?) in
self.messages.removeAll(keepingCapacity: false)
self.messagesTable.reloadData()
if let activeUser = user
{
if (self.user != activeUser)
{
self.user = activeUser
self.signedInStatus(isSignedIn: true)
let name = user!.email?.components(separatedBy: "#")[0]
self.displayName = name!
print("The first call",Auth.auth().currentUser as Any)
}
else
{
// user must Sign in
self.signedInStatus(isSignedIn: false
self.loginSession()
}
}
}
}
the library
import UIKit
import Firebase
import FirebaseEmailAuthUI
import FirebaseAuthUI
import FirebaseGoogleAuthUI
the signout Method
#IBAction func signOut
try Auth.auth().signOut()
the UI
func showAlert(title: String, message: String) {
DispatchQueue.main.async {
let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
let dismissAction = UIAlertAction(title: "Dismiss", style: .destructive, handler: nil)
alert.addAction(dismissAction)
self.present(alert, animated: true, completion: nil)
}
}
When I tap the "signOut" button, the method gets called and gets executed. after the try Auth.auth().signOut() line of code gets executed, the current user is nil
(lldb) po Auth.auth().currentUser
nil
And if i login again
the Message will not Appear unless i rebuild the App
I'm currently working on an application that requires the use of the Google Calendar API in Swift. Unfortunately, the progress of the project is at a standstill as I'm unable to determine how I need to proceed in order to get past the error shown in the title. It appears just after performing the google sign in function. Circumventing the firebase client ID in favor of a different one generated through the Google Developer Console also did not seem to resolve the problem. On multiple occassions in the code, I added scope values as well as the addition of "https://www.googleapis.com/auth/userinfo.profile" to the scope based on another stackoverflow user's solution but none of it has resolved my problem. I do have a Google-Info.plist file who has been properly configured with the reverse ID as well as url scheme, and also attempted to use the client id from that plist file to perform the function, but it still doesn't seem to work. Below I have included code from the two dominant parts of my program that include references to the calendar api or authorization functions. Let me know if there's anything you see that may be incorrectly implemented or if I missed a step in getting this to work. Most of my code is based on the quickstart code provided here: https://developers.google.com/google-apps/calendar/quickstart/ios?ver=swift
with only slight alterations to allow the additional implementation of Firebase.
Note: Sign-In does appear to work and is successfully communicating data to firebase, it simply isn't allowing further progress once calling Google Calendar. In adition to what I provided below, there is also a separate viewcontroller that houses the google sign in button, but I don't believe the issues I'm having reside in that class, hence its exclusion.
APPDELEGATE
import UIKit
import Firebase
import GoogleSignIn
import FirebaseDatabase
import GoogleAPIClientForREST
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, GIDSignInDelegate {
var scopes = [kGTLRAuthScopeCalendarReadonly, "https://www.googleapis.com/auth/userinfo.profile"]
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
GIDSignIn.sharedInstance().clientID = FirebaseApp.app()?.options.clientID
GIDSignIn.sharedInstance().delegate = self
GIDSignIn.sharedInstance().scopes = scopes
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = UINavigationController(rootViewController: ViewController())
window?.makeKeyAndVisible()
return true
}
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
if let err = error {
print("Failed to log into Google: ", err)
return
}
print("Successfully logged into Google", user)
//Allows information to be stored in Firebase Database
let ref = Database.database().reference(fromURL: "https://tesseractscheduler.firebaseio.com/")
guard let idToken = user.authentication.idToken else { return }
guard let accessToken = user.authentication.accessToken else { return }
LoginController().service.authorizer = user.authentication.fetcherAuthorizer()
let credentials = GoogleAuthProvider.credential(withIDToken: idToken, accessToken: accessToken)
Auth.auth().signIn(with: credentials, completion: { (user, error) in
if let err = error {
print("Failed to create a Firebase User with Google account: ", err)
return
}
//successfully authenticated user
guard let uid = user?.uid else { return }
print("Successfully logged into Firebase with Google", uid)
//Creates database entry with users unique identifier, username, and email. "null" provided to prevent errors.
ref.updateChildValues(["UID": uid, "username": user?.displayName ?? "null", "Email": user?.email ?? "null"])
//Pushes to next screen if login has occurred.
if GIDSignIn.sharedInstance().hasAuthInKeychain(){
//GIDSignIn.sharedInstance().clientID = "197204473417-56pqo0dhn8v2nf5v64aj7o64ui414rv7.apps.googleusercontent.com"
self.window?.rootViewController = UINavigationController(rootViewController: LoginController())
}
LoginController().fetchEvents()
})
}
func application(_ application: UIApplication, open url: URL, options:
[UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
GIDSignIn.sharedInstance().handle(url,
sourceApplication: options[
UIApplicationOpenURLOptionsKey.sourceApplication] as! String!, annotation : options[UIApplicationOpenURLOptionsKey.annotation])
return true
}
LOGINCONTROLLER
import UIKit
import GoogleSignIn
import Firebase
import GoogleAPIClientForREST
class LoginController: UIViewController {
let service = GTLRCalendarService()
let output = UITextView()
let appDelegate = (UIApplication.shared.delegate as? AppDelegate)
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.leftBarButtonItem = UIBarButtonItem(title: "Logout", style: .plain, target: self, action: #selector(didTapSignOut))
view.backgroundColor = UIColor(red: 61/255, green: 91/255, blue: 151/255, alpha: 1)
output.frame = view.bounds
output.isEditable = false
output.contentInset = UIEdgeInsets(top: 20, left: 0, bottom: 20, right: 0)
output.autoresizingMask = [.flexibleHeight, .flexibleWidth]
output.isHidden = true
view.addSubview(output);
}
func fetchEvents() {
let query = GTLRCalendarQuery_EventsList.query(withCalendarId: "primary")
query.maxResults = 10
query.timeMin = GTLRDateTime(date: Date())
query.singleEvents = true
query.orderBy = kGTLRCalendarOrderByStartTime
service.executeQuery(
query,
delegate: self,
didFinish: #selector(displayResultWithTicket(ticket:finishedWithObject:error:)))
}
#objc func displayResultWithTicket(
ticket: GTLRServiceTicket,
finishedWithObject response : GTLRCalendar_Events,
error : NSError?) {
if let error = error {
showAlert(title: "Error", message: error.localizedDescription)
return
}
var outputText = ""
if let events = response.items, !events.isEmpty {
for event in events {
let start = event.start!.dateTime ?? event.start!.date!
let startString = DateFormatter.localizedString(
from: start.date,
dateStyle: .short,
timeStyle: .short)
outputText += "\(startString) - \(event.summary!)\n"
}
} else {
outputText = "No upcoming events found."
}
output.text = outputText
}
private func presentViewController(alert: UIAlertController, animated flag: Bool, completion: (() -> Void)?) -> Void {
UIApplication.shared.keyWindow?.rootViewController?.present(alert, animated: flag, completion: completion)
}
//Shows an error alert with a specified output from the log.
func showAlert(title : String, message: String) {
let alert = UIAlertController(
title: title,
message: message,
preferredStyle: UIAlertControllerStyle.alert
)
let ok = UIAlertAction(
title: "OK",
style: UIAlertActionStyle.default,
handler: nil
)
alert.addAction(ok)
presentViewController(alert: alert, animated: true, completion: nil)
}
//Communicated to navigation button to perform logout function.
#objc func didTapSignOut(_ sender: AnyObject) {
GIDSignIn.sharedInstance().signOut()
print("Successfully logged out of Google.")
showAlert(title: "Log Off", message: "Logout Successful!")
appDelegate?.window?.rootViewController = UINavigationController(rootViewController: ViewController())
}
// Do any additional setup after loading the view.
}
Please let me know if there's anything else you would need provided to be able to help identify the issue. I've searched quite extensively and been unable to find a solution for my particular issue. I apologize if it's a silly question: I'm still fairly new to the incorporation of APIs.
I can't say for sure if there is a more effective workaround yet, but for now I have been able to avoid this error by stripping the code of all references to Firebase and ignoring its implementation. Something about the way I was authenticating Google Sign In with Firebase was causing this error to occur. It is no longer an issue after Firebase's removal. El Tomato's question led me to trying this method and so far I have at least been able to progress. If I have time later in the project, I may come back to see if it's possible to implement them both without the error occurring, but for now it's a non-vital feature.
I am trying to find a way to skip provider options screen in FirebaseUI.
I just need phone authentication and there is no need to show user provider options.
Is there a way to take user directly to phone authentication screen?
Here is my code on viewcontroller
override func viewDidLoad() {
super.viewDidLoad()
//createGradientLayer()
checkLoggedIn()
}
func checkLoggedIn() {
Auth.auth().addStateDidChangeListener { auth, user in
if user != nil {
// User is signed in.
} else {
// No user is signed in.
self.login()
}
}
}
func login() {
let authUI = FUIAuth.defaultAuthUI()
authUI?.delegate = self as? FUIAuthDelegate
let providers: [FUIAuthProvider] = [
FUIPhoneAuth(authUI:FUIAuth.defaultAuthUI()!),
]
authUI?.providers = providers
FUIAuth.defaultAuthUI()?.isSignInWithEmailHidden = true
let authViewController = authUI?.authViewController()
self.present(authViewController!, animated: true, completion: nil)
}
func authUI(_ authUI: FUIAuth, didSignInWith user: User?, error: Error?) {
if error != nil {
//Problem signing in
login()
}else {
//User is in! Here is where we code after signing in
}
}
You were almost there. After FUIAuthProvider initialization start Phone Auth flow directly:
FUIPhoneAuth *provider = self.authUI.providers.firstObject;
[provider signInWithPresentingViewController:self];
Here is sample code.
In order to add logo to Welcome screen subclass FUIAuthPickerViewController and implement FUIAuthDelegate delegate method:
func authPickerViewController(forAuthUI authUI: FUIAuth) -> FUIAuthPickerViewController
Here is one more sample for this.
Let's supose that you have a view controller with a button to start the phone validation. This is the code that should be included in the button (obj-c)
- (IBAction)btnPhoneValidation:(id)sender {
FUIAuth *authUI = [FUIAuth defaultAuthUI];
authUI.delegate = self;
//The following array may contain diferente options for validate the user (with Facebook, with google, e-mail...), in this case we only need the phone method
NSArray<id<FUIAuthProvider>> * providers = #[[[FUIPhoneAuth alloc]initWithAuthUI:[FUIAuth defaultAuthUI]]];
authUI.providers = providers;
//You can present the screen asking for the user number with the following method.
FUIPhoneAuth *provider = authUI.providers.firstObject;
[provider signInWithPresentingViewController:self phoneNumber:nil];
//This is the default way to present several options.
// UINavigationController *authViewController = [authUI authViewController];
// [self presentViewController:authViewController animated:YES completion:nil];
}
The same process but with e-mail authentication, replacing the provider type:
NSArray<id<FUIAuthProvider>> * providers = #[[[FUIEmailAuth alloc]init]];
authUI.providers = providers;
FUIEmailAuth *provider = authUI.providers.firstObject;
[provider signInWithPresentingViewController:self email:nil];
According to the FirebaseAuthUI documentation, you cannot customize the flow. (See the section on custom email/password screens)
Just for extra clarification, here's what I tried so far:
I'm checking if Gmail native app is installed via the this code:
let urlPath:String = "googlegmail://q"
let url: NSURL = NSURL(string: urlPath)!
let isInstalled = UIApplication.sharedApplication().canOpenURL(url)
if isInstalled {
print("Installed")
}else{
print("Not installed")
}
Next, I'm just trying to get the username that the user is using to access email (this is where I'm stuck).
I don't want to use private apis, but only publicly available apis.
First of all you need to confirm Delegate of Google Plus i.e GIDSignInDelegate,GIDSignInUIDelegate
after this make delegate self and add Scope
GIDSignIn.sharedInstance().delegate = self
GIDSignIn.sharedInstance().uiDelegate = self
GIDSignIn.sharedInstance().scopes.append("https://www.googleapis.com/auth/contacts")
GIDSignIn.sharedInstance().scopes.append("https://www.googleapis.com/auth/plus.login")
GIDSignIn.sharedInstance().scopes.append("https://www.googleapis.com/auth/plus.stream.read")
GIDSignIn.sharedInstance().scopes.append("https://www.googleapis.com/auth/plus.me")`
//MARK:- get Info of user from google api
func signIn(signIn: GIDSignIn!, didSignInForUser user: GIDGoogleUser!, withError error: NSError!){
if (error == nil){
getGoogleContacts()
}
}`
private func getGoogleContacts(){
guard let currentUserToken = GIDSignIn.sharedInstance().currentUser.authentication.accessToken else{
userAuthenticate()
return
} GNServerAPIProcessor.requestForGetGoogleContactsFromGmail(currentUserToken) { (responseValue, error) in
if error == nil{
if responseValue != nil{`// here is user result with email
}
}
}``
The code below, is what you'll need to get the user's username. Before you do that you'll have to authorize the user with a Gmail login WebView.
fileprivate func fetchMessagesContent(forIdentifier identifier:String) {
let messageQuery = GTLRGmailQuery_UsersMessagesGet.query(withUserId: "me", identifier: identifier)
messageQuery.identifier = identifier
messageQuery.format = "metadata"
messageQuery.metadataHeaders = ["to", "From"]
service.executeQuery(messageQuery,
delegate: self,
didFinish: #selector(displayMessageContent(ticket:finishedWithObject:error:)))
}
#objc private func displayMessageContent(ticket: GTLRServiceTicket,
finishedWithObject labelsResponse: GTLRGmail_Message,
error: NSError?) {
if error != nil {
// TODO: Send fail message.
print("Error from display messages with Custom Filter is \(error?.localizedDescription)")
return
}
//call the API users.messages.get to all ids
let headers = labelsResponse.payload?.headers
//Saving data in Realm
let gmailMessage = GmailMessage()
gmailMessage.sender = ((headers?[0] as AnyObject).value)!
gmailMessage.recipient = (headers?.count)! > 1 ? ((headers?[1] as AnyObject).value)! : ""
gmailMessage.username = labelsResponse.identifier!
}
I'm implementing the login possibility with touchID using Swift.
Following: when the App is started, there is a login screen and a touchID popup - that's working fine. The problem occurs, when the app is loaded from background: I want the touchID popup appear over a login screen if a specific timespan hasn't been exceeded yet - but this time I want the touchID to go to the last shown view before the app entered background. (i.e. if the user wants to cancel the touchID, there is a login screen underneath where he then can authenticate via password, which leads him to the last shown view OR if the touchID authentication succeeded, the login screen should be dismissed and the last shown view presented.)
I really tried everything on my own, and searched for answers - nothing did help me. Here is my code:
override func viewDidLoad() {
super.viewDidLoad()
//notify when foreground or background have been entered -> in that case there are two methods that will be invoked: willEnterForeground and didEnterBackground
let notificationCenter = NSNotificationCenter.defaultCenter()
notificationCenter.addObserver(self, selector: "willEnterForeground", name:UIApplicationWillEnterForegroundNotification, object: nil)
notificationCenter.addObserver(self, selector: "didEnterBackground", name: UIApplicationDidEnterBackgroundNotification, object: nil)
password.secureTextEntry = true
if (username != nil) {
username.text = "bucketFit"
}
username.delegate = self
password.delegate = self
if let alreadyShown : AnyObject? = def.objectForKey("alreadyShown") {
if (alreadyShown == nil){
authenticateWithTouchID()
}
}
}
willEnterForeground:
func willEnterForeground() {
//save locally that the guide already logged in once and the application is just entering foreground
//the variable alreadyShown is used for presenting the touchID, see viewDidAppear method
def.setObject(true, forKey: "alreadyShown")
if let backgroundEntered : AnyObject? = def.objectForKey("backgroundEntered") {
let startTime = backgroundEntered as! NSDate
//number of seconds the app was in the background
let inactivityDuration = NSDate().timeIntervalSinceDate(startTime)
//if the app was longer than 3 minutes inactiv, ask the guide to input his password
if (inactivityDuration > 2) {
showLoginView()
} else {
def.removeObjectForKey("alreadyShown")
showLoginView()
}
}
}
authenticateWithTouchID():
func authenticateWithTouchID() {
let context : LAContext = LAContext()
context.localizedFallbackTitle = ""
var error : NSError?
let myLocalizedReasonString : NSString = "Authentication is required"
//check whether the iphone has the touchID possibility at all
if context.canEvaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, error: &error) {
//if yes then execute the touchID and see whether the finger print matches
context.evaluatePolicy(LAPolicy.DeviceOwnerAuthenticationWithBiometrics, localizedReason: myLocalizedReasonString as String, reply: { (success : Bool, evaluationError : NSError?) -> Void in
//touchID succeded -> go to students list page
if success {
NSOperationQueue.mainQueue().addOperationWithBlock({ () -> Void in
self.performSegueWithIdentifier("studentsList", sender: self)
})
} else {
// Authentification failed
print(evaluationError?.description)
//print out the specific error
switch evaluationError!.code {
case LAError.SystemCancel.rawValue:
print("Authentication cancelled by the system")
case LAError.UserCancel.rawValue:
print("Authentication cancelled by the user")
default:
print("Authentication failed")
}
}
})
}
}
shouldPerformSegueWithIdentifier:
override func shouldPerformSegueWithIdentifier(identifier: String, sender: AnyObject?) -> Bool {
if (false) { //TODO -> username.text!.isEmpty || password.text!.isEmpty
notify("Login failed", message: "Please enter your username and password to proceed")
return false
} else if (false) { //TODO when backend ready! -> !login("bucketFit", password: "test")
notify("Incorrect username or password", message: "Please try again")
return false
//if the login page is loaded after background, dont proceed (then we need to present the last presented view on the stack before the app leaved to background)
} else if let alreadyShown : AnyObject? = def.objectForKey("alreadyShown") {
if (alreadyShown != nil){
//TODO check whether login data is correct
dismissLoginView()
return false
}
}
return true
}
Thank you in advance.
What you could do is create a AuthenticationManager. This manager would be a shared instance which keep track of whether authentication needs to be renewed. You may also want this to contain all of the auth methods.
class AuthenticationManager {
static let sharedInstance = AuthenticationManager()
var needsAuthentication = false
}
In AppDelegate:
func willEnterForeground() {
def.setObject(true, forKey: "alreadyShown")
if let backgroundEntered : AnyObject? = def.objectForKey("backgroundEntered") {
let startTime = backgroundEntered as! NSDate
//number of seconds the app was in the background
let inactivityDuration = NSDate().timeIntervalSinceDate(startTime)
//if the app was longer than 3 minutes inactiv, ask the guide to input his password
if (inactivityDuration > 2) {
AuthenticationManager.sharedInstance.needsAuthentication = true
}
}
}
Then, subclass UIViewController with a view controller named SecureViewController. Override viewDidLoad() in this subclass
override fun viewDidLoad() {
super.viewDidLoad()
if (AuthenticationManager.sharedInstance().needsAuthentication) {
// call authentication methods
}
}
Now, make all your View Controllers that require authentication subclasses of SecureViewController.