Automatic user logout when response is unauthenticated in Swift
What's the problem?
Login tokens can become invalid over time through expiration or the User can simply be deleted from the database. In that case, what do we do? Well we should probably log them out of the app if any of these conditions are met. In this article, we'll walk through a simple way to pull that off in Swift using Alamofire's event monitor system.
Detection of invalid authentication state
Given we have an APIClient
class that creates a default Alamofire URL session, we can attach a ClosureEventMonitor
which can react to all requests and responses. This gives a hook which can act when things fail. In our case, Laravel will return a HTTP 401 for an unauthenticated user to a protected endpoint. So we'll listen for a 401 and make sure that request isn't to our logout
url, since that will create an infinite loop, then post a Notification
.
1enum NotificationsName { 2 public static let authenticationFailed = NSNotification.Name("authenticationFailed") 3} 4 5class APIClient { 6 private let session: Session = { 7 let monitor = ClosureEventMonitor() 8 monitor.requestDidCompleteTaskWithError = { 9 request, sessionTask, error in10 guard11 request.response?.statusCode == 401,12 request.request?.url?.path.contains("/logout") == false13 else { return }14 15 NotificationCenter.default.post(name: NotificationsName.authenticationFailed, object: nil)16 }17 18 let session = Session(eventMonitors: [monitor])19 return session20 }()21}
Auto logout handler
Now we can attach a listener to listen for this notification, in any class you'd like.
1class UserManager {2 init() {3 NotificationCenter.default.addObserver(forName: NotificationsName.authenticationFailed, object: nil, queue: nil) { [weak self] _ in4 DispatchQueue.main.async { [weak self] in5 self?.logout(animate: false)6 }7 }8 }9}
Now what should logout
do? Well that is up to you, but it should likely:
- Kick user back to login screen (can be animated or not)
- Clear out any cached data (so a new account login won't see previous user's data)
- Clear out any active auth tokens or move them to another location (in case of multi login app)
Sounds like a lot of things to do ^, good thing is we are using a Notification here, so we can broadcast to many listeners. If you have a data provider that caches data, it can listen to this event and clear it out, so each class can react to this change, instead of having a mega class do it all.