gpt4 book ai didi

How to properly pass a user and run middleware on apollo server v4(如何正确传递用户并在Apollo服务器v4上运行中间件)

转载 作者:bug小助手 更新时间:2023-10-24 23:17:57 30 4
gpt4 key购买 nike



I am creating an apollo server v4 gql gateway with the express.js integration.
I have user typedefs and user resolvers working and creating a jwt when a user is created.
I then try to use my jwtMiddleware middleware on the /graphql endpoint so that it can validate a bearer token is being passed in to prevent unauthenticated requests to some other queries I have created.

我正在创建一个Apollo服务器v4gql网关,其中集成了exts.js。在创建用户时,我让用户typedef和用户解析器工作并创建JWT。然后,我尝试在/GraphQL端点上使用我的jwtMiddleware中间件,以便它可以验证传入的承载令牌,以防止对我创建的其他一些查询的未经身份验证的请求。


In my index.ts:

在我的index.ts中:


import express, { Request, Response, Application } from 'express';
import gqlServerV1 from './gql/v1/gqlServerV1';
import { mongoClient } from './mongodb/mongoclient';
import cors from 'cors';
import pkg from 'body-parser';
import { expressMiddleware } from '@apollo/server/express4';
import jwtMiddleware from './middleware/verifyJwt';
const { json } = pkg;

// Create express app
const app: Application = express();
const port: number = 5950;
const startUp = async () => {
// Fire up mongodb client
await mongoClient();

// Apply gql server to work with express as middleware w/ apollo-server v4
// Migrate away from v3: https://www.apollographql.com/docs/apollo-server/migration/#migrate-from-apollo-server-express
await gqlServerV1.start();

app.use(
'/v1/graphql',
cors<cors.CorsRequest>(),
json(),
jwtMiddleware,
expressMiddleware(gqlServerV1, {
context: async ({ req }) => ({
token: req.headers.token,
user: req.user,
}),
})
);

console.log(`server started at http://localhost:${port}`);
};

app.listen(port, async () => {
await startUp();
});


jwtMiddleware file

JwtMiddleware文件


import jwt from 'jsonwebtoken';
import dotenv from 'dotenv';

dotenv.config();

const JWT_SECRET = process.env.JWT_SECRET || 'defaultSecret';

const jwtMiddleware = async (req, res, next, context) => {
const authorizationHeader = req.headers.authorization;

console.log('heress');

if (!authorizationHeader || !authorizationHeader.startsWith('Bearer ')) {
// Token is missing or in an invalid format
return next();
}

const token = authorizationHeader.replace('Bearer ', '');

try {
// Verify the JWT token
const decodedToken = jwt.verify(token, JWT_SECRET);

console.log(decodedToken);

// Get the user data from the request context
const user = context.user;

// Continue processing the request if the user is authenticated
if (user) {
next();
} else {
// The user is not authenticated, so return an error
return res.status(401).json({ message: 'Unauthorized' });
}
} catch (error) {
// The JWT token is invalid, so return an error
return res.status(401).json({ message: 'Invalid token' });
}
};

export default jwtMiddleware;


The issue I am facing:

我面临的问题是:


when starting my server I see this error coming from index.ts when passing req.user

当启动我的服务器,我看到这个错误来自index.ts时,传递req.user


TSError: ⨯ Unable to compile TypeScript:
src/index.ts:37:19 - error TS2339: Property 'user' does not exist on type 'Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>'.

37 user: req.user,


  1. I never see any console logs from my middleware being output.


This is my gql server in a separate file:

这是我的GQL服务器在一个单独的文件中:


import { ApolloServer } from '@apollo/server';
import addressTypeDefs from './typeDefs/addressTypeDefs';
import userTypeDef from './typeDefs/userTypeDef';
import resolvers from './resolvers';

interface MyContext {
token?: String;
user?: Object;
}

// Create gql server
const gqlServerV1 = new ApolloServer<MyContext>({
typeDefs: [addressTypeDefs, userTypeDef],
resolvers,
introspection: false,
});

export default gqlServerV1;


package json scripts:

包json脚本:


  "scripts": {
"start": "ts-node-dev --watch src src/index.ts",
"dev:server": "nodemon --watch './**/*.ts' --exec 'node --experimental-specifier-resolution=node --loader ts-node/esm' src/index.ts",
"test": "jest --detectOpenHandles --config jest.config.ts ./__tests__",
"watch": "nodemon --watch './**/*.{ts,graphql}' --exec 'node --experimental-specifier-resolution=node --no-warnings --loader ts-node/esm' src/index.ts",
"dev": "tsc-watch --onSuccess \"npm run watch\""
},

I also have a custom.d.ts file to try to extend express:

我还有一个定制的.d.ts文件,可以尝试扩展Express:


interface JwtPayload {
// Customize the properties based on JWT payload
email: string;
}

// Extend the express request type
declare namespace Express {
interface Request {
user: JwtPayload;
}
}



  1. How do I properly pass a req.user ?

  2. Why is my middleware never running to validate the user/token?


Thanks!

谢谢!


更多回答
优秀答案推荐

I figured out the problem and will leave the question posted so others can learn. The issue I was facing was because ts-node was not able to interpret the type I was extending and adding user to i.e. the request. Here's what I did.

我发现了问题,并将问题张贴在网上,这样其他人就可以学习了。我面临的问题是因为ts-node不能解释我正在扩展和添加用户的类型,即请求。我是这么做的。



  1. Create a new dir and d.ts file at root/src/@types/express/index.d.ts.

  2. In ts config make sure I have my custom types come before any others in the typeRoot config. Like so:


{
"compilerOptions": {
"rootDirs": ["src"],
"outDir": "dist",
"lib": ["es2020"],
"target": "es2020",
"module": "esnext",
"moduleResolution": "node",
"esModuleInterop": true,
"types": ["node", "jest", "express"],
"typeRoots": ["./src/@types", "./node_modules/@types"],
"skipLibCheck": true /* Skip type checking all .d.ts files. */
},
"include": ["src/**/*.ts"]
}



  1. Inside of the index.d.ts I imported a custom interface I have set up in my models from mongodb and set that as the type like so:


import * as express from 'express';
import { User } from '../../models/User';

declare global {
namespace Express {
interface Request {
user?: User;
}
}
}



  1. In my verifyJwt middleware, I removed context from the middleware signature and replaced instances of context with req instead.


After this, I restarted the ts server as well as my local server and Voila, it worked and the dumb Property 'user' does not exist on type 'Request<ParamsDictionary, any, any, ParsedQs, Record<string, any>>'. error was gone. AND my middleware began working and I started seeing console logs from the middleware as verification.

在此之后,我重新启动了ts服务器以及我的本地服务器和Voila,它起作用了,并且在类型‘请求’中不存在哑属性‘USER’。错误已经消失了。我的中间件开始工作,我开始看到来自中间件的控制台日志作为验证。


Hope this helps someone else.

希望这对其他人有帮助。


更多回答

30 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com