メインコンテンツへスキップ
バージョン: 9.x

認可

非公式ベータ版翻訳

このページは PageTurner AI で翻訳されました(ベータ版)。プロジェクト公式の承認はありません。 エラーを見つけましたか? 問題を報告 →

createContext関数は各受信リクエストに対して呼び出されるため、ここでリクエストオブジェクトから呼び出し元ユーザーに関するコンテキスト情報を追加できます。

リクエストヘッダーからコンテキストを作成

server/context.ts
ts
import * as trpc from '@trpc/server';
import { inferAsyncReturnType } from '@trpc/server';
import * as trpcNext from '@trpc/server/adapters/next';
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
server/context.ts
ts
import * as trpc from '@trpc/server';
import { inferAsyncReturnType } from '@trpc/server';
import * as trpcNext from '@trpc/server/adapters/next';
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

オプション1: リゾルバーを使用した認可

server/routers/_app.ts
ts
import * as trpc from '@trpc/server';
import { TRPCError } from '@trpc/server';
import { createRouter } from '../createRouter';
export const appRouter = createRouter()
// open for anyone
.query('hello', {
input: z.string().nullish(),
resolve: (opts) => {
return `hello ${opts.input ?? opts.ctx.user?.name ?? 'world'}`;
},
})
// checked in resolver
.query('secret', {
resolve: (opts) => {
if (!opts.ctx.user) {
throw new TRPCError({ code: 'UNAUTHORIZED' });
}
return {
secret: 'sauce',
};
},
});
server/routers/_app.ts
ts
import * as trpc from '@trpc/server';
import { TRPCError } from '@trpc/server';
import { createRouter } from '../createRouter';
export const appRouter = createRouter()
// open for anyone
.query('hello', {
input: z.string().nullish(),
resolve: (opts) => {
return `hello ${opts.input ?? opts.ctx.user?.name ?? 'world'}`;
},
})
// checked in resolver
.query('secret', {
resolve: (opts) => {
if (!opts.ctx.user) {
throw new TRPCError({ code: 'UNAUTHORIZED' });
}
return {
secret: 'sauce',
};
},
});

オプション2: ミドルウェアを使用した認可

server/routers/_app.ts
ts
import * as trpc from '@trpc/server';
import { TRPCError } from '@trpc/server';
import { createRouter } from '../createRouter';
export const appRouter = createRouter()
// this is accessible for everyone
.query('hello', {
input: z.string().nullish(),
resolve: (opts) => {
return `hello ${opts.input ?? opts.ctx.user?.name ?? 'world'}`;
},
})
.merge(
'admin.',
createRouter()
// this protects all procedures defined next in this router
.middleware(async ({ ctx, next }) => {
if (!ctx.user?.isAdmin) {
throw new TRPCError({ code: 'UNAUTHORIZED' });
}
return next();
})
.query('secret', {
resolve: (opts) => {
return {
secret: 'sauce',
};
},
}),
);
server/routers/_app.ts
ts
import * as trpc from '@trpc/server';
import { TRPCError } from '@trpc/server';
import { createRouter } from '../createRouter';
export const appRouter = createRouter()
// this is accessible for everyone
.query('hello', {
input: z.string().nullish(),
resolve: (opts) => {
return `hello ${opts.input ?? opts.ctx.user?.name ?? 'world'}`;
},
})
.merge(
'admin.',
createRouter()
// this protects all procedures defined next in this router
.middleware(async ({ ctx, next }) => {
if (!ctx.user?.isAdmin) {
throw new TRPCError({ code: 'UNAUTHORIZED' });
}
return next();
})
.query('secret', {
resolve: (opts) => {
return {
secret: 'sauce',
};
},
}),
);

このミドルウェアは保護されたルーターヘルパーを作成することで、複数のサブルーターで再利用できます。