# @urql/exchange-auth

> An exchange for managing authentication and token refresh in urql

Latest version **3.0.0** (published 2025-08-09) · MIT license · 0 weekly downloads

## Install

```sh
npm install @urql/exchange-auth
pnpm add @urql/exchange-auth
yarn add @urql/exchange-auth
bun add @urql/exchange-auth
```

## Health

**Score 60/100 (C)** — status: stable.

Positive: has types; esm support; no vulnerabilities; has provenance; high maintenance score; high quality score.

Warnings: low downloads.

Negative: stale.

## Facts

| | |
|---|---|
| Version | 3.0.0 |
| Published | 2025-08-09 |
| First published | 2020-09-08 |
| Weekly downloads | 0 |
| License | MIT |
| TypeScript types | bundled |
| Module format | ESM + CommonJS |
| Dependencies | 2 |
| Unpacked size | 45.7 KB |
| Known vulnerabilities | 0 |
| Install scripts | no |
| Provenance | attested (GitHub Actions) |
| GitHub stars | 8975 |
| Author | urql GraphQL Contributors |
| Maintainers | michaelmerrill, sarmeyer, mariano-formidable, ryan.roemer, formidable-owner, formidablelabs, carbonrobot, masiddee, scott-rippey, sarahformidable, robwalkerco, ceceppa, keithluchtel, scottianstewart, philpl, andyrichardson, jdecroock, parkerziegler, npm-urql |
| Keywords | urql, exchange, auth, authentication, graphql, exchanges |

## Links

- npm: https://www.npmjs.com/package/@urql/exchange-auth
- Repository: https://github.com/urql-graphql/urql
- Homepage: https://formidable.com/open-source/urql/docs/
- Issues: https://github.com/urql-graphql/urql/issues
- npm.io page: https://npm.io/package/@urql/exchange-auth

## Dependencies (2)

- [wonka](https://npm.io/package/wonka.md) ^6.3.2
- [@urql/core](https://npm.io/package/@urql/core.md) ^6.0.0

## Alternatives

- [@clerk/clerk-expo](https://npm.io/package/@clerk/clerk-expo.md) — 133.6K weekly downloads
- [@pothos/plugin-authz](https://npm.io/package/@pothos/plugin-authz.md) — 12.4K weekly downloads
- [@bounded-sh/client](https://npm.io/package/@bounded-sh/client.md) — 3.2K weekly downloads
- [@luigi-project/plugin-auth-oauth2](https://npm.io/package/@luigi-project/plugin-auth-oauth2.md) — 2.3K weekly downloads
- [@nocobase/plugin-verification](https://npm.io/package/@nocobase/plugin-verification.md) — 2.0K weekly downloads

## Recent versions

- 3.0.0 (latest) — 2025-08-09
- 3.0.0-canary-b981b388ee9ed0066399a632aad6b84559f014a6 (canary) — 2025-08-09
- 3.0.0-canary-d3b019d51905c1c8b22be9ea1d9fe9ca4335a46c — 2025-08-09
- 3.0.0-canary-b2d8b993af4abb0ffc5c5284b90aca56c527f045 — 2025-06-29
- 2.2.1 — 2025-03-03
- 2.2.1-canary-573944cea80f766668d3b9d8aa1afd2c50d744a4 — 2025-03-03
- 2.2.0 — 2024-05-10
- 2.2.0-canary-9bf3289b — 2024-05-07
- 2.2.0-canary-019b1bb0 — 2024-05-04
- 2.2.0-canary-9272cefa — 2024-05-03
- 2.2.0-canary-0204e044 — 2024-05-03
- 2.1.6 — 2023-07-30
- 2.1.6-canary-f9ea1db4 — 2023-07-30
- 2.1.6-canary-51f67ade — 2023-07-28
- 2.1.5 — 2023-07-12
- … 99 more at https://npm.io/package/@urql/exchange-auth/versions

## README

<h2 align="center">@urql/exchange-auth</h2>

<p align="center"><strong>An exchange for managing authentication in <code>urql</code></strong></p>

`@urql/exchange-auth` is an exchange for the [`urql`](https://github.com/urql-graphql/urql) GraphQL client which helps handle auth headers and token refresh

## Quick Start Guide

First install `@urql/exchange-auth` alongside `urql`:

```sh
yarn add @urql/exchange-auth
# or
npm install --save @urql/exchange-auth
```

You'll then need to add the `authExchange`, that this package exposes to your `urql` Client

```js
import { createClient, cacheExchange, fetchExchange } from 'urql';
import { makeOperation } from '@urql/core';
import { authExchange } from '@urql/exchange-auth';

const client = createClient({
  url: 'http://localhost:1234/graphql',
  exchanges: [
    cacheExchange,
    authExchange(async utils => {
      // called on initial launch,
      // fetch the auth state from storage (local storage, async storage etc)
      let token = localStorage.getItem('token');
      let refreshToken = localStorage.getItem('refreshToken');

      return {
        addAuthToOperation(operation) {
          if (token) {
            return utils.appendHeaders(operation, {
              Authorization: `Bearer ${token}`,
            });
          }
          return operation;
        },
        willAuthError(_operation) {
          // e.g. check for expiration, existence of auth etc
          return !token;
        },
        didAuthError(error, _operation) {
          // check if the error was an auth error
          // this can be implemented in various ways, e.g. 401 or a special error code
          return error.graphQLErrors.some(e => e.extensions?.code === 'FORBIDDEN');
        },
        async refreshAuth() {
          // called when auth error has occurred
          // we should refresh the token with a GraphQL mutation or a fetch call,
          // depending on what the API supports
          const result = await mutate(refreshMutation, {
            token: authState?.refreshToken,
          });

          if (result.data?.refreshLogin) {
            // save the new tokens in storage for next restart
            token = result.data.refreshLogin.token;
            refreshToken = result.data.refreshLogin.refreshToken;
            localStorage.setItem('token', token);
            localStorage.setItem('refreshToken', refreshToken);
          } else {
            // otherwise, if refresh fails, log clear storage and log out
            localStorage.clear();
            logout();
          }
        },
      };
    }),
    fetchExchange,
  ],
});
```

## Handling Errors via the errorExchange

Handling the logout logic in `refreshAuth` is the easiest way to get started,
but it means the errors will always get swallowed by the `authExchange`.
If you want to handle errors globally, this can be done using the `mapExchange`:

```js
import { mapExchange } from 'urql';

// this needs to be placed ABOVE the authExchange in the exchanges array, otherwise the auth error
// will show up hear before the auth exchange has had the chance to handle it
mapExchange({
  onError(error) {
    // we only get an auth error here when the auth exchange had attempted to refresh auth and
    // getting an auth error again for the second time
    const isAuthError = error.graphQLErrors.some(
      e => e.extensions?.code === 'FORBIDDEN',
    );
    if (isAuthError) {
      // clear storage, log the user out etc
    }
  }
}),
```

---
_Source: https://npm.io/package/@urql/exchange-auth · Machine-readable twin of the npm.io package page. Health data is recomputed on every publish._
