mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-17 12:56:05 +00:00
added onBeforeUpdate listener + auto create a secret on auth enable
This commit is contained in:
@@ -1,16 +1,9 @@
|
||||
import { type AuthAction, Authenticator, type ProfileExchange, Role, type Strategy } from "auth";
|
||||
import { Exception } from "core";
|
||||
import { transformObject } from "core/utils";
|
||||
import {
|
||||
type Entity,
|
||||
EntityIndex,
|
||||
type EntityManager,
|
||||
EnumField,
|
||||
type Field,
|
||||
type Mutator
|
||||
} from "data";
|
||||
import { type Static, secureRandomString, transformObject } from "core/utils";
|
||||
import { type Entity, EntityIndex, type EntityManager } from "data";
|
||||
import { type FieldSchema, entity, enumm, make, text } from "data/prototype";
|
||||
import { cloneDeep, mergeWith, omit, pick } from "lodash-es";
|
||||
import { pick } from "lodash-es";
|
||||
import { Module } from "modules/Module";
|
||||
import { AuthController } from "./api/AuthController";
|
||||
import { type AppAuthSchema, STRATEGIES, authConfigSchema } from "./auth-schema";
|
||||
@@ -22,10 +15,25 @@ declare global {
|
||||
}
|
||||
}
|
||||
|
||||
type AuthSchema = Static<typeof authConfigSchema>;
|
||||
|
||||
export class AppAuth extends Module<typeof authConfigSchema> {
|
||||
private _authenticator?: Authenticator;
|
||||
cache: Record<string, any> = {};
|
||||
|
||||
override async onBeforeUpdate(from: AuthSchema, to: AuthSchema) {
|
||||
const defaultSecret = authConfigSchema.properties.jwt.properties.secret.default;
|
||||
|
||||
if (!from.enabled && to.enabled) {
|
||||
if (to.jwt.secret === defaultSecret) {
|
||||
console.warn("No JWT secret provided, generating a random one");
|
||||
to.jwt.secret = secureRandomString(64);
|
||||
}
|
||||
}
|
||||
|
||||
return to;
|
||||
}
|
||||
|
||||
override async build() {
|
||||
if (!this.config.enabled) {
|
||||
this.setBuilt();
|
||||
@@ -46,14 +54,15 @@ export class AppAuth extends Module<typeof authConfigSchema> {
|
||||
return new STRATEGIES[strategy.type].cls(strategy.config as any);
|
||||
} catch (e) {
|
||||
throw new Error(
|
||||
`Could not build strategy ${String(name)} with config ${JSON.stringify(strategy.config)}`
|
||||
`Could not build strategy ${String(
|
||||
name
|
||||
)} with config ${JSON.stringify(strategy.config)}`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
const { fields, ...jwt } = this.config.jwt;
|
||||
this._authenticator = new Authenticator(strategies, this.resolveUser.bind(this), {
|
||||
jwt
|
||||
jwt: this.config.jwt
|
||||
});
|
||||
|
||||
this.registerEntities();
|
||||
@@ -124,7 +133,11 @@ export class AppAuth extends Module<typeof authConfigSchema> {
|
||||
}
|
||||
|
||||
private async login(strategy: Strategy, identifier: string, profile: ProfileExchange) {
|
||||
console.log("--- trying to login", { strategy: strategy.getName(), identifier, profile });
|
||||
/*console.log("--- trying to login", {
|
||||
strategy: strategy.getName(),
|
||||
identifier,
|
||||
profile
|
||||
});*/
|
||||
if (!("email" in profile)) {
|
||||
throw new Exception("Profile must have email");
|
||||
}
|
||||
@@ -263,17 +276,9 @@ export class AppAuth extends Module<typeof authConfigSchema> {
|
||||
return this.configDefault;
|
||||
}
|
||||
|
||||
const obj = {
|
||||
return {
|
||||
...this.config,
|
||||
...this.authenticator.toJSON(secrets)
|
||||
};
|
||||
|
||||
return {
|
||||
...obj,
|
||||
jwt: {
|
||||
...obj.jwt,
|
||||
fields: this.config.jwt.fields
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,15 +51,7 @@ export const authConfigSchema = Type.Object(
|
||||
enabled: Type.Boolean({ default: false }),
|
||||
basepath: Type.String({ default: "/api/auth" }),
|
||||
entity_name: Type.String({ default: "users" }),
|
||||
jwt: Type.Composite(
|
||||
[
|
||||
jwtConfig,
|
||||
Type.Object({
|
||||
fields: Type.Array(Type.String(), { default: ["id", "email", "role"] })
|
||||
})
|
||||
],
|
||||
{ default: {}, additionalProperties: false }
|
||||
),
|
||||
jwt: jwtConfig,
|
||||
strategies: Type.Optional(
|
||||
StringRecord(strategiesSchema, {
|
||||
title: "Strategies",
|
||||
|
||||
@@ -41,10 +41,11 @@ export interface UserPool<Fields = "id" | "email" | "username"> {
|
||||
export const jwtConfig = Type.Object(
|
||||
{
|
||||
// @todo: autogenerate a secret if not present. But it must be persisted from AppAuth
|
||||
secret: Type.String({ default: "secret" }),
|
||||
secret: Type.String({ default: "" }),
|
||||
alg: Type.Optional(Type.String({ enum: ["HS256"], default: "HS256" })),
|
||||
expiresIn: Type.Optional(Type.String()),
|
||||
issuer: Type.Optional(Type.String())
|
||||
issuer: Type.Optional(Type.String()),
|
||||
fields: Type.Array(Type.String(), { default: ["id", "email", "role"] })
|
||||
},
|
||||
{
|
||||
default: {},
|
||||
@@ -74,11 +75,6 @@ export class Authenticator<Strategies extends Record<string, Strategy> = Record<
|
||||
this.userResolver = userResolver ?? (async (a, s, i, p) => p as any);
|
||||
this.strategies = strategies as Strategies;
|
||||
this.config = parse(authenticatorConfig, config ?? {});
|
||||
|
||||
/*const secret = String(this.config.jwt.secret);
|
||||
if (secret === "secret" || secret.length === 0) {
|
||||
this.config.jwt.secret = randomString(64, true);
|
||||
}*/
|
||||
}
|
||||
|
||||
async resolve(
|
||||
|
||||
Reference in New Issue
Block a user