Since next-auth doesn't use JWT anymore, remove the nextauth-jwt plugin

..and replace it with the Auth Bearer plugin.
This commit is contained in:
Abel Luck 2023-06-06 13:21:09 +00:00
parent 24d52eef3d
commit bdad5f551c
7 changed files with 52 additions and 112 deletions

View file

@ -27,6 +27,7 @@
"fluent-ffmpeg": "^2.1.2",
"graphile-migrate": "^1.4.1",
"graphile-worker": "^0.13.0",
"hapi-auth-bearer-token": "^8.0.0",
"hapi-auth-jwt2": "^10.4.0",
"hapi-postgraphile": "^0.11.0",
"hapi-swagger": "^16.0.1",

View file

@ -0,0 +1,22 @@
import type * as Hapi from "@hapi/hapi";
import AuthBearer from "hapi-auth-bearer-token";
import { IAppConfig } from "@digiresilience/metamigo-config";
import { IMetamigoRepositories } from "@digiresilience/metamigo-common";
export const registerAuthBearer = async (
server: Hapi.Server,
config: IAppConfig
): Promise<void> => {
await server.register(AuthBearer);
server.auth.strategy("session-id-bearer-token", "bearer-access-token", {
allowQueryToken: false,
validate: async (request: Hapi.Request, token: string, h: Hapi.ResponseToolkit) => {
const repos = request.db() as IMetamigoRepositories;
const session = await repos.sessions.findBy({ sessionToken: token });
const isValid = !!session;
const credentials = { token };
return { isValid, credentials };
},
});
};

View file

@ -7,8 +7,8 @@ import type { IAppConfig } from "../../config";
import { dbInitOptions, IRepositories } from "@digiresilience/metamigo-db";
import { registerNextAuth } from "./hapi-nextauth.js";
import { registerSwagger } from "./swagger.js";
import { registerNextAuthJwt } from "./nextauth-jwt.js";
import { registerCloudflareAccessJwt } from "./cloudflare-jwt.js";
import { registerAuthBearer } from "./auth-bearer.js";
import pg from "pg-promise/typescript/pg-subset";
export const register = async (
@ -34,6 +34,6 @@ export const register = async (
await registerNextAuth(server, config);
await registerSwagger(server);
await registerNextAuthJwt(server, config);
await registerCloudflareAccessJwt(server, config);
await registerAuthBearer(server, config);
};

View file

@ -1,104 +0,0 @@
import * as Hoek from "@hapi/hoek";
import * as Hapi from "@hapi/hapi";
import type { IAppConfig } from "../../config";
// hapi-auth-jwt2 expects the key to be a raw key
const jwkToHapiAuthJwt2 = (jwkString) => {
try {
const jwk = JSON.parse(jwkString);
return Buffer.from(jwk.k, "base64");
} catch {
throw new Error(
"Failed to parse key for JWT verification. This is probably an application configuration error."
);
}
};
const jwtDefaults = {
jwkeysB64: undefined,
validate: undefined,
strategyName: "nextauth-jwt",
};
const jwtRegister = async (server: Hapi.Server, options): Promise<void> => {
server.dependency(["hapi-auth-jwt2"]);
const settings = Hoek.applyToDefaults(jwtDefaults, options);
const key = settings.jwkeysB64.map((k) => jwkToHapiAuthJwt2(k));
if (!settings.strategyName) {
throw new Error("Missing strategy name in nextauth-jwt pluginsettings!");
}
server.auth.strategy(settings.strategyName, "jwt", {
key,
cookieKey: false,
urlKey: false,
validate: settings.validate,
});
};
export const registerNextAuthJwt = async (
server: Hapi.Server,
config: IAppConfig
): Promise<void> => {
if (config.nextAuth.signingKey) {
await server.register({
plugin: {
name: "nextauth-jwt",
version: "0.0.2",
register: jwtRegister,
},
options: {
jwkeysB64: [config.nextAuth.signingKey],
async validate(decoded, request: Hapi.Request) {
const { email, name, role } = decoded;
const user = await request.db().users.findBy({ email });
if (!config.isProd) {
server.logger.info(
{
email,
name,
role,
},
"nextauth-jwt authorizing request"
);
// server.logger.info({ user }, "nextauth-jwt user result");
}
return {
isValid: Boolean(user && user.isActive),
// this credentials object is made available in every request
// at `request.auth.credentials`
credentials: { email, name, role },
};
},
},
});
} else if (config.isProd) {
throw new Error("Missing nextauth.signingKey configuration value.");
} else {
server.log(
["warn"],
"Missing nextauth.signingKey configuration value. Authentication of nextauth endpoints disabled!"
);
}
};
// @hapi/jwt expects the key in its own format
/* UNUSED
const _jwkToHapiJwt = (jwkString) => {
try {
const jwk = JSON.parse(jwkString);
const rawKey = Buffer.from(jwk.k, "base64");
return {
key: rawKey,
algorithms: [jwk.alg],
kid: jwk.kid,
};
} catch {
throw new Error(
"Failed to parse key for JWT verification. This is probably an application configuration error."
);
}
};
*/

View file

@ -4,7 +4,7 @@ import Toys from "@hapipal/toys";
export const withDefaults = Toys.withRouteDefaults({
options: {
cors: true,
auth: "nextauth-jwt",
auth: "session-id-bearer-token",
validate: {
failAction: Metamigo.validatingFailAction,
},

View file

@ -50,11 +50,10 @@ const build = async (config: IAppConfig): Promise<Glue.Manifest> => {
route: {
path: "/graphql",
options: {
auth: false,
// auth: {
// strategies: ["nextauth-jwt"],
// mode: "optional",
// },
auth: {
strategies: ["session-id-bearer-token"],
mode: "optional",
},
},
},
pgConfig: config.postgraphile.authConnection,

22
package-lock.json generated
View file

@ -137,6 +137,7 @@
"fluent-ffmpeg": "^2.1.2",
"graphile-migrate": "^1.4.1",
"graphile-worker": "^0.13.0",
"hapi-auth-bearer-token": "^8.0.0",
"hapi-auth-jwt2": "^10.4.0",
"hapi-postgraphile": "^0.11.0",
"hapi-swagger": "^16.0.1",
@ -11597,6 +11598,27 @@
"topo": "3.x.x"
}
},
"node_modules/hapi-auth-bearer-token": {
"version": "8.0.0",
"resolved": "https://registry.npmjs.org/hapi-auth-bearer-token/-/hapi-auth-bearer-token-8.0.0.tgz",
"integrity": "sha512-1YeUlwhhky8tnNx9bOQPB/TvsEwbgcYwAZ6DAvHlK+tHRiMbXU+2HNE8qpRia+oj21W2K/omaxyZIB5dOzTPoA==",
"dependencies": {
"@hapi/hoek": "^9.0.0"
},
"engines": {
"node": ">=8.0.0"
},
"peerDependencies": {
"@hapi/boom": ">=7.x.x",
"@hapi/hapi": ">=19.x.x",
"joi": ">=17.x.x"
}
},
"node_modules/hapi-auth-bearer-token/node_modules/@hapi/hoek": {
"version": "9.3.0",
"resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz",
"integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ=="
},
"node_modules/hapi-auth-jwt2": {
"version": "10.4.0",
"resolved": "https://registry.npmjs.org/hapi-auth-jwt2/-/hapi-auth-jwt2-10.4.0.tgz",