-
Notifications
You must be signed in to change notification settings - Fork 735
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
Provide a pattern for dynamic reconfiguration of network transport / auth headers #37
Comments
FYI I just have a shared Apollo client instance, and any time the session changes (login/logout/expired, etc), I just re-configure a new Apollo client and replace it. |
For what it's worth, the solution @idris brought up is pretty much what we're doing as well |
How do you handle queries that fail because of invalid/expired tokens? |
I'd prefer this to not be in the network transport as a delegate but rather maybe an authentication delegate on the client. Currently, the network transport is the only customization point (see discussion in #6) and if you'd implement your own transport, you would then have to re-implement authentication. Some cases the authentication mechanism should be able to handle (long-term):
|
@MrAlek: Thanks for writing these cases down! The more I think about this, the more I realize this will take some effort to get right. And we should probably think about this in conjunction with #6. One idea would be to implement something akin to RequestAdapter and RequestRetrier in Alamofire. These are fairly low-level callbacks, but they do offer quite a bit of flexibility. You could then perform the authentication yourself, or plug in something like p2/OAuth. (Or perform exponential backoff on connection failures, etc.) My first thought would be to put these on a public protocol HTTPNetworkTransportDelegate: class {
func networkTransport(_ networkTransport: HTTPNetworkTransport, shouldSend request: URLRequest) -> Bool
func networkTransport(_ networkTransport: HTTPNetworkTransport, willSend request: inout URLRequest)
func networkTransport(_ networkTransport: HTTPNetworkTransport, request: URLRequest, didFailWithError error: Error, retryHandler: (_ shouldRetry: Bool) -> Void)
} I'm not entirely happy with this because Also, as you mentioned, this ties it to one particular network transport. An alternative might be to consider The main issue seems to be that the 'means of authentication' is actually network transport specific. So it is hard to do this in a generic way. A web socket transport for example, wouldn't allow you to perform authentication on a per-request basis, but only for the connection as a whole. There is also some work to be done to still allow network operations to be What do you think? How does this compare to the network stack you're currently using? |
Wow, I didn't know about the Using I think it makes sense to have generic callbacks so you can base your authentication/retry policy based on the queries/operations! |
Could we - until a better solution is found - add another initializer to |
Any update? :) |
@fruitcoder: Hey, sorry, I've been preoccupied with the new store and caching API, which has taken much longer than expected. Once this lands, we're in a better position to redesign the network layer, also thinking about the WebSocket transport and subscriptions. |
Cool, then I'll stick with my fork for now. Nice work on the store and caching! |
Hi, I just bumped in to this. Personally I think that the use of the NetworkTransport protocol gives enough customisation opportunities without making Apollo too opinionated in handling requests. Here is an example of using Alamofire and SessionManager. Once you are in control of the SessionManager you can add your RequestAdapter, RequestRetriers, background sessions etc etc
|
Good work on SQLLite persistence and I'm using 0.6.0 beta. We need network layer customization for updating Auth headers. When do you think it will be available? |
@vishal-p: The network layer is already customizable by providing your own implementation of |
Thanks for the reply @martijnwalraven, tried above code but got crash on |
hi @martijnwalraven Is this enhancement available now with 0.6.0 release ? |
Just saw this thread, has anyone had a chance to work on this? |
Same, this is quite important here :) |
Any update, folks? |
Hi, my solution is based on original HTTPNetworkTransport form Apollo. You only need to add your headers (line 37) based on your local settings, like Authorization header. The client creation is like original |
@sergiog90 so aren't you sharing the same ApolloClient instance for all your requests? |
@matteinn I'm sharing a single instance for all requests and adding dynamically headers for any performed request through the client. |
I'd like to share our use-case why we would really love to see support for this and how we'd like to use it: We're using OAuth2 for authorization, via AppAuth. For each network request sent to the server, the token may need to be refreshed which is an asynchronous operation. So Apollo needs to ask our app for the additional headers which would be an asynchronous operation. For example, Apollo could pass a completion block that our app then has to call once the tokens have been refreshed. We would then pass the additional headers as parameters to the completion block. Right now we're using a modified version of Apollo and need to wrap the Apollo calls so the tokens get refreshed and can be passed to Apollo… not a good solution. |
So I was playing around with an implementation to allow a delegate of |
I came up with a design that doesn't need the |
That would be great! Sorry, have been really busy with GraphQL Summit. |
@martijnwalraven How about going for that middleware pattern Apollo Link uses? That would solve most of this. |
@MrAlek Yes, I think that makes sense. Want to take a stab at a design so we can discuss here? I haven't had any time to think about this since our last conversation. |
@martijnwalraven I don't have much time right now either I'm afraid :/ We've worked around this particular problem right now by not using @DarkDust have you looked at Apollo Link? I think that context-passing middleware concept would work in the iOS client too. |
@MaxDesiatov This is something that I was looking for (and possibly all developers who wanted to extend core networking). This library should be added to docs for people who already use Alamofire. |
Thank you very much @wtrocki, that's great to hear! I've mentioned this library multiple times in related issues of this repository and also Apollo Slack, but it doesn't look there's any interest from the maintainers of Apollo to mention ApolloAlamofire anywhere in the docs. I actually don't mind that and hope that users can still discover it directly. |
@MaxDesiatov Library is amazing and it is been used quite extensively from what I see. Are you open for collaboration on this? As chances to get this functionality to core is fairly limited maybe we could move that to some aggregator where more developers can join and actively maintain it. This will be also great way to discover it (which is why I think now we still have so many PR's to the core trying to resolve it by duplicating functionality). We can put that into apollo-community organization and invite users that are actively using them. WDYT? |
Sure, that's quite reasonable, I wouldn't mind having something like apollo-community and would greatly appreciate if it was somehow linked. Look forward to hearing more details on how this organization would be governed and if there are any additional criteria or requirements. |
@martijnwalraven your thoughts about using ApolloAlamofire? |
Came to this issue via https://www.apollographql.com/docs/ios/initialization#adding-headers. Will that doc ever be updated with the conclusions here? Will this issue actually ever turn into changes in the SDK? |
I think there is wider discussion now in the community about support more advanced use cases for IOS and getting things merged. |
@wtrocki What does that mean with respect to this particular issue? Which specific solution will be chosen? |
ApolloAlamofire mentioned couple times here resolves a lots of issues and IMHO should be listed in documentation as alternative to internal transports. If there is any use case that this lib is not resolving lets ping team or create issue in the repo. EDIT: Library is now available under The way I see it is that core networking will be working for simple use cases but if app needs to work with OAuth, cert pinning, send metrics etc. ApolloAlamofire provides a great alternative, especially that most of the apps will already have Alamofire configured. Couple PR's created for Apollo-ios are targeting the problem that ApolloAlamofire resolves. |
There's plenty of us who don't want yet another dependency, particularly |
Yes. It is just alternative that has features that still did not landed in apollo-ios library. |
I'm wondering if anyone would be interested in using a new potential package similar to ApolloAlamofire without Alamofire as a dependency, which would use |
would be great if it would build in as any auth requires it. Don't want to reply on another "package"... |
Very much still subject to change but a draft on cancel-before-flight and swap-out-info-on-the-request stuff is up as #602 |
Shipped with v0.11.0! |
Hey @designatednerd, from what I understand, this will work only in case of malformed response or netwok error ? |
Yes, that's correct - because the same request is retried, there's no reason to think that if you get errors back from the server, you won't get those same errors sending again. The only exception I can think of is for Automatic Persisted Queries, which will be special cased. Right now #608 is looking like the most promising implementation for that. |
In our case, the missing authentication error (401) is located in |
Dammit, I love that I wrote this code last week and I already forgot what it does 🙃. Wherever the error is created when dealing with a response, it hits the |
It's not clear how to use the API to implement login / logout, as it would require us to reconfigure headers. We’ll need a way to dynamically configure / reconfigure the client instance to provide different auth headers, perhaps other transport options as well.
The text was updated successfully, but these errors were encountered: