···2828from persisted storage, and redirect them to the application home or login page.
29293030**Refresh (optional)** — this is not always implemented; if your API supports it, the
3131-user will receive both an auth token, and a refresh token.
3131+user will receive both an auth token, and a refresh token.
3232The auth token is usually valid for a shorter duration of time (e.g. 1 week) than the refresh token
3333(e.g. 6 months), and the latter can be used to request a new
3434auth token if the auth token has expired. The refresh logic is triggered either when the JWT is known to be invalid (e.g. by decoding it and inspecting the expiry date),
···283283 return false;
284284}
285285```
286286+287287+This can be really useful when we know when our authentication state is invalid and want to prevent
288288+even sending any operation that we know will fail with an authentication error. However, if we were
289289+to use this and are logging in our users with a login _mutation_ then the above code will
290290+unfortunately never let this login mutation through to our GraphQL API.
291291+292292+If we have such a mutation we may need to write a more sophisticated `willAuthError` function like
293293+the following:
294294+295295+```js
296296+const willAuthError = ({ operation, authState }) => {
297297+ if (!authState) {
298298+ // Detect our login mutation and let this operation through:
299299+ return !(
300300+ operation.kind === 'mutation' &&
301301+ // Here we find any mutation definition with the "login" field
302302+ operation.query.definitions.some(definition => {
303303+ return (
304304+ definition.kind === 'OperationDefinition' &&
305305+ definition.selectionSet.selections.some(node => {
306306+ // The field name is just an example, since signup may also be an exception
307307+ return node.kind === 'Field' && node.name.value === 'login';
308308+ })
309309+ );
310310+ })
311311+ );
312312+ } else if (false /* JWT is expired */) {
313313+ return true;
314314+ }
315315+316316+ return false;
317317+};
318318+```
319319+320320+Alternatively, you may decide to let all operations through if `authState` isn't defined or to allow
321321+all mutations through. In an application that allows unauthenticated users to perform various
322322+actions, it's a good idea for us to return `false` when `!authState` applies.
286323287324[Read more about `@urql/exchange-auth`'s API in our API docs.](../api/auth-exchange.md)
288325