Handling authentication in iOS apps - ios

I am trying to figure out the best UX for handling 'protected' view controllers throughout an iOS app, that require authentication. For example, say certain view controllers require authentication in my app. If a user navigates to that view controller I can have a check in viewWillAppear that checks if a user is authenticated and show the login screen if they are not. But here is the tricky part... What happens if they cancel the login? A whole set of issues can arise. I can pop the view controller they are on, but what if the previous controller they came from also requires authentication. I can potentially end up with a chain of popping view controller and showing a login view... This seems like an awful user experience.
I can think of one solution which is working now but doesn't seem correct:
An unauthenticated user enters a 'protected' view controller
Replace the AppDelegate's window.rootViewController with the login screen
When the user logs in successfully they are brought to the first screen of the app (losing the state of where they were in the app).
I assume that this is a common problem that other devs have faced. I couldn't find any best practices for handling this and figured you guys would be able to recommend some tips?

Add a flag in Login view controller that you are coming to the protected view controller from Login View and set that flag to YES when user clicks cancel button on login screen and use popToRootViewController to pop to root view controller. and in rootViewController's viewWillAppear, set flag to NO.
User doesn't need the other protected view controllers if they select cancel in login.
and as per my observation, user doesn't have a chance to go to multiple protected view controllers at once, because, if user comes to first protected view controller, you are showing him login screen and if he cancels it, you are pop ing the view. So there is no chance for user though. either way, the above method works for you.

Related

SWrevealviewcontroller should be visible on welcome screen after login

I am new to iOS ran into a problem, I have successfully implemented SWRevealViewController side menu and it works if I put the view controller as initial screen but when it comes to showing it after login procedure it does not show up the menu, so after searching the web for quite some time I found out that I need to design a separate story board for login and register and separate for other screens.. so I did it as per that. Still, I have problems in showing up my side menu. My code does not get in
if revealViewController() != nil{ }
It returns NULL so the code does not go ahead.
And this is my second storyboard:
I am using UserDefaults to keep whether the user is logged in or not and storing user profile details in UserDefaults as well to be used within the app for future.
No need to use second storyboard.
You can simply switch between UIViewControllers by implementing a container view controller, if not using segues for specific reasons.
However, what I would suggest is to set your main view controller, revealViewController?, as an initial view controller, and check login status (using your UserDefaults) on viewDidLoad(). If there's no available login info, modally present another view controller for the login process. Then simply dismiss the login view controller if login succeeded.

In iOS, how to dynamically load a view controller using the same tab bar

my situation is:
My app need to display the views normally but when I press and call a view that will display some sensitive information, I need to be logged, so a login view need be displayed. The trick for me is: when I call presentViewController and load the view, the view is called in a modal way that hide the tab bar and I can`t access other views.
Other thing is I`m doing the check on if user is logged in viewDidAppear, is that a bad practice?
tks for any reply.
In such cases, the concept of container view controller is your friend. You have a UIViewController that encapsulates all the business logic, in your case, the login logic. It manages a view that, say, has a form-like structure where the user enters the data. You can add this as a child of the parent view controller (where your tabs exist). After he presses login (or something), you can remove this child view controller and continue where you left off!
No, checking in viewDidAppear for session validation is something that I do all the time, I think you are fine here.
Edit
In response to a comment. Yes, session validation viewDidAppear can cause problems. A careful application design is the key here. I personally store the login information of the user (as a user model) in NSUserDefaults and remove it whenever the user logs out.

Conditionally Produce two different view controllers from single UITabBarItem

I'm writing an iOS application that includes a UITabBarController, where one of the tabs is the user's profile. However, if the user is not signed in, I would like the application to display a different ViewController (Sign in/Sign up) instead.
I currently have the profile tab routing to a navigaion controller which has its RootViewController as ProfileViewController. In ProfileViewController's viewDidLoad, I have a check to see if the user is signed in. If the user is not, It performs a segue to SignInSignUpViewController which eventually loops back to ProfileViewController.
This approach is over-complicated and broken in a couple ways. For example, the navigation controller allows for the user to back into the signup/signin view controller after they've already signed in.
I feel like this is a pretty common idiom in iOS, but I can't find a good solution online. Anyone have any ideas?
Thanks in advance!
You might want to take a look at the UINavigationController method – setViewControllers:animated:. After you've logged in call this and pass your profile ProfileViewController. It will then be at the top of the stack, so the user won't be able to navigate back to the login view controller.

iOS Modal Login Screen presented anywhere in app

What is the best approach to create an iOS app login screen that slides in (by presenting it modally) whenever the user isn't logged in?
A user will be "logged out" in the following circumstances:
he has never logged into the app (i.e. first use)
he has explicitly logged out of the app
he is logged out on the server (e.g. his security token has expired
on the server, and that is communicated to the app)
My app consists of a UINavigationController that is set as the app's RootViewController, and each screen (other than the Login screen), is pushed onto the NavigationController as the user navigates the app. One of the screens a user can navigate to (i.e. that is pushed onto the stack) is the Logout screen (where the user can log out of the app). The Login screen should appear modally when needed, and the logic and presentation should happen from one centralized place. I am using Storyboards.
What I have tried is to subclass UINavigationController (for the RootViewController), and in its viewDidAppear method I check whether the user is logged in (I store a flag in NSUserDefaults). If he is logged in, the app's first screen is (programmatically) pushed onto the stack; if he isn't logged in, the Login screen is (programmatically) presented modally.
This approach has the following two issues:
you cannot set a background image for the subclassed
UINavigationController, so a blank screen appears for a short while
the subclassed UINavigationController's viewDidAppear is not
called when popping to its RootViewController (specifically when
popped from the Logout screen)
Ideally I want one central place to check whether a user is logged in (I was hoping the subclassed UINavigationController's viewDidAppear method would be this spot) to check the user's logged-in state, and present the modal Login screen if needed.
I have looked at Login Screen using Storyboard and Example for login screen modally based on storyboard (and others referenced in these) but none of them address the issue of presenting the modal Login screen from a central point.
First you should note, that as per Apples developer notes, you are not supposed to subclass UINavigationController.
Second, this is fairly opinion based, however I suggest you should use your application delegate class as the pillar point for checking login status, it's a singleton as UINavigationController, effectively is.
I would suggest posting an NSNotification that your AppDelegate can listen for so that the AppDelegate takes responsibility for presenting your modal login view.
Your communication layer can be responsible for posting the notification whenever the user logs out or the server responds saying that the token has expired.
Try presenting the UINavigationController modally from a "Login ViewController":
On app launch, the LoginVC is shown, requiring the credentials. If the login succeeds, push the UINavigationController.
When the login is invalidated (logout, cookie expires, 401 from server, ...), dismiss the UINavigationController and return to the LoginVC.
Note that on returning to the LoginVC all application state is lost, which may or may not be what you want.
Your AppDelegate should retain a reference to the LoginVC, through which you can call the 'dismiss', e.g.
[((YourAppDelegate*)[[UIApplication sharedApplication] delegate]) fallbackToLoginVC]
OK so here is what I ended up doing:
As pointed out by John Woods, don't subclass UINavigationController. Instead, I created a base UIViewController, which in its viewWillAppear checks whether the user is logged in; if not, modally present the Login screen. All View Controllers that need to check the logged-in state inherit from this base View Controller, so it becomes the "central point" for checking the logged-in state (I don't like using the AppDelegate for this kind of logic).
I like Mike Pollard's suggestion of using notifications to notify when the user's token expires (since this may happen well before viewWillAppear is called). Subscribing to this notification can then also be done in the base View Controller.
Hendrik Demmer's solution is probably the most straightforward, but I don't like having a Login screen "lurking" around at the bottom of the view controller stack - or is this just nitpicking?

iOS: managing state between segues

I'm working on an iPad app that has two controllers, a Login Controller and a View Controller. The Login Controller challenges the user for a username/password and once authenticated, there's a modal segue to the View Controller.
I've implemented a timeout wherein after 20 minutes of inactivity, the app segues back to the Login Controller. However, when the user logs back into the app, the state of the View Controller isn't preserved.
Is there a way to pass the View Controller object back to the Login Controller for re-use after logging into the app again? Is there a better way to manage the state?
Two possibilities come to mind...
You can create a model object either as a "singleton" or possibly owned by the application delegate and update it from the view controller and read from it whenever your view controller's view will appear.
The other option would be to have the view controller as the app's root controller and the login controller a modal overlay.
Your comment "Manage the state" is the answer you seek.
If there are changeable things about your view controller you'd like to save, then save them as they change, (either in NSUserDefaults, or CoreData, or some other persistent store) and have them populate when ViewController calls viewDidLoad.
Storing an entire UIViewController at the AppDelegate level just to preserve a handful of values is likely to be very wasteful, and won't help you at all if the app terminates. For this and many other reasons, your best bet is to follow MVC and make your model a persistent store which feeds the view.

Resources