Alamofire: Additional requests after failing token refresh

Created on 28 Aug 2020  路  3Comments  路  Source: Alamofire/Alamofire

I'm currently working on an app where we use Alamofire for authentication. Right now we are struggling to make our refresh logic work properly by using the AuthenticationInterceptor.

What did you do?

If we are sending an authenticated request (request A) to our backend and we are getting a 401 status code (due to an expired access token), we are sending a token refresh request. If the token refresh gives us a 400 (e.g. due to an invalid refresh token, expired refresh token) we are triggering a logout, which also deletes the tokens.

What did you expect to happen?

We are expecting Alamofire not to retry queued requests if a token refresh previously ended with a 400.

Request A -> 401
Token Refresh -> 400

What happened instead?

After getting a 400 for a token refresh attempt, Alamofire now sends out request A again, which of course leads to a 401. It will also trigger to token refresh requests with invalid (empty) refresh tokens.

Request A -> 401
Token Refresh -> 400
Request A -> 401
Token Refresh -> 400
Token Refresh -> 400

Alamofire Environment

Alamofire version: 5.2.1
Xcode version: 11.6
Swift version: 5.2
Platform(s) running Alamofire: iOS
macOS version running Xcode: 10.15.4 (19E287)

## Demo Project
-

Additional info

According to the documentation for AuthenticationInterceptor there is another way to handle token refreshes by validating the expiration of the access token upfront (implementing requiresRefresh). This way request A won't be sent out in case the token is expired. It will trigger a token refresh first and if this results in a 400, the whole flow will be stopped. However, since our access tokens will expire after a very short amount of time and we are having problems with users that manually change the system time, we are just returning false from requiresRefresh. Furthermore, here is our implementation forisRequestanddidRequest`:

func didRequest(_: URLRequest, with response: HTTPURLResponse, failDueToAuthenticationError _: Error) -> Bool {
  return response.statusCode == 401
}

func isRequest(_ urlRequest: URLRequest, authenticatedWith credential: User) -> Bool {        
  let bearerToken = HTTPHeader.authorization(bearerToken: credential.tokenStore.accessToken).value
  return urlRequest.headers["Authorization"] == bearerToken
}
support

All 3 comments

Any information on this? I am interested in solving this as well.

@cnoon Can you take a look at this?

Sorry to bother again, but do you have any advice for us? Is there anything we can do to clarify the problem better?

Was this page helpful?
0 / 5 - 0 ratings

Related issues

zhouhao27 picture zhouhao27  路  3Comments

borek2 picture borek2  路  3Comments

yamifr07 picture yamifr07  路  3Comments

tib picture tib  路  3Comments

lvandal picture lvandal  路  3Comments