1
import { NextRequest } from 'next/server';
3
import { JWTPayload, LOBE_CHAT_AUTH_HEADER } from '@/const/auth';
4
import { KeyVaultsGateKeeper } from '@/server/modules/KeyVaultsEncrypt';
6
export interface AsyncAuthContext {
7
jwtPayload: JWTPayload;
9
userId?: string | null;
13
* Inner function for `createContext` where we create the context.
14
* This is useful for testing when we don't want to mock Next.js' request/response
16
export const createAsyncContextInner = async (params?: {
17
jwtPayload?: JWTPayload;
19
userId?: string | null;
20
}): Promise<AsyncAuthContext> => ({
21
jwtPayload: params?.jwtPayload || {},
22
secret: params?.secret || '',
23
userId: params?.userId,
26
export type AsyncContext = Awaited<ReturnType<typeof createAsyncContextInner>>;
28
export const createAsyncRouteContext = async (request: NextRequest): Promise<AsyncContext> => {
29
// for API-response caching see https://trpc.io/docs/v11/caching
31
const authorization = request.headers.get('Authorization');
32
const lobeChatAuthorization = request.headers.get(LOBE_CHAT_AUTH_HEADER);
34
const secret = authorization?.split(' ')[1];
35
const gateKeeper = await KeyVaultsGateKeeper.initWithEnvKey();
36
const { plaintext } = await gateKeeper.decrypt(lobeChatAuthorization || '');
38
const { userId, payload } = JSON.parse(plaintext);
39
return createAsyncContextInner({ jwtPayload: payload, secret, userId });