Skip to content

Commit

Permalink
Mimick session ID for JWT auth
Browse files Browse the repository at this point in the history
The main point is to allow the tests to continue to use JWT auth,
while also testing session features such as missing messages for lost
connections
  • Loading branch information
goto-bus-stop committed Dec 6, 2024
1 parent 9670a5f commit 6a82126
Show file tree
Hide file tree
Showing 4 changed files with 42 additions and 20 deletions.
6 changes: 5 additions & 1 deletion src/auth/JWTStrategy.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,11 @@ class JWTStrategy extends Strategy {
throw new BannedError();
}

return this.success(user);
const info = 'sessionID' in value && typeof value.sessionID === 'string'
? { sessionID: value.sessionID }
: undefined;

return this.success(user, info);
}
}

Expand Down
50 changes: 32 additions & 18 deletions src/controllers/authenticate.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { randomUUID } from 'node:crypto';
import { promisify } from 'node:util';
import cookie from 'cookie';
import jwt from 'jsonwebtoken';
Expand Down Expand Up @@ -60,19 +61,21 @@ async function getAuthStrategies(req) {
}

/**
* @param {import('../HttpApi.js').HttpApi} api
* @param {import('../schema.js').User} user
* @param {string} sessionID
* @param {import('../types.js').Request} req
* @param {import('../schema').User} user
* @param {AuthenticateOptions & { session: 'cookie' | 'token' }} options
*/
async function refreshSession(api, user, sessionID, options) {
async function refreshSession(req, user, options) {
const { authRegistry } = req.uwaveHttp;
const sessionID = req.authInfo?.sessionID ?? req.sessionID;

const token = jwt.sign(
{ id: user.id },
{ id: user.id, sessionID: randomUUID() },
options.secret,
{ expiresIn: '31d' },
);

const socketToken = await api.authRegistry.createAuthToken(user, sessionID);
const socketToken = await authRegistry.createAuthToken(user, sessionID);

if (options.session === 'cookie') {
return { token: 'cookie', socketToken };
Expand Down Expand Up @@ -101,10 +104,11 @@ async function login(req) {
throw new BannedError();
}

const { token, socketToken } = await refreshSession(req.uwaveHttp, user, req.sessionID, {
...options,
session: sessionType,
});
const { token, socketToken } = await refreshSession(
req,
user,
{ ...options, session: sessionType },
);

return toItemResponse(serializeCurrentUser(user), {
meta: {
Expand Down Expand Up @@ -173,10 +177,7 @@ async function socialLoginCallback(service, req, res) {
window.close();
`;

await refreshSession(req.uwaveHttp, user, req.sessionID, {
...req.authOptions,
session: 'cookie',
});
await refreshSession(req, user, { ...req.authOptions, session: 'cookie' });

res.end(`
<!DOCTYPE html>
Expand Down Expand Up @@ -245,10 +246,23 @@ async function socialLoginFinish(service, req) {

Object.assign(user, updates);

const { token, socketToken } = await refreshSession(req.uwaveHttp, user, req.sessionID, {
...options,
session: sessionType,
});
const passportLogin = promisify(
/**
* @type {(
* user: Express.User,
* options: import('passport').LogInOptions,
* callback: (err: any) => void,
* ) => void}
*/
(req.login),
);
await passportLogin(user, { session: sessionType === 'cookie' });

const { token, socketToken } = await refreshSession(
req,
user,
{ ...options, session: sessionType },
);

return toItemResponse(user, {
meta: {
Expand Down
4 changes: 4 additions & 0 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ declare global {
authOptions?: AuthenticateOptions;
fullUrl: string;
}
interface AuthInfo {
/** A session ID provided through some other means than the actual session. */
sessionID?: string;
}
}
}

Expand Down
2 changes: 1 addition & 1 deletion test/utils/plugin.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ async function testPlugin(uw) {

async function createTestSessionToken(user) {
const token = jwt.sign(
{ id: user.id },
{ id: user.id, sessionID: randomUUID() },
uw.options.secret,
{ expiresIn: '1d' },
);
Expand Down

0 comments on commit 6a82126

Please sign in to comment.