Skip to main content

Authorization

The createContext-function is called for each incoming request so here you can add contextual information about the calling user from the request object.

Create context from request headers#

import * as trpc from '@trpc/server';
import { inferAsyncReturnType } from '@trpc/server';
import { decodeAndVerifyJwtToken } from './somewhere/in/your/app/utils';
export async function createContext({
req,
res,
}: trpcNext.CreateNextContextOptions) {
// Create your context based on the request object
// Will be available as `ctx` in all your resolvers
// This is just an example of something you'd might want to do in your ctx fn
async function getUserFromHeader() {
if (req.headers.authorization) {
const user = await decodeAndVerifyJwtToken(req.headers.authorization.split(' ')[1])
return user;
}
return null;
}
const user = await getUserFromHeader();
return {
user,
};
}
type Context = inferAsyncReturnType<typeof createContext>;
// [..] Define API handler and app router

Option 1: Authorize using resolver#

import * as trpc from '@trpc/server';
import { createRouter } from './[trpc]';
export const appRouter = createRouter()
// open for anyone
.query('hello', {
input: z.string().optional(),
resolve: ({ input, ctx }) => {
return `hello ${input ?? ctx.user?.name ?? 'world'}`;
},
})
// checked in resolver
.query('secret', {
resolve: ({ ctx }) => {
if (!ctx.user) {
throw trpc.httpError.unauthorized();
}
if (ctx.user?.name !== 'KATT') {
throw trpc.httpError.forbidden();
}
return {
secret: 'sauce',
};
},
});

Option 2: Authorize using middleware#

import * as trpc from '@trpc/server';
import { createRouter } from './[trpc]';
export const appRouter = createRouter()
// this is accessible for everyone
.query('hello', {
input: z.string().optional(),
resolve: ({ input, ctx }) => {
return `hello ${input ?? ctx.user?.name ?? 'world'}`;
},
})
.merge(
'admin.',
createRouter()
// this protectes all procedures defined after in this router
.middleware(async ({ ctx }) => {
if (!ctx.user?.isAdmin) {
throw httpError.unauthorized();
}
})
.query('secret', {
resolve: ({ ctx }) => {
return {
secret: 'sauce',
}
},
}),
);