100 lines
2.7 KiB
TypeScript
100 lines
2.7 KiB
TypeScript
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: any = Hoek.applyToDefaults(jwtDefaults, options);
|
|
const key = settings.jwkeysB64.map((k) => jwkToHapiAuthJwt2(k));
|
|
|
|
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],
|
|
validate: async (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."
|
|
);
|
|
}
|
|
};
|
|
*/
|