Created
May 14, 2020 16:45
-
-
Save bzhr/cd047e751a6293756db474695f40bae0 to your computer and use it in GitHub Desktop.
Apollo Refresh Token
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import React from "react"; | |
import ReactDOM from "react-dom"; | |
import ApolloClient from "apollo-client"; | |
import { ApolloProvider } from "@apollo/react-hooks"; | |
import { ApolloLink, fromPromise } from "apollo-link"; | |
import { onError } from "apollo-link-error"; | |
// import "./index.css"; | |
import App from "./App"; | |
import * as serviceWorker from "./serviceWorker"; | |
import { createUploadLink } from "apollo-upload-client"; | |
import { setContext } from "apollo-link-context"; | |
import { InMemoryCache } from "apollo-cache-inmemory"; | |
import "./assets/main.css"; | |
import { signOut } from "./components/Auth"; | |
import { getToken, getRefreshToken, getNewToken } from "./constants/token"; | |
const API_URL = process.env.REACT_APP_API_URL; | |
const httpLink = createUploadLink({ | |
uri: API_URL ? API_URL : "/graphql", | |
credentials: "omit", | |
}); | |
const authLink = setContext((_, { headers }) => { | |
// get the authentication token from local storage if it exists | |
const token = localStorage.getItem("token"); | |
return { | |
headers: { | |
...headers, | |
authorization: token ? `JWT ${token}` : "", | |
}, | |
}; | |
}); | |
let isRefreshing = false; | |
let pendingRequests = []; | |
const resolvePendingRequests = () => { | |
pendingRequests.map((callback) => callback()); | |
pendingRequests = []; | |
}; | |
const errorLink = onError( | |
({ graphQLErrors, networkError, operation, forward, location, ...other }) => { | |
console.log("On error"); | |
console.log(graphQLErrors, networkError, other); | |
// TODO --- On error message invalid token clear local storage | |
if (graphQLErrors && graphQLErrors.filter((e) => e).length > 0) { | |
console.log("Errors: ", graphQLErrors); | |
for (let err of graphQLErrors) { | |
console.log("Message: ", err.message); | |
if (err.message.includes("You do not have permission")) { | |
const token = getToken(); | |
const refreshToken = getRefreshToken(); | |
console.log("Token, refresh", token, refreshToken); | |
if (token && refreshToken) { | |
console.log("In if condition"); | |
let forward$; | |
if (!isRefreshing) { | |
isRefreshing = true; | |
forward$ = fromPromise( | |
getNewToken(client) | |
.then(({ data: { refreshToken } }) => { | |
console.log("Promise data: ", refreshToken); | |
if (refreshToken && refreshToken.success) { | |
localStorage.setItem("token", refreshToken.token); | |
localStorage.setItem( | |
"refreshToken", | |
refreshToken.refreshToken | |
); | |
resolvePendingRequests(); | |
} else { | |
signOut(); | |
} | |
return refreshToken.token; | |
}) | |
.catch((error) => { | |
// Handle token refresh errors e.g clear stored tokens, redirect to login, ... | |
console.log("Error after setting token: ", error); | |
pendingRequests = []; | |
return; | |
}) | |
.finally(() => { | |
console.log("Finally"); | |
isRefreshing = false; | |
}) | |
).filter((value) => { | |
console.log("In Filter: ", value); | |
return Boolean(value); | |
}); | |
} else { | |
console.log("In else condition"); | |
// Will only emit once the Promise is resolved | |
forward$ = fromPromise( | |
new Promise((resolve) => { | |
console.log("In else condition Promise"); | |
pendingRequests.push(() => resolve()); | |
}) | |
); | |
} | |
return forward$.flatMap(() => { | |
console.log("Forwarding!"); | |
console.log(operation); | |
return forward(operation); | |
}); | |
} | |
// else { | |
// // If there's no token, then sign out user | |
// console.log("There's no token, sign out the user", signOut); | |
// signOut(); | |
// } | |
} | |
} | |
} | |
if (networkError) { | |
console.log("Network error: ", networkError); | |
} | |
} | |
); | |
const links = [errorLink, authLink, httpLink]; | |
const link = ApolloLink.from(links); | |
export const client = new ApolloClient({ | |
link, | |
cache: new InMemoryCache(), | |
fetchOptions: { | |
mode: "no-cors", | |
}, | |
}); | |
ReactDOM.render( | |
<ApolloProvider client={client}> | |
<App /> | |
</ApolloProvider>, | |
document.getElementById("root") | |
); | |
// If you want your app to work offline and load faster, you can change | |
// unregister() to register() below. Note this comes with some pitfalls. | |
// Learn more about service workers: https://bit.ly/CRA-PWA | |
serviceWorker.unregister(); |
That one is specific to your backend.
I used graphql, I had one mutation called refreshToken(), but cannot execute that because ApolloClient not yet initialized. Do u have any idea ?
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hi, could u show me the refreshToken function pls ?