-
Hi, I'm trying to convert an application based on Apollo server and Urql to your library. I have an issue finding a socket-ish alternative for passing an authorization header on each operation. So the way it works now is that I configured the urql client to add a token to every HTTP request: const client = createClient({
url,
requestPolicy: "cache-and-network",
fetchOptions() {
const currentUser = readStore<CurrentUser>("currentUser");
if (!currentUser) return {};
return { headers: { authorization: currentUser.token } };
},
.......
} Then in Apollo server's const apollo = new ApolloServer({
typeDefs,
resolvers,
async context({ req }): Promise<Context> {
const currentUser = await decodeAndFetch(req.headers.authorization);
currentUser && markOnline(currentUser._id);
return { ip: req.ip, currentUser };
}
}); I don't see how to rewrite that using Socket.io. I'm not a fan of adding an auth middleware, as the token decoding and user fetching would only happen once at the start. Do you have any advice ? Thank you. |
Beta Was this translation helpful? Give feedback.
Replies: 1 comment 1 reply
-
Hey there and sorry for the late reply - my GitHub notifications were messed up and I did not get any for this repository 😢 . As I understand you already made the choice that you want to use There are multiple ways of applying authentication. Authenticate before being permitted to even execute GraphQL operationsThe See the corresponding recipe in the README: Authenticate via handshake headersFrom what you are writing it seems like what you want to achieve is to process some headers used for doing the WebSocket upgrade for extracting session information. That also works! Server registerSocketIOGraphQLServer({
socketServer,
/* getParameter is invoked for each operation. */
getParameter: async ({ socket }) => {
const authHeader = socket.handshake.headers["authorization"];
return {
/* The parameters used for the operation execution. */
graphQLExecutionParameter: {
schema,
contextValue: {
socket,
},
},
};
},
}); On the client you can pass that token via the const socket = io({ extraHeaders: { Authorization: "Bearer fooo"} }); The drawback of that option is that the authorization header is always used from the initial handshake. Authenticate via custom extensionsWhat if it was possible to send some additional payload with every operation, that could be accessed within the class SocketIOGraphQLApolloLink extends ApolloLink {
private networkLayer: SocketIOGraphQLClient<FetchResult>;
constructor(networkLayer: SocketIOGraphQLClient<FetchResult>) {
super();
this.networkLayer = networkLayer;
}
public request(operation: Operation): Observable<FetchResult> | null {
return new Observable<FetchResult>((sink) =>
applyAsyncIterableIteratorToSink(
applyLiveQueryJSONPatch(
this.networkLayer.execute({
operationName: operation.operationName,
operation: print(operation.query),
variables: operation.variables,
extensions: {
auth: "fooooo"
}
})
),
sink
)
);
}
} I created #747 for this. Please let me know if that would solve your issue. |
Beta Was this translation helpful? Give feedback.
Hey there and sorry for the late reply - my GitHub notifications were messed up and I did not get any for this repository 😢 .
As I understand you already made the choice that you want to use
@n1ru4l/socket-io-graphql-server
as your GraphQL transportation layer.There are multiple ways of applying authentication.
Authenticate before being permitted to even execute GraphQL operations
The
isLazy
option forregisterSocketIOGraphQLServer
can be used to not automatically permit users to execute GraphQL operations. Instead you can apply your custom authentication logic (e.g. a handshake) and then allow the connected socket to execute GraphQL operations via thegraphQLServer.registerSocket(socket);
…