Skip to main content
Version: 5.0

Resource Authentication

All network requests are run through the static getFetchInit optionally defined in your Resource.

Here's an example using simple cookie auth:

import { Resource } from '@rest-hooks/rest';

abstract class AuthdResource extends Resource {
static getFetchInit = (init: RequestInit): RequestInit => ({
...init,
credentials: 'same-origin',
});
}

You can also do more complex flows (like adding arbitrary headers) to the request. Every getFetchInit() takes in the existing init options of fetch, and returns new init options to be used.

Access Tokens

resources/AuthdResource.ts
import { getAuthToken } from 'authorization-singleton';
import { Resource } from '@rest-hooks/rest';

abstract class AuthdResource extends Resource {
declare static accessToken?: string;
static getFetchInit = (init: RequestInit): RequestInit => ({
...init,
headers: {
...init.headers,
'Access-Token': this.accessToken,
},
});
}

Upon login we set the token:

Auth.tsx
import AuthdResource from 'resources/AuthdResource';

function Auth() {
const handleLogin = useCallback(
async e => {
const { accessToken } = await login(new FormData(e.target));
// success!
AuthdResource.accessToken = accessToken;
},
[login],
);

return <AuthForm onSubmit={handleLogin} />;
}

Auth Headers from React Context

danger

Using React Context for state that is not displayed (like auth tokens) is not recommended.

Here we use a context variable to set headers. Note - this means any endpoint functions can only be called from a React Component. (However, this should be fine since the context will only exist in React anyway.)

HookableResource gives us endpoint methods that are hooks so we can access React context.

import { HookableResource } from '@rest-hooks/rest';

abstract class AuthdResource extends HookableResource {
static useFetchInit = (init: RequestInit) => {
const accessToken = useAuthContext();
return {
...init,
headers: {
...init.headers,
'Access-Token': accessToken,
},
};
};
}
caution

Using this means all endpoint calls must only occur during a function render.

function CreatePost() {
const { fetch } = useController();
// PostResource.useCreate() calls useFetchInit()
const createPost = PostResource.useCreate();

return (
<form
onSubmit={e => fetch(createPost, {}, new FormData(e.target))}
>
{/* ... */}
</form>
);
}

Code organization

If much of your Resources share a similar auth mechanism, you might try extending from a base class that defines such common customizations.