Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Authorization with refresh tokens #42

Closed
viktorgardart opened this issue Jul 25, 2016 · 3 comments
Closed

Authorization with refresh tokens #42

viktorgardart opened this issue Jul 25, 2016 · 3 comments

Comments

@viktorgardart
Copy link

So the API i'm currently working against have tokens that does not last very long (30 mins). I'm also provided with a refreshtoken which I'm using to generate a new Accesstoken.

So when creating a request i want to check if the token has expired. IF the token has expired i want to request a new one and then continue with the previous request.

I have the flow to check if the token have expired or not working. But when requesting a new one i cant figure out how to "pause" the previous one and the continue it after i've received the new token.

Could someone point me into the correct direction here?

@guillermo-carrasco
Copy link

Hi there :)

Would be nice to get some insights on how we could tackle this problem. The refresh token checkings are done in a beforeEach request fashion, we would like to keep it since it keeps the code clean:

self.networking.beforeEach = { request in
  self.setAuthHeaders()
  return request
}

setAuthHeaders is the method that does all the work with the tokens, and what we would like is to sort of "pause" that return request until the headers are set, which will take a bit more time if the token has expired.

@vadymmarkov
Copy link
Owner

@viktorgardart @guillermo-carrasco Hi there! Thanks for reaching out. Seeing that Malibu is promise-based, the solution should come out of promises as well. You could build your own chain of requests, resolve, reject, throw corresponding errors and so on, for example:

struct AuthService {
  // Let's say you have some `authStorage` where you can get the current token from
  // and check if it's expired or not.
  func acquireToken() -> Promise<String> {
    let promise = Promise<String>()

    // Resolve with the current token unless it is expired
    guard authStorage.isExpired else {
      promise.resolve(authStorage.accessToken)
      return promise
    }    

    // Request a new token
    Malibu.networking(name: "auth").GET(TokenRequest())
      .validate()
      .toJSONDictionary()
      .then({ dictionary -> String in
        let accessToken: String
        // 1. Get tokens from dictionary
        // 2. Save tokens
        return accessToken
      })
      .done({ accessToken in
        promise.resolve(accessToken)
      })
      .fail({ error in
        // Handle errors
        promise.reject(error)
      })

    return promise
  }
  // ...
}

AuthService()
  . acquireToken()
  .then({ accessToken -> Ride in
    // Set token headers
    return Malibu.networking(name: "basic").GET(MyRequest())  
  })

On the other hand, it could be a new feature on Malibu Networking:

public var prepare: (Promise<Void> -> Void)?

So you can still use your AuthService, but only in one place to keep the code clean:

networking.prepare = { task in
  AuthService()
  . acquireToken()
  .done({ _ in
    task.resolve() 
  })
  .fail({ error in
    // Handle errors
    task.reject(error)
  })   
}

// Will be executed only when promise from `prepare` closure is resolved
// so you always have your actual valid token here
networking.beforeEach = { request in
  // set auth headers
  return request
}

@viktorgardart
Copy link
Author

@vadymmarkov That prepare solution sounds like a good plan to implement. For now im sticking with your first solution you mentioned.

Thank you so much, and have a great weekend!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants