0

I am using tRPC with SvelteKit for the first time, and I am stuck trying to validate the user's authentication.

I have the following in hooks.server.ts:

import { createContext } from '$lib/trpc/context';
import { router } from '$lib/trpc/router';
import type { Handle, HandleServerError } from '@sveltejs/kit';
import { redirect } from '@sveltejs/kit';
import { createTRPCHandle } from 'trpc-sveltekit';

import { getHTTPStatusCodeFromError } from '@trpc/server/http';

const trpcHandleError = ({ type, path, error }) => {
    console.error(`Encountered error while trying to process ${type} @ ${path}:`, error);
    const httpStatus = getHTTPStatusCodeFromError(error);

    if (httpStatus === 401) {
        // How do I redirect here??
    } else if (httpStatus == 403) {
        // Throw a 404
    }
}

export const handle: Handle = createTRPCHandle({ router, createContext, onError: trpcHandleError });

export const handleError: HandleServerError = ({ error, event }) => {
    // ...or here?
}

My question is: How do I redirect the user within the trpcHandleError to /login if the error.code is UNAUTHORIZED?

I've tried simply throw redirect(307, '/login'); but it was just ignored.

Basil
  • 488
  • 1
  • 15

1 Answers1

3

onError is a hook that gets notified when error occurs, but gives you no control over the response result.

Instead, you can provide a responseMeta function param to createTRPCHandle({ responseMeta }). This function is supposed to return a meta object that has { status, headers } keys, which affects the final response (source code).

It has following function signature:

const { status, headers } = responseMeta({
  ctx,
  paths,
  type,
  data: Array<{ error: ... } | { result: { data: ... } }>,
});

You can read the params.data array, and filter out items that have error key to handle them. To achieve the same effect of redirect(307, '/login'), you need to return a meta object of shape:

{ status: 307, headers: { Location: "/login" } }
hackape
  • 18,643
  • 2
  • 29
  • 57
  • I implemented a preliminary version of this, but how would one go about adding a redirect back to the original URL after re-authing? – David Lee Apr 19 '23 at 05:27
  • @DavidLee I believe you can respond with `{ status: 307, headers: { Location: "/login?redirect_url=..." } }`, and handle the redirection in `/login` route. – hackape Apr 19 '23 at 09:15