Skip to content
This repository has been archived by the owner on Apr 14, 2023. It is now read-only.

Adding credentials to the HttpLink and/or ApolloFetch API #44

Closed
tgriesser opened this issue Aug 23, 2017 · 19 comments
Closed

Adding credentials to the HttpLink and/or ApolloFetch API #44

tgriesser opened this issue Aug 23, 2017 · 19 comments
Assignees

Comments

@tgriesser
Copy link

I was going to open a PR to add credentials as an option to the HttpLink and/or ApolloFetch api, but wanted to open a ticket to discuss first.

Currently it appears the only way to add credentials in HttpLink is through a custom ApolloFetch provided by the fetch option, either with a middleware or a custom constructOptions.

That works fine, though it feels like the wrong place to need to add this. Since credentials are part of the top-level api for the global fetch, it seems it should be made a bit more first-class and be provided as an option to either HttpLink, ApolloFetch, or both particularly since it's usually tied to the uri, and not specific to the request.

new HttpLink({uri: 'https://www.example.com/graphql', credentials: 'include'})

or

new HttpLink({
   fetch: createApolloFetch({
      uri: 'https://www.example.com/graphql', 
      credentials: 'include'
   })
})

Also, wanted to get any thoughts on adding headers as another new top-level option on either of these classes, for specifying default headers that should remain consistent across any requests - merged with a the standard headers provided by ApolloFetch unless they're later modified by a middleware.

new HttpLink({
  uri: 'https://www.example.com/graphql', 
  credentials: 'include', 
  headers: {
    'X-Example-Header': config.VERSION
  }
})

or

new HttpLink({
  fetch: createApolloFetch({
    uri: 'https://www.example.com/graphql', 
    credentials: 'include',
    headers: {
      'X-Example-Header': config.VERSION
    }
  })
})
@stubailo
Copy link
Contributor

Hmm, this is definitely one thing that was easier in the previous network interface implementation. I think it should probably be possible to do everything with just HttpLink IMO, but curious what @jbaxleyiii thinks.

@stubailo
Copy link
Contributor

Also, @jaydenseric what do you think?

@stubailo
Copy link
Contributor

Just asked James, we like the first example:

new HttpLink({
  uri: 'https://www.example.com/graphql', 
  credentials: 'include', 
  headers: {
    'X-Example-Header': config.VERSION
  }
})

I think that would include modifications to apollo fetch as well, right?

@tgriesser
Copy link
Author

Cool

I think that would include modifications to apollo fetch as well, right?

Correct, they'd pass through from HttpLink/BatchHttpLink to apollo fetch and presumably be merged into the options object here.

@stubailo
Copy link
Contributor

@tgriesser that would be awesome - do you have time to work on a PR for that?

@tgriesser
Copy link
Author

Yep, I'll get something over in a bit

@stubailo
Copy link
Contributor

Thanks!

@jaydenseric
Copy link

Also, @jaydenseric what do you think?

I don't fully appreciate the consequences of this proposal as the way all these new packages link together still hasn't clicked for me yet, even though I'm productively using them.

Unless I'm confused, is it a good idea this high up in the API to bake in support for fetch API options such as credentials: 'include' when a custom fetch function might use something other than fetch internally, such as XHR?

As an side note, auth header examples are pretty different looking between apollo-link and apollo-fetch:

Is apollo-link really intended to be used directly when building apps anyway?

this is definitely one thing that was easier in the previous network interface implementation.

IMO it has been as easy, or easier (WIP documentation aside) than before to set everything up. A real-world batched client setup with auth headers and uploads for a SSR Next.js app (see example without auth here for context):

import { ApolloClient } from 'react-apollo'
import BatchHttpLink from 'apollo-link-batch-http'
import { createApolloFetchUpload } from 'apollo-fetch-upload'

function createApolloClient({ initialState, getViewerToken }) {
  const apolloUploadFetch = createApolloFetchUpload({
    uri: `${process.env.API_URI}/graphql`
  })

  apolloUploadFetch.batchUse(({ options }, next) => {
    const viewerToken = getViewerToken()
    if (viewerToken) {
      if (!options.headers) options.headers = {}
      options.headers.authorization = `Bearer ${viewerToken}`
    }
    next()
  })

  return new ApolloClient({
    ssrMode: !process.browser,
    initialState,
    networkInterface: new BatchHttpLink({ fetch: apolloUploadFetch })
  })
}

For auth related fetch headers I used to have them fixed for SSR and as middleware for the client, in case the viewer situation changes between operations in a group of batched requests. For simplicity I just use middleware for both now since it doesn't seem to really slow SSR.

@stubailo
Copy link
Contributor

Is apollo-link really intended to be used directly when building apps anyway?

I'd claim that the code sample above qualifies as "using it directly", since you still have to deal with the configuration API.

I think you've got a good point about custom fetch functions that might have different APIs than window.fetch.

Would it be fair to say that the idea of building this into apollo-fetch is less controversial? What's our confidence level that having a credentials: include option on apollo-fetch would be a good idea?

@AdamYee
Copy link

AdamYee commented Oct 5, 2017

I might not fully understand the challenge here, but perhaps credentials could be used at the Link level or the fetch level where fetch defined credentials override Link defined credentials. It seems like the design approach has been to provide helpful defaults in a Link in addition to providing convenient ways to set fetch behavior.

Until this lands on an established pattern, I'll be taking this approach which seems independent of any changes made Link-wise.

const fetch = createApolloFetchUpload({
  uri: '/graphql'
});
fetch.batchUse(({ options }, next) => {
  options.credentials = 'same-origin';
  next();
});

I also noticed the docs have been getting updated recently. Does anyone know the current API design direction for this issue?

@jbaxleyiii
Copy link
Contributor

I think we should allow credentials and headers to the constructor for the http-link https://github.com/apollographql/apollo-link/tree/master/packages/apollo-link-http#options.

I'll assign and do this!

@jbaxleyiii jbaxleyiii self-assigned this Oct 10, 2017
@jbaxleyiii jbaxleyiii added this to the Apollo Client 2.0 Launch milestone Oct 12, 2017
@jbaxleyiii
Copy link
Contributor

Supported via #144!

@shendepu
Copy link

@jbaxleyiii Since credentials is configurable on apollo-link-http, but it is not available on apollo-link-batch-http.

@goldo
Copy link

goldo commented Nov 10, 2017

any news on credentials being available for apollo-link-batch-http ?

@moimael
Copy link

moimael commented Nov 14, 2017

Would be great to have it on apollo-link-batch-http, we had to disable batching in production and are seeing a huge increase in dyno usage.

@rtymchyk
Copy link

@moimael until there's an API on apollo-link-batch-http the workaround is using the solution described here: #44 (comment)

@KROT47
Copy link

KROT47 commented Dec 15, 2017

@tgriesser, @stubailo, any news on solving this?

@stubailo
Copy link
Contributor

Can you open a new issue specifically for the batch link?

@KROT47
Copy link

KROT47 commented Dec 16, 2017

@stubailo done. See #343

TreeAntSan added a commit to TreeAntSan/javrater-webapp that referenced this issue Apr 18, 2018
…ken not being loaded until a page refresh by using a custom fetch function. Links to existing literature are in the comments. It seems to work but I don't know if it's correct.

Simplified httpLink to use newly available headers option. Without this regrabbing the token would be far more complicated to achieve. (see apollographql/apollo-link#44)
Switching around confusing names in UserProtector (meData).

TODO: Still haven't figured out how to get header to refresh reliably - but now you no longer need to refresh the page to get the auth token. (Good way to test is to logout, navigate directly via address bar to /user/me and follow the login link on that page. You'll be directed back to the page and the data about your user will appear immediately).

Server:
Added new getAuthToken function - something I wrote for something I ended up abandoning (for now?)
onipiing added a commit to onipiing/jav-webapp that referenced this issue Nov 30, 2019
…ken not being loaded until a page refresh by using a custom fetch function. Links to existing literature are in the comments. It seems to work but I don't know if it's correct.

Simplified httpLink to use newly available headers option. Without this regrabbing the token would be far more complicated to achieve. (see apollographql/apollo-link#44)
Switching around confusing names in UserProtector (meData).

TODO: Still haven't figured out how to get header to refresh reliably - but now you no longer need to refresh the page to get the auth token. (Good way to test is to logout, navigate directly via address bar to /user/me and follow the login link on that page. You'll be directed back to the page and the data about your user will appear immediately).

Server:
Added new getAuthToken function - something I wrote for something I ended up abandoning (for now?)
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

10 participants