hi guys, I would like to ask if what plugin for access token to refresh you are using. Im just new with moya and some of the stuff are using Rx. Do you guys know a much easier way to do it with provider or plugin?
Hey @vlainvaldez. First of all sorry for the delay in response - things got busy with the newest Moya 14! As for the question, this is a pretty common ask so try to do a search on our issues - I'm sure you will find out a lot of hints!
For instance, this comment lists some issues that might be worth looking into. Hope you find these useful!
Let me know if you had any troubles implementing something like this for your project.
@sunshinejr yes, I solved it by creating my own Plugin by and also having an extension for provider
Awesome. Glad you figured it out @vlainvaldez and thanks for letting me know! 馃帀
Hi @vlainvaldez
I also have this issue,
can you share how you solved it.
thx!!!!
so I have this provider extension
import Moya
import Foundation
extension MoyaProvider {
public convenience init(
handleRefreshToken: Bool,
plugins: [PluginType] = [],
manager: Manager = MoyaProvider<Target>.defaultAlamofireManager() ) {
if handleRefreshToken {
self.init(requestClosure: MoyaProvider.endpointResolver(), manager: manager, plugins: plugins)
} else {
self.init()
}
}
static func endpointResolver() -> MoyaProvider<Target>.RequestClosure {
return { (endpoint, closure) in
//Getting the original request
let request = try! endpoint.urlRequest()
//assume you have saved the existing token somewhere
if (AccessToken.hasValidToked()) {
// Token is valid, so just resume the original request
closure(.success(request))
return
}
let authenticationProvider: MoyaProvider<AuthenticationRequest> = MoyaProvider<AuthenticationRequest>()
guard
let currentSession = LocalSettings.currentSession
else {
return
}
//Do a request to refresh the authtoken based on refreshToken
authenticationProvider.request(.refreshToken(currentSession.refreshToken)) { result in
switch result {
case .success(let response):
do {
let gatewayResponse: GatewayResponseAPIModel<SignInResponseAPIModel> = try JSONDecoder().decode(GatewayResponseAPIModel<SignInResponseAPIModel>.self,
from: response.data)
guard let body = gatewayResponse.body else {
closure(.failure(MoyaError.jsonMapping(response)))
return
}
let userSession = UserSession(accessToken: body.accessToken,
expiresIn: body.expiresIn,
refreshToken: body.refreshToken,
tokenDate: gatewayResponse.date,
tokenType: body.tokenType,
userId: body.userId)
LocalSettings.currentSession = userSession
closure(.success(request))
} catch let error {
closure(.failure(MoyaError.encodableMapping(error)))
}
// closure(.success(request)) // This line will "resume" the actual request, and then you can use AccessTokenPlugin to set the Authentication header
case .failure(let error):
closure(.failure(error)) //something went terrible wrong! Request will not be performed
}
}
}
}
}
and a plugin to include my access token in the header
import Foundation
import Moya
public final class AccessTokenPlugin: PluginType {
// MARK: - Initializer
public init() { }
// MARK: - Stored Properties
private var request: (RequestType, TargetType)?
// MARK: - Instance Methods
public func prepare(_ request: URLRequest, target: TargetType) -> URLRequest {
var request = request
guard
let session = LocalSettings.currentSession
else { return request }
request.addValue("Bearer \(session.accessToken)", forHTTPHeaderField: "Authorization")
return request
}
}
Usage Will be:
var provider: MoyaProvider<OTPRequest> = MoyaProvider<OTPRequest>(
handleRefreshToken: true,
plugins: [
AccessTokenPlugin()
]
)
Sorry for the slow response
thanks for your reply!
I will try to follow your suggestion!!
Most helpful comment
so I have this provider extension
and a plugin to include my access token in the header
Usage Will be:
Sorry for the slow response