Skip to content

Commit

Permalink
fix: csrf token refetch (#2196)
Browse files Browse the repository at this point in the history
  • Loading branch information
flagrede authored Oct 31, 2023
1 parent 4a731ed commit 53af644
Show file tree
Hide file tree
Showing 3 changed files with 62 additions and 10 deletions.
68 changes: 59 additions & 9 deletions web-marketplace/src/apollo.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,19 @@ import {
ApolloProvider,
createHttpLink,
DefaultOptions,
FetchResult,
InMemoryCache,
Observable,
split,
} from '@apollo/client';
import { setContext } from '@apollo/client/link/context';
import { useQuery } from '@tanstack/react-query';
import { onError } from '@apollo/client/link/error';
import { useQuery, useQueryClient } from '@tanstack/react-query';

import { ApolloClientFactory } from 'lib/clients/apolloClientFactory';
import { getCsrfTokenQuery } from 'lib/queries/react-query/registry-server/getCsrfTokenQuery/getCsrfTokenQuery';
import { GET_CSRF_QUERY_KEY } from 'lib/queries/react-query/registry-server/getCsrfTokenQuery/getCsrfTokenQuery.constants';
import { getFromCacheOrFetch } from 'lib/queries/react-query/utils/getFromCacheOrFetch';

import { apiUri, indexerApiUri } from './lib/apiUri';

Expand All @@ -23,7 +28,8 @@ export const AuthApolloProvider = ({
apolloClientFactory,
children,
}: AuthApolloProviderProps): any => {
const query = useQuery(getCsrfTokenQuery({}));
const reactQueryClient = useQueryClient();
useQuery(getCsrfTokenQuery({}));

// https://www.apollographql.com/docs/react/networking/authentication
const httpLink = createHttpLink({
Expand All @@ -36,12 +42,19 @@ export const AuthApolloProvider = ({
});

// https://www.apollographql.com/docs/react/api/link/apollo-link-context/#overview
const authLink = setContext((_, { headers }) => ({
headers: {
...headers,
'X-CSRF-TOKEN': query.data,
},
}));
const authLink = setContext(async (_, { headers }) => {
const csrfToken = await getFromCacheOrFetch({
query: getCsrfTokenQuery({}),
reactQueryClient: reactQueryClient,
});

return {
headers: {
...headers,
'X-CSRF-TOKEN': csrfToken,
},
};
});

const defaultOptions: DefaultOptions = {
watchQuery: {
Expand All @@ -54,6 +67,43 @@ export const AuthApolloProvider = ({
},
};

const errorLink = onError(({ operation, networkError, forward }) => {
if (
networkError &&
networkError.message.includes('status code 403') &&
operation.operationName !== 'GetCurrentAccount'
) {
const observable = new Observable<FetchResult<Record<string, any>>>(
observer => {
(async () => {
try {
await reactQueryClient.invalidateQueries({
queryKey: [GET_CSRF_QUERY_KEY],
});
// trigger a call to get a new CSRF token and refill the cache earlier
await getFromCacheOrFetch({
query: getCsrfTokenQuery({}),
reactQueryClient: reactQueryClient,
});

const subscriber = {
next: observer.next.bind(observer),
error: observer.error.bind(observer),
complete: observer.complete.bind(observer),
};

forward(operation).subscribe(subscriber);
} catch (err) {
observer.error(err);
}
})();
},
);

return observable;
}
});

const mainLink = authLink.concat(httpLink);

const splitLink = split(
Expand All @@ -63,7 +113,7 @@ export const AuthApolloProvider = ({
return operationName.startsWith('Indexer');
},
indexerHttpLink,
ApolloLink.from([mainLink]),
ApolloLink.from([errorLink, mainLink]),
);

apolloClientFactory.prepare({
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
export const GET_CSRF_QUERY_KEY = 'csrfToken';
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import { apiUri } from 'lib/apiUri';

import { GET_CSRF_QUERY_KEY } from './getCsrfTokenQuery.constants';
import {
ReactQueryCsrfTokenProps,
ReactQueryCsrfTokenResponse,
Expand All @@ -8,7 +9,7 @@ import {
export const getCsrfTokenQuery = ({
...params
}: ReactQueryCsrfTokenProps): ReactQueryCsrfTokenResponse => ({
queryKey: ['csrfToken'],
queryKey: [GET_CSRF_QUERY_KEY],
queryFn: async () => {
const resp = await fetch(`${apiUri}/marketplace/v1/csrfToken`, {
method: 'GET',
Expand Down

0 comments on commit 53af644

Please sign in to comment.