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:
parent
24d52eef3d
commit
bdad5f551c
7 changed files with 52 additions and 112 deletions
22
apps/metamigo-api/src/app/plugins/auth-bearer.ts
Normal file
22
apps/metamigo-api/src/app/plugins/auth-bearer.ts
Normal 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 };
|
||||
},
|
||||
});
|
||||
};
|
||||
|
|
@ -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);
|
||||
};
|
||||
|
|
|
|||
|
|
@ -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."
|
||||
);
|
||||
}
|
||||
};
|
||||
*/
|
||||
|
|
@ -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,
|
||||
},
|
||||
|
|
|
|||
|
|
@ -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,
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue