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 in
10 guard
11 request.response?.statusCode == 401,
12 request.request?.url?.path.contains("/logout") == false
13 else { return }
14 
15 NotificationCenter.default.post(name: NotificationsName.authenticationFailed, object: nil)
16 }
17 
18 let session = Session(eventMonitors: [monitor])
19 return session
20 }()
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] _ in
4 DispatchQueue.main.async { [weak self] in
5 self?.logout(animate: false)
6 }
7 }
8 }
9}

Now what should logout do? Well that is up to you, but it should likely:

  1. Kick user back to login screen (can be animated or not)
  2. Clear out any cached data (so a new account login won't see previous user's data)
  3. 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.