{"action":"closed","issue":{"url":"https://api.github.com/repos/Moya/Moya/issues/1643","repository_url":"https://api.github.com/repos/Moya/Moya","labels_url":"https://api.github.com/repos/Moya/Moya/issues/1643/labels{/name}","comments_url":"https://api.github.com/repos/Moya/Moya/issues/1643/comments","events_url":"https://api.github.com/repos/Moya/Moya/issues/1643/events","html_url":"https://github.com/Moya/Moya/issues/1643","id":315499454,"node_id":"MDU6SXNzdWUzMTU0OTk0NTQ=","number":1643,"title":"OAuth2: Refresh token","user":{"login":"vermotr","id":6630146,"node_id":"MDQ6VXNlcjY2MzAxNDY=","avatar_url":"https://avatars0.githubusercontent.com/u/6630146?v=4","gravatar_id":"","url":"https://api.github.com/users/vermotr","html_url":"https://github.com/vermotr","followers_url":"https://api.github.com/users/vermotr/followers","following_url":"https://api.github.com/users/vermotr/following{/other_user}","gists_url":"https://api.github.com/users/vermotr/gists{/gist_id}","starred_url":"https://api.github.com/users/vermotr/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/vermotr/subscriptions","organizations_url":"https://api.github.com/users/vermotr/orgs","repos_url":"https://api.github.com/users/vermotr/repos","events_url":"https://api.github.com/users/vermotr/events{/privacy}","received_events_url":"https://api.github.com/users/vermotr/received_events","type":"User","site_admin":false},"labels":[{"id":122272862,"node_id":"MDU6TGFiZWwxMjIyNzI4NjI=","url":"https://api.github.com/repos/Moya/Moya/labels/question","name":"question","color":"cc317c","default":true},{"id":618895614,"node_id":"MDU6TGFiZWw2MTg4OTU2MTQ=","url":"https://api.github.com/repos/Moya/Moya/labels/stale","name":"stale","color":"bfdadc","default":false}],"state":"closed","locked":false,"assignee":null,"assignees":[],"milestone":null,"comments":8,"created_at":"2018-04-18T14:16:32Z","updated_at":"2018-06-20T08:55:56Z","closed_at":"2018-06-20T08:55:56Z","author_association":"NONE","body":"Hi everyone, I need your help!\r\n\r\nI use an OAuth2 API and I need to perform the following steps in order for my service to work:\r\n1. Check my `access_token` and if it is expired, do a request to ask a new token with my `refresh_token`\r\n2. Execute my initial request\r\n\r\nI have tried many things and I have already read several times this issue https://github.com/Moya/Moya/issues/748.\r\n\r\nHowever, I do not manage to do my steps.\r\n\r\nBased on the work of @AndrewSB ([NetworkingType.swift ](https://gist.github.com/AndrewSB/4f1f1256a0a35e82ac44cf7d3dba56f0) + [OAuthTokenRequest.swift](https://gist.github.com/AndrewSB/f41d5834afc32b284957535192221f38)) and based on the [artsy/eidolon](https://github.com/artsy/eidolon/blob/master/Kiosk/App/Networking/Networking.swift) repository, I have written this code:\r\n```swift\r\nimport Foundation\r\nimport Moya\r\nimport Result\r\nimport RxSwift\r\n\r\nclass APIProvider<Target>: MoyaProvider<Target> where Target: TargetType {\r\n\t\r\n\tfileprivate let online: Observable<Bool>\r\n\tfileprivate let provider: MoyaProvider<Target>\r\n\t\r\n\tinit(\r\n\t\tendpointClosure: @escaping MoyaProvider<Target>.EndpointClosure = MoyaProvider.defaultEndpointMapping,\r\n\t\trequestClosure: @escaping MoyaProvider<Target>.RequestClosure = MoyaProvider<Target>.defaultRequestMapping,\r\n\t\tstubClosure: @escaping MoyaProvider<Target>.StubClosure = MoyaProvider.neverStub,\r\n\t\tmanager: Manager = MoyaProvider<Target>.defaultAlamofireManager(),\r\n\t\tplugins: [PluginType] = [],\r\n\t\tonline: Observable<Bool> = .just(true)) {\r\n\t\tself.online = online\r\n\t\tself.provider = MoyaProvider(endpointClosure: endpointClosure, requestClosure: requestClosure, stubClosure: stubClosure, manager: manager, plugins: plugins)\r\n\t}\r\n\t\r\n\tfunc request(_ target: Target) -> Observable<Moya.Response> {\r\n\t\tlet actualRequest = provider.rx.request(target)\r\n\t\r\n\t\tprint(\"=> request\")\r\n\t\treturn online\r\n\t\t\t// .ignore(value: false) // Wait until we're online\r\n\t\t\t.take(1)              // Take 1 to make sure we only invoke the API once.\r\n\t\t\t.flatMap { _ in       // Turn the online state into a network request\r\n\t\t\t\treturn actualRequest\r\n\t\t}\r\n\t}\r\n}\r\n\r\nprotocol NetworkingType {\r\n\tassociatedtype T: TargetType\r\n\tvar provider: APIProvider<T> { get }\r\n}\r\n\r\nstruct Networking: NetworkingType {\r\n\ttypealias T = MyAPI\r\n\tvar provider: APIProvider<MyAPI>\r\n\t\r\n}\r\n\r\nstruct AuthenticatedNetworking: NetworkingType {\r\n\ttypealias T = MyAuthenticatedAPI\r\n\tvar provider: APIProvider<MyAuthenticatedAPI>\r\n}\r\n\r\n// \"Public\" interfaces\r\nextension Networking {\r\n\t\r\n\tfunc request(_ token: MyAPI) -> Observable<Moya.Response> {\r\n\t\tprint(\"=> Normal request\")\r\n\t\treturn self.provider.request(token)\r\n\t}\r\n\t\r\n}\r\n\r\nextension AuthenticatedNetworking {\r\n\t\r\n\tfunc request(_ token: MyAuthenticatedAPI) -> Observable<Moya.Response> {\r\n\t\tprint(\"=> Authenticated request\")\r\n\t\treturn self.provider.request(token)\r\n\t}\r\n\t\r\n}\r\n\r\n// Static methods\r\nextension NetworkingType {\r\n\t\r\n\tstatic var plugins: [PluginType] {\r\n\t\treturn [\r\n\t\t\tNetworkLoggerPlugin(verbose: true)\r\n\t\t];\r\n\t}\r\n\t\r\n\tstatic var authenticatedPlugins: [PluginType] {\r\n\t\treturn [\r\n\t\t\tNetworkLoggerPlugin(verbose: true)\r\n\t\t];\r\n\t}\r\n\t\r\n\tstatic func newDefaultNetworking() -> Networking {\r\n\t\treturn Networking(provider: newProvider(plugins))\r\n\t}\r\n\t\r\n\tstatic func newAuthorizedNetworking() -> AuthenticatedNetworking {\r\n\t\treturn AuthenticatedNetworking(provider: newProvider(authenticatedPlugins))\r\n\t}\r\n\t\r\n\t// (Endpoint, NSURLRequest -> Void) -> Void\r\n\tstatic func endpointResolver() -> MoyaProvider<T>.RequestClosure {\r\n\t\treturn { (endpoint, closure) in\r\n\t\t\tdo {\r\n\t\t\t\tvar request = try endpoint.urlRequest()\r\n\t\t\t\trequest.httpShouldHandleCookies = false\r\n\t\t\t\tclosure(.success(request))\r\n\t\t\t} catch let error {\r\n\t\t\t\tclosure(.failure(MoyaError.underlying(error, nil)))\r\n\t\t\t}\r\n\t\t}\r\n\t}\r\n\t\r\n\tstatic func endpointsClosure<T>() -> (T) -> Endpoint where T: TargetType, T: MyAPIType {\r\n\t\treturn { target in\r\n\t\t\tvar endpoint: Endpoint = Endpoint(url: URL(target: target).absoluteString, sampleResponseClosure: {.networkResponse(200, target.sampleData)}, method: target.method, task: target.task, httpHeaderFields: nil)\r\n\t\t\t\r\n\t\t\tswitch target.authorizationType {\r\n\t\t\tcase .bearer:\r\n\t\t\t\tendpoint = endpoint.adding(newHTTPHeaderFields: [\"Authorization\": ApplicationManager.shared.accessToken])\r\n\t\t\tdefault:\r\n\t\t\t\tbreak;\r\n\t\t\t}\r\n\t\t\treturn endpoint\r\n\t\t}\r\n\t}\r\n}\r\n\r\nprivate func newProvider<T>(_ plugins: [PluginType]) -> APIProvider<T> where T: MyAPIType {\r\n\treturn APIProvider(endpointClosure: Networking.endpointsClosure(),\r\n\t\t\t\t\t   requestClosure: Networking.endpointResolver(),\r\n\t\t\t\t\t   plugins: plugins)\r\n}\r\n```\r\n\r\nIn my code, I make a request like this:\r\n```swift\r\nlet provider = Networking.newAuthorizedNetworking().provider\r\nprovider.request(.myRequest()).[…]\r\n```\r\n\r\nIt would seem that I never enter into the `request` function of AuthenticatedNetworking. And it is there that I want to do my token verification.\r\n\r\nThanks,"}}
{"actor":{"display_login":"stale"}}