JeffN
JeffN

Reputation: 1605

AlamoFire Retry Request after Oauth Fail

Wracking my brain on this. I have an app using OAuth2 where I request a token which has an expiration. I am trying to figure out the best way to check for the expiration and if it is expired, request a new token before I send my new API request. I have an enum of the Router class from AlamoFire that checks for an access token like so:

UserManager.getUser()?.getUserAccessToken()

That method looks like:

    func getUserAccessTokenForRequest() -> String? {
    if isTokenValid() {
        return self.accessToken
    }
    else {
        var localAccessToken : String?
        let request = DataManager.currentRequest as Request?
        DataManager.currentRequest?.cancel()
        DataManager.refreshToken{ (success, value) in
            if success  {
                if let returnedToken : String = value as? String {
                    request?.resume()
                }
            } else {
                if let localError: AnyObject = value {
                }
            }
        }
        return nil;
    }
}

However when I go to resume the initial request, it is nil because it has already completed and received a response that the token was invalid. I am running into the issue of Async tasks completing before I would like them too (because they are async). I am wondering what the best architecture for this would look like. I could check if the token is valid in my data manager before I even make a request. However I don't want to have to do that for every call.

Would overriding the create request method be the best way to go?

Upvotes: 2

Views: 5500

Answers (1)

Soheil Jadidian
Soheil Jadidian

Reputation: 888

UPDATE:

Just found this: Alamofire : How to handle errors globally

ORIGINAL ANSWER:

I did something similar with AFNetworking a while ago, I guess you can implement something like this for Alamofire:

// if token was expired refresh it and retry
private class func refreshTokenAndRetry(operation: AFHTTPRequestOperation, success: (response: AnyObject!) -> Void, failure: (error: NSError!) -> Void) {
Client.refreshToken(
  success: { (credential: AFOAuthCredential!) -> Void in
    if credential != nil {
      println("Refreshed token and retrying operation")
      var request = operation.request.mutableCopy() as! NSMutableURLRequest
      request.addValue(nil, forHTTPHeaderField: "Authorization")
      request.addValue("Bearer \(credential.accessToken)", forHTTPHeaderField: "Authorization")
      let retryOperation = requestOperationManager.HTTPRequestOperationWithRequest(
        request,
        success: { (operation: AFHTTPRequestOperation!, responseObject: AnyObject!) in
          success(response: responseObject)
        },
        failure: { (operation: AFHTTPRequestOperation!, error: NSError!) in
          failure(error: error)
        }
      )
      retryOperation.start()
    }
  },
  failure: { (error) -> Void in
    failure(error: error)
  }
)
}

What you're missing is creating a mutable copy of the original request, then set the token in headers and create a new operation with the new request.

Upvotes: 1

Related Questions