Following this example in Nextjs repository, I want to implement the CSRF protection (perhaps with csurf package), because I'm using a session ID cookie with express-session.
I tried setting csurf in my custom server and save the generated token in res.locals.csrfToken which can be taken, on first page load, by the static method "getInitialProps" which is located in /lib/withApollo.js in the example I linked. As soon as I try to change page (with links) or try to make a post request with apollo (login, for instance), server changes the csrf token, so the one which was used by Apollo is no more useful and so I get a "csrf is invalid" error.
Custom server with csurf configuration
const csrf = require('csurf');
const csrfProtection = csrf();
////express-session configuration code////
app.use(csrfProtection);
app.use((req, res, next) => {
res.locals.csrfToken = req.csrfToken();
next();
})
/lib/initApollo.js
function create(initialState, { getToken, cookies, csrfToken }) {
const httpLink = createHttpLink({
uri: "http://localhost:3000/graphql",
credentials: "include"
});
const authLink = setContext((_, { headers }) => {
const token = getToken();
return {
headers: {
...headers,
authorization: token ? `Bearer ${token}` : "",
Cookie: cookies ? cookies : "",
"x-xsrf-token": csrfToken ? csrfToken : ""
}
};
});
/lib/withApollo.js
static async getInitialProps(ctx) {
const {
Component,
router,
ctx: { req, res }
} = ctx;
const apollo = initApollo(
{},
{
getToken: () => parseCookies(req).token,
cookies: req ? req.headers.cookie : "",
csrfToken: res ? res.locals.csrfToken : document.cookie
}
);
With this config, every route is protected against csrf, but the token created on the server often change and Apollo can't retrieve the updated one as soon as it needs, so the first load is successful, but the subsequent page change (links) or any post request fails, because the token has changed.
They also make and maintain a GraphQL client (Apollo Client) that we can use with React frameworks like Next. js. The Apollo Client is a state management client that allows you to manage both local and remote data with GraphQL and you can use it to fetch, cache, and modify application data.
You can enable credentials with CORS by setting the Access-Control-Allow-Credentials HTTP header to true . You must specify an origin to enable credentialed requests. If your server sends the * wildcard value for the Access-Control-Allow-Origin HTTP header, your browser will refuse to send credentials.
GraphQL serverA server that contains a GraphQL schema and can resolve operations that are executed against that schema. Apollo Server is an example of a GraphQL server.
After so much browsing i finally was able to send csrf cookie. I think the problem lies with with the word return
.When you use return it excludes the cookie. This is what i did by editing /lib/initApollo.js
.
function create(initialState, { getToken, cookies, csrfToken }) { const httpLink = createHttpLink({ uri: "http://localhost:3000/graphql", credentials: "include" }); const authLink = setContext((_, { headers }) => { const token = getToken(); return { headers: { ...headers, authorization: token ? `Bearer ${token}` : "", "x-xsrf-token": csrfToken ? csrfToken : "" } cookies: { ...cookies } }; }); });
pree!! However SSR does not have cookies. I think we should have two endpoint from client and another for SSR. The SSR url can be csrf exempted.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With