I’m trying to figure out the best practice for dealing with authentication with the Directus SDK.
I’ll get to the question before getting into the long boring details. The docs for the NextJS authentication tutorial say this:
You may have noticed in
./lib/directus.tsthat the Directus client is initialized with the parametercookieas a string. This serves well for server-side rendering applications, such as what this tutorial covers.
But the tutorial doesn’t get into the specifics of handling refresh tokens. The way it’s written means that every 15 minutes the access token is invalidated (based on the access token TTL) or if the user completely closes their browser since it’s a session cookie. I’d prefer it not to be a session based cookie but I’m guessing I just need to specify a maxAge when setting the cookie.
But the example never gets into the specifics of how to handle the refresh token. It only says this:
Temporary tokens will expire after some time, which can be rectified using the refresh functionality offered by the Directus SDK:
When using the Directus client in cookie mode I only get the access token in the login(...) response. I don’t get a refresh token. So if I attempt to do a refresh() call I get the error:
Invalid payload. The refresh token is required in either the payload or cookie.
I don’t have a refresh token. I assumed that this would be handled by the sdk client but I guess that’s not the case. Am I missing something about the authentication flow? On this page of the documentation it states:
You do not need to provide the
refresh_token, but you must specify themode.
Am I missing something in the documentation that I should be reading?
Thanks!
Now to the boring implementation details for anyone interested.
I have a Svelte 5 + SvelteKit project and I want to make my API calls via the SDK from the server-side logic (like +page.server.ts or +layout.server.ts). This question would most likely apply to any server-side scenario.
The Svelte example in the documentation is specific to client-side so it doesn’t help in my situation. The NextJS example does make calls from the server-side so I thought I would go by those tutorial steps but translated to a Svelte 5 app.
Here are some code specifics:
$lib/auth/directus.ts - Directus Client
export const client = createDirectus(env.DIRECTUS_URL)
.with(rest())
.with(authentication('cookie', { credentials: 'include' }));
NOTE ABOUT THIS - should I be using a “singleton” like pattern like this from the server-side or creating a new client per SDK/API request? If no user-specific data (like tokens) is stored on the server-side I’m assuming this is fine.
routes/(auth)/login/+page.server.ts - Server side logic for the login
const response = await client.login({ email: form.data.email, password: form.data.password });
if (response.access_token) {
event.cookies.set('directus_session_token', response.access_token, {
sameSite: 'strict',
path: '/',
secure: true,
});
} else {
throw new Error('could not find access_token in login response');
}
Checking if the user is authenticated - using the readMe() function
client.setToken(token);
const user = await client.request(readMe());
Trying to attempt a refresh - this doesn’t use the previously exported client:
const client = createDirectus(env.DIRECTUS_URL).with(authentication()).with(rest());
const response = await client.request(refresh({ mode: 'cookie' }));
if (!response.access_token) {
return false;
}
event.cookies.set('directus_session_token', response.access_token, {
sameSite: 'strict',
path: '/',
secure: true,
});