Reputation: 239
I am using react-native and apollo client and if I try to set header by jwt stored in AsyncStorage, it seems not working.
Other resolvers which doesn't need header works very well. My code is like below.
import { ApolloClient } from "apollo-client";
import { InMemoryCache } from "apollo-cache-inmemory";
import { ApolloLink } from "apollo-link";
import { createHttpLink } from "apollo-link-http";
import AsyncStorage from "@react-native-community/async-storage";
const cache = new InMemoryCache();
const getToken = async () => {
const token = await AsyncStorage.getItem("jwt");
if (token) {
return token;
} else {
return null;
}
};
const httpLink = new createHttpLink({
uri: ""
});
const authLink = new ApolloLink((operation, forward) => {
operation.setContext({
headers: {
"X-JWT": getToken()
// this is where I set headers by getToken function
// If I change function getToken to real token in string type, it works then
}
});
return forward(operation);
});
const client = new ApolloClient({
cache: cache,
link: authLink.concat(httpLink)
});
export default client;
Like I commented in the code, calling getToken function is not working what I expected. I think I should have more knowledge of async and await, but I don't get it what is the real problem.
The error message I get from console is jwt malformed
. Please let me know how to fix this problem
Upvotes: 5
Views: 5405
Reputation: 25423
dont use operation.setContext
try to use setContext
from @apollo/client/link/context
like this
import { setContext } from "@apollo/client/link/context";
import {
ApolloClient,
InMemoryCache,
ApolloLink,
} from "@apollo/client";
import { setContext } from "@apollo/client/link/context";
import AsyncStorage from "@react-native-community/async-storage";
const httpLink = createHttpLink();
const authLink = setContext(async (_, { headers = {} }) => {
const token = await AsyncStorage.getItem("jwt");
return {
headers: {
...headers,
"X-JWT": token,
},
};
});
const client = new ApolloClient({
link: ApolloLink.from([authLink, httpLink]),
cache: new InMemoryCache(),
});
export default client;
Upvotes: 0
Reputation: 41
Thank you @аlex dykyі, this is my latest version
import { Auth } from "@aws-amplify/auth";
import { ApolloClient, ApolloLink, createHttpLink, InMemoryCache } from "@apollo/client";
import { setContext } from "@apollo/client/link/context";
export const getGraphqlClient = (url: string) => {
const getToken = async () => {
return (await Auth.currentSession()).getIdToken().getJwtToken();
};
const authMiddleware = setContext(async (operation) => {
return {
headers: {
authorization: `Bearer ${await getToken()}` || null,
},
};
});
const link = ApolloLink.from([authMiddleware]);
const httpLink = createHttpLink({ uri: url });
return new ApolloClient({
link: link.concat(httpLink),
cache: new InMemoryCache(),
});
};
Upvotes: 0
Reputation: 5698
import { setContext } from '@apollo/client/link/context';
// import getJwtToken // return string
const authMiddleware = setContext(async (operation) =>{
const token = await getJwtToken();
return {
headers: {
authorization: token || null,
},
};
});
const link = ApolloLink.from([
authMiddleware,
// ...
]);
Upvotes: 4
Reputation: 11810
Try to use setContext
directly
import { ApolloClient } from "apollo-client";
import { createHttpLink } from "apollo-link-http";
import { setContext } from "apollo-link-context";
import { InMemoryCache } from "apollo-cache-inmemory";
import AsyncStorage from "@react-native-community/async-storage";
const httpLink = createHttpLink();
const authLink = setContext(async (_, { headers }) => {
const token = await AsyncStorage.getItem("jwt");
return {
headers: {
...headers,
"X-JWT": token || null
}
};
});
const client = new ApolloClient({
link: authLink.concat(httpLink),
cache: new InMemoryCache()
});
export default client;
Upvotes: 16
Reputation: 2651
The problem is that you are not awaiting the promise.
That means it should be await getToken()
. In order to make this working the ApolloLink function should also be async
.
This would decrease your performance a little because on every request it would read the token from your AsyncStore
.
I would do it like that:
import { ApolloClient } from "apollo-client";
import { InMemoryCache } from "apollo-cache-inmemory";
import { ApolloLink } from "apollo-link";
import { createHttpLink } from "apollo-link-http";
import AsyncStorage from "@react-native-community/async-storage";
const cache = new InMemoryCache();
let token
const getToken = async () => {
if(token) return token;
token = await AsyncStorage.getItem("jwt");
return token || null;
};
const httpLink = new createHttpLink({
uri: ""
});
const authLink = new ApolloLink(async (operation, forward) => {
operation.setContext({
headers: {
"X-JWT": await getToken()
// this is where I set headers by getToken function
// If I change function getToken to real token in string type, it works then
}
});
return forward(operation);
});
const client = new ApolloClient({
cache: cache,
link: authLink.concat(httpLink)
});
export default client;
Upvotes: -1