mirror of
https://github.com/shishantbiswas/bknd.git
synced 2026-03-16 12:37:20 +00:00
Add integration tests for auth, improve auth middleware and cookies handling
This commit is contained in:
@@ -114,12 +114,12 @@ export class AppAuth extends Module<typeof authConfigSchema> {
|
||||
identifier: string,
|
||||
profile: ProfileExchange
|
||||
): Promise<any> {
|
||||
console.log("***** AppAuth:resolveUser", {
|
||||
/*console.log("***** AppAuth:resolveUser", {
|
||||
action,
|
||||
strategy: strategy.getName(),
|
||||
identifier,
|
||||
profile
|
||||
});
|
||||
});*/
|
||||
if (!this.config.allow_register && action === "register") {
|
||||
throw new Exception("Registration is not allowed", 403);
|
||||
}
|
||||
@@ -140,12 +140,12 @@ export class AppAuth extends Module<typeof authConfigSchema> {
|
||||
}
|
||||
|
||||
private filterUserData(user: any) {
|
||||
console.log(
|
||||
/*console.log(
|
||||
"--filterUserData",
|
||||
user,
|
||||
this.config.jwt.fields,
|
||||
pick(user, this.config.jwt.fields)
|
||||
);
|
||||
);*/
|
||||
return pick(user, this.config.jwt.fields);
|
||||
}
|
||||
|
||||
@@ -171,18 +171,18 @@ export class AppAuth extends Module<typeof authConfigSchema> {
|
||||
if (!result.data) {
|
||||
throw new Exception("User not found", 404);
|
||||
}
|
||||
console.log("---login data", result.data, result);
|
||||
//console.log("---login data", result.data, result);
|
||||
|
||||
// compare strategy and identifier
|
||||
console.log("strategy comparison", result.data.strategy, strategy.getName());
|
||||
//console.log("strategy comparison", result.data.strategy, strategy.getName());
|
||||
if (result.data.strategy !== strategy.getName()) {
|
||||
console.log("!!! User registered with different strategy");
|
||||
//console.log("!!! User registered with different strategy");
|
||||
throw new Exception("User registered with different strategy");
|
||||
}
|
||||
|
||||
console.log("identifier comparison", result.data.strategy_value, identifier);
|
||||
//console.log("identifier comparison", result.data.strategy_value, identifier);
|
||||
if (result.data.strategy_value !== identifier) {
|
||||
console.log("!!! Invalid credentials");
|
||||
//console.log("!!! Invalid credentials");
|
||||
throw new Exception("Invalid credentials");
|
||||
}
|
||||
|
||||
|
||||
@@ -67,6 +67,9 @@ export const cookieConfig = Type.Partial(
|
||||
{ default: {}, additionalProperties: false }
|
||||
);
|
||||
|
||||
// @todo: maybe add a config to not allow cookie/api tokens to be used interchangably?
|
||||
// see auth.integration test for further details
|
||||
|
||||
export const jwtConfig = Type.Object(
|
||||
{
|
||||
// @todo: autogenerate a secret if not present. But it must be persisted from AppAuth
|
||||
@@ -139,7 +142,7 @@ export class Authenticator<Strategies extends Record<string, Strategy> = Record<
|
||||
}
|
||||
|
||||
// @todo: determine what to do exactly
|
||||
__setUserNull() {
|
||||
resetUser() {
|
||||
this._user = undefined;
|
||||
}
|
||||
|
||||
@@ -203,8 +206,8 @@ export class Authenticator<Strategies extends Record<string, Strategy> = Record<
|
||||
this._user = omit(payload, ["iat", "exp", "iss"]) as SafeUser;
|
||||
return true;
|
||||
} catch (e) {
|
||||
this._user = undefined;
|
||||
console.error(e);
|
||||
this.resetUser();
|
||||
//console.error(e);
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -222,10 +225,8 @@ export class Authenticator<Strategies extends Record<string, Strategy> = Record<
|
||||
private async getAuthCookie(c: Context): Promise<string | undefined> {
|
||||
try {
|
||||
const secret = this.config.jwt.secret;
|
||||
|
||||
const token = await getSignedCookie(c, secret, "auth");
|
||||
if (typeof token !== "string") {
|
||||
await deleteCookie(c, "auth", this.cookieOptions);
|
||||
return undefined;
|
||||
}
|
||||
|
||||
@@ -253,12 +254,17 @@ export class Authenticator<Strategies extends Record<string, Strategy> = Record<
|
||||
await setSignedCookie(c, "auth", token, secret, this.cookieOptions);
|
||||
}
|
||||
|
||||
private async deleteAuthCookie(c: Context) {
|
||||
await deleteCookie(c, "auth", this.cookieOptions);
|
||||
}
|
||||
|
||||
async logout(c: Context) {
|
||||
const cookie = await this.getAuthCookie(c);
|
||||
if (cookie) {
|
||||
await deleteCookie(c, "auth", this.cookieOptions);
|
||||
await this.deleteAuthCookie(c);
|
||||
await addFlashMessage(c, "Signed out", "info");
|
||||
}
|
||||
this.resetUser();
|
||||
}
|
||||
|
||||
// @todo: move this to a server helper
|
||||
|
||||
@@ -3,24 +3,6 @@ import type { Context } from "hono";
|
||||
import { createMiddleware } from "hono/factory";
|
||||
import type { ServerEnv } from "modules/Module";
|
||||
|
||||
async function resolveAuth(app: ServerEnv["Variables"]["app"], c: Context<ServerEnv>) {
|
||||
const resolved = c.get("auth_resolved") ?? false;
|
||||
if (resolved) {
|
||||
return;
|
||||
}
|
||||
if (!app.module.auth.enabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
const authenticator = app.module.auth.authenticator;
|
||||
const guard = app.modules.ctx().guard;
|
||||
|
||||
guard.setUserContext(await authenticator.resolveAuthFromRequest(c));
|
||||
|
||||
// renew cookie if applicable
|
||||
authenticator.requestCookieRefresh(c);
|
||||
}
|
||||
|
||||
export function shouldSkipAuth(req: Request) {
|
||||
const skip = new URL(req.url).pathname.startsWith(config.server.assets_path);
|
||||
if (skip) {
|
||||
@@ -30,22 +12,46 @@ export function shouldSkipAuth(req: Request) {
|
||||
}
|
||||
|
||||
export const auth = createMiddleware<ServerEnv>(async (c, next) => {
|
||||
if (!shouldSkipAuth(c.req.raw)) {
|
||||
// make sure to only register once
|
||||
if (c.get("auth_registered")) {
|
||||
return;
|
||||
}
|
||||
// make sure to only register once
|
||||
if (c.get("auth_registered")) {
|
||||
throw new Error("auth middleware already registered");
|
||||
}
|
||||
c.set("auth_registered", true);
|
||||
|
||||
await resolveAuth(c.get("app"), c);
|
||||
c.set("auth_registered", true);
|
||||
const skipped = shouldSkipAuth(c.req.raw);
|
||||
const app = c.get("app");
|
||||
const guard = app.modules.ctx().guard;
|
||||
const authenticator = app.module.auth.authenticator;
|
||||
|
||||
if (!skipped) {
|
||||
const resolved = c.get("auth_resolved");
|
||||
if (!resolved) {
|
||||
if (!app.module.auth.enabled) {
|
||||
guard.setUserContext(undefined);
|
||||
} else {
|
||||
guard.setUserContext(await authenticator.resolveAuthFromRequest(c));
|
||||
|
||||
// renew cookie if applicable
|
||||
authenticator.requestCookieRefresh(c);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await next();
|
||||
|
||||
// release
|
||||
guard.setUserContext(undefined);
|
||||
authenticator.resetUser();
|
||||
c.set("auth_resolved", false);
|
||||
});
|
||||
|
||||
export const permission = (...permissions: Permission[]) =>
|
||||
createMiddleware<ServerEnv>(async (c, next) => {
|
||||
if (!shouldSkipAuth) {
|
||||
if (!c.get("auth_registered")) {
|
||||
throw new Error("auth middleware not registered, cannot check permissions");
|
||||
}
|
||||
|
||||
if (!shouldSkipAuth(c.req.raw)) {
|
||||
const app = c.get("app");
|
||||
if (app) {
|
||||
const p = Array.isArray(permissions) ? permissions : [permissions];
|
||||
|
||||
Reference in New Issue
Block a user