关于与 apollo-server 一起使用时如何处理 'graphql-redis-subscriptions' 身份验证的任何想法
Any idea on how to handle 'graphql-redis-subscriptions' authentication when used together with apollo-server
我正在使用 https://github.com/davidyaha/graphql-redis-subscriptions 中的 'graphql-redis-subscriptions'。
给出了几个关于如何设置订阅的示例,它们确实有效,但我面临的问题是如何进行身份验证并允许订阅仅由登录的客户端用户收听。我正在使用 Apollo-server 为 graphql api 提供服务,如下所示:
const server = new ApolloServer({
schema,
dataSources,
context: async ({ req, connection }) => {
if (connection) {
return {
...connection.context
};
}
const token = req.headers[API_TOKEN];
return {
premiumAuth: token
};
},
});
server.listen(5000);
apollo-server
的context
选项中的Authenticated是针对HTTP协议请求的认证。这意味着它将保护 /graphql
端点免受未经身份验证的访问。例如
const contextFunction: ContextFunction<IContextFunctionParams, IConnectors<IMemoryDB>> = (
context: IContextFunctionParams,
): Context<IAppContext> => {
const { req, connection } = context;
if (connection) {
return connection.context;
} else {
const token: string = validateToken(req);
const userConnector = new UserConnector<IMemoryDB>(memoryDB);
let user: IUser | undefined;
try {
const userType: UserType = UserType[token];
user = userConnector.findUserByUserType(userType);
} catch (error) {
throw error;
}
return {
requestingUser: user,
locationConnector: new LocationConnector<IMemoryDB>(memoryDB),
userConnector,
templateConnector: new TemplateConnector<IMemoryDB>(
memoryDB,
pubsub,
// postgresPubSub,
),
};
}
};
用于WebSocket协议连接,graphql订阅依赖。
您需要在 subscriptions.onConnect
方法中进行身份验证,例如
const server = new ApolloServer({
typeDefs,
resolvers,
context: contextFunction,
introspection: true,
subscriptions: {
onConnect: (
connectionParams: IWebSocketConnectionParams,
webSocket: WebSocket,
connectionContext: ConnectionContext,
) => {
console.log('websocket connect');
console.log('connectionParams: ', connectionParams);
if (connectionParams.token) {
const token: string = validateToken(connectionParams.token);
const userConnector = new UserConnector<IMemoryDB>(memoryDB);
let user: IUser | undefined;
try {
const userType: UserType = UserType[token];
user = userConnector.findUserByUserType(userType);
} catch (error) {
throw error;
}
const context: ISubscriptionContext = {
// pubsub: postgresPubSub,
pubsub,
subscribeUser: user,
userConnector,
locationConnector: new LocationConnector<IMemoryDB>(memoryDB),
};
return context;
}
throw new Error('Missing auth token!');
},
onDisconnect: (webSocket: WebSocket, connectionContext: ConnectionContext) => {
console.log('websocket disconnect');
},
},
});
源代码:https://github.com/mrdulin/apollo-graphql-tutorial/tree/master/src/subscriptions
我正在使用 https://github.com/davidyaha/graphql-redis-subscriptions 中的 'graphql-redis-subscriptions'。 给出了几个关于如何设置订阅的示例,它们确实有效,但我面临的问题是如何进行身份验证并允许订阅仅由登录的客户端用户收听。我正在使用 Apollo-server 为 graphql api 提供服务,如下所示:
const server = new ApolloServer({
schema,
dataSources,
context: async ({ req, connection }) => {
if (connection) {
return {
...connection.context
};
}
const token = req.headers[API_TOKEN];
return {
premiumAuth: token
};
},
});
server.listen(5000);
apollo-server
的context
选项中的Authenticated是针对HTTP协议请求的认证。这意味着它将保护 /graphql
端点免受未经身份验证的访问。例如
const contextFunction: ContextFunction<IContextFunctionParams, IConnectors<IMemoryDB>> = (
context: IContextFunctionParams,
): Context<IAppContext> => {
const { req, connection } = context;
if (connection) {
return connection.context;
} else {
const token: string = validateToken(req);
const userConnector = new UserConnector<IMemoryDB>(memoryDB);
let user: IUser | undefined;
try {
const userType: UserType = UserType[token];
user = userConnector.findUserByUserType(userType);
} catch (error) {
throw error;
}
return {
requestingUser: user,
locationConnector: new LocationConnector<IMemoryDB>(memoryDB),
userConnector,
templateConnector: new TemplateConnector<IMemoryDB>(
memoryDB,
pubsub,
// postgresPubSub,
),
};
}
};
用于WebSocket协议连接,graphql订阅依赖。
您需要在 subscriptions.onConnect
方法中进行身份验证,例如
const server = new ApolloServer({
typeDefs,
resolvers,
context: contextFunction,
introspection: true,
subscriptions: {
onConnect: (
connectionParams: IWebSocketConnectionParams,
webSocket: WebSocket,
connectionContext: ConnectionContext,
) => {
console.log('websocket connect');
console.log('connectionParams: ', connectionParams);
if (connectionParams.token) {
const token: string = validateToken(connectionParams.token);
const userConnector = new UserConnector<IMemoryDB>(memoryDB);
let user: IUser | undefined;
try {
const userType: UserType = UserType[token];
user = userConnector.findUserByUserType(userType);
} catch (error) {
throw error;
}
const context: ISubscriptionContext = {
// pubsub: postgresPubSub,
pubsub,
subscribeUser: user,
userConnector,
locationConnector: new LocationConnector<IMemoryDB>(memoryDB),
};
return context;
}
throw new Error('Missing auth token!');
},
onDisconnect: (webSocket: WebSocket, connectionContext: ConnectionContext) => {
console.log('websocket disconnect');
},
},
});
源代码:https://github.com/mrdulin/apollo-graphql-tutorial/tree/master/src/subscriptions