welp
welp2y ago

Initial websockets getToken() returns null: next-auth + websockets :)

Hello! So the way I am trying to authenticate websockets is like this:
import { getToken } from "next-auth/jwt";

type Incoming = IncomingMessage & {
cookies: Partial<{ [key: string]: string }>;
};

export const createTRPCContext = async (
opts:
| CreateNextContextOptions
| NodeHTTPCreateContextFnOptions<IncomingMessage, ws>
) => {
const { req } = opts;
const token = await getToken({ req: req as Incoming });

if (token) {
return { session: { user: token } };
}

return { session: null };
};
import { getToken } from "next-auth/jwt";

type Incoming = IncomingMessage & {
cookies: Partial<{ [key: string]: string }>;
};

export const createTRPCContext = async (
opts:
| CreateNextContextOptions
| NodeHTTPCreateContextFnOptions<IncomingMessage, ws>
) => {
const { req } = opts;
const token = await getToken({ req: req as Incoming });

if (token) {
return { session: { user: token } };
}

return { session: null };
};
And it works except for the initial requests. I wouldn't mind this (maybe I would since needless errors), but my problem is trying to use subscriptions: it just will prompt an error on the initial request and I can't think of a way to retry (retrying works for everything else). I would like to solve this initial null JWT token request problem as that would make everything work very nicely but I wouldn't mind making the subscriptions work either. The way I am subscribing in my react component:
api.messages.whoIsTyping.useSubscription(
{
slug,
},
{
onData(data) {
setCurrentlyTyping(data);
},
onError(err) {
console.error("Subscription error:", err);
},
}
);
api.messages.whoIsTyping.useSubscription(
{
slug,
},
{
onData(data) {
setCurrentlyTyping(data);
},
onError(err) {
console.error("Subscription error:", err);
},
}
);
I would really appreciate some commentary/insight! Thank you for your time.
1 Reply
welp
welpOP2y ago
I also tried with handling auth with const session = await getServerSession(req as any, res as any, authOptions); however I run into the following error: res.getHeader is not a function Eventually I came with this which doesn't resolve anything as the token comes up null:
export const createTRPCContext = async (
opts:
| CreateNextContextOptions
| NodeHTTPCreateContextFnOptions<IncomingMessage, ws>
// eslint-disable-next-line @typescript-eslint/require-await
) => {
const { req, res } = opts;
if (typeof (res as any).getHeaders !== "function") {
const token = await getToken({
req: req as any,
secret: process.env.NEXTAUTH_SECRET,
});

if (token) {
// console.log("Got JWT token:", token);
return { session: { user: token } };
}

console.log("null token");
return { session: null };
}

const session = await getServerSession(req as any, res as any, authOptions);

if (session) {
return { session };
}
console.log("null session");
return { session: null };
};
export const createTRPCContext = async (
opts:
| CreateNextContextOptions
| NodeHTTPCreateContextFnOptions<IncomingMessage, ws>
// eslint-disable-next-line @typescript-eslint/require-await
) => {
const { req, res } = opts;
if (typeof (res as any).getHeaders !== "function") {
const token = await getToken({
req: req as any,
secret: process.env.NEXTAUTH_SECRET,
});

if (token) {
// console.log("Got JWT token:", token);
return { session: { user: token } };
}

console.log("null token");
return { session: null };
}

const session = await getServerSession(req as any, res as any, authOptions);

if (session) {
return { session };
}
console.log("null session");
return { session: null };
};
I got it working! I still get null sessions but now I do eventually get the session needed for a subscription to be possible! Working code is the following:
export const createTRPCContext = async (
opts:
| CreateNextContextOptions
| NodeHTTPCreateContextFnOptions<IncomingMessage, ws>
// eslint-disable-next-line @typescript-eslint/require-await
) => {
const { req, res } = opts;
if (typeof (res as any).getHeaders !== "function") {
const token = await getToken({
req: req as any,
secret: process.env.NEXTAUTH_SECRET,
});

if (token) {
// console.log("Got JWT token:", token);
return { session: { user: token } };
}

console.log("null token");

const session = await getSession(opts);

if (session) {
return { session };
}

console.log("null getSession");

return { session: null };
}

const session = await getServerSession(req as any, res as any, authOptions);

if (session) {
return { session };
}
console.log("null session");
return { session: null };
};
export const createTRPCContext = async (
opts:
| CreateNextContextOptions
| NodeHTTPCreateContextFnOptions<IncomingMessage, ws>
// eslint-disable-next-line @typescript-eslint/require-await
) => {
const { req, res } = opts;
if (typeof (res as any).getHeaders !== "function") {
const token = await getToken({
req: req as any,
secret: process.env.NEXTAUTH_SECRET,
});

if (token) {
// console.log("Got JWT token:", token);
return { session: { user: token } };
}

console.log("null token");

const session = await getSession(opts);

if (session) {
return { session };
}

console.log("null getSession");

return { session: null };
}

const session = await getServerSession(req as any, res as any, authOptions);

if (session) {
return { session };
}
console.log("null session");
return { session: null };
};