UI authentication improvements
This commit is contained in:
1 parent
77563fc85e
commit
8533ee7f2e
4 files changed
+44
-28
No files matched your search
@@ -141,4 +141,8 @@ export default class Authorizer {
|
|||||||
this.validatorCache.set(resource, validator);
|
this.validatorCache.set(resource, validator);
|
||||||
return validator;
|
return validator;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public getPermissionSets(): PermissionSet[] {
|
||||||
|
return this.permissionSets;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -31,7 +31,7 @@ import Authorizer from "./common/authorizer";
|
|||||||
import * as logger from "./logger";
|
import * as logger from "./logger";
|
||||||
import * as localCache from "./local-cache";
|
import * as localCache from "./local-cache";
|
||||||
import { PermissionSet } from "./types";
|
import { PermissionSet } from "./types";
|
||||||
import { authSimple } from "./ui/api-functions";
|
import { authLocal } from "./ui/api-functions";
|
||||||
import * as init from "./init";
|
import * as init from "./init";
|
||||||
import { version as VERSION } from "../package.json";
|
import { version as VERSION } from "../package.json";
|
||||||
|
|
||||||
@@ -47,16 +47,6 @@ const router = new Router();
|
|||||||
const JWT_SECRET = "" + config.get("UI_JWT_SECRET");
|
const JWT_SECRET = "" + config.get("UI_JWT_SECRET");
|
||||||
const JWT_COOKIE = "genieacs-ui-jwt";
|
const JWT_COOKIE = "genieacs-ui-jwt";
|
||||||
|
|
||||||
function getPermissionSets(ctx): PermissionSet[] {
|
|
||||||
const allPermissions = localCache.getPermissions(ctx.state.configSnapshot);
|
|
||||||
const users = localCache.getUsers(ctx.state.configSnapshot);
|
|
||||||
const user = users[ctx.state.user.username];
|
|
||||||
const permissionSets = user.roles.map(role =>
|
|
||||||
Object.values(allPermissions[role] || {})
|
|
||||||
);
|
|
||||||
return permissionSets;
|
|
||||||
}
|
|
||||||
|
|
||||||
koa.on("error", async err => {
|
koa.on("error", async err => {
|
||||||
throw err;
|
throw err;
|
||||||
});
|
});
|
||||||
@@ -73,14 +63,39 @@ koa.use(
|
|||||||
koaJwt({
|
koaJwt({
|
||||||
secret: JWT_SECRET,
|
secret: JWT_SECRET,
|
||||||
passthrough: true,
|
passthrough: true,
|
||||||
cookie: JWT_COOKIE
|
cookie: JWT_COOKIE,
|
||||||
|
isRevoked: async (ctx, token) => {
|
||||||
|
if (token["authMethod"] === "local") {
|
||||||
|
return !localCache.getUsers(ctx.state.configSnapshot)[
|
||||||
|
token["username"]
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
})
|
})
|
||||||
);
|
);
|
||||||
|
|
||||||
koa.use(async (ctx, next) => {
|
koa.use(async (ctx, next) => {
|
||||||
if (ctx.state.user && ctx.state.user.username)
|
const permissionSets: PermissionSet[] = [];
|
||||||
ctx.state.authorizer = new Authorizer(getPermissionSets(ctx));
|
|
||||||
else ctx.state.authorizer = new Authorizer([]);
|
if (ctx.state.user && ctx.state.user.username) {
|
||||||
|
const allPermissions = localCache.getPermissions(ctx.state.configSnapshot);
|
||||||
|
|
||||||
|
let user;
|
||||||
|
if (ctx.state.user.authMethod === "local") {
|
||||||
|
user = localCache.getUsers(ctx.state.configSnapshot)[
|
||||||
|
ctx.state.user.username
|
||||||
|
];
|
||||||
|
} else {
|
||||||
|
throw new Error("Invalid auth method");
|
||||||
|
}
|
||||||
|
|
||||||
|
for (const role of (user.roles || []).sort())
|
||||||
|
permissionSets.push(Object.values(allPermissions[role] || {}));
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.state.authorizer = new Authorizer(permissionSets);
|
||||||
|
|
||||||
return next();
|
return next();
|
||||||
});
|
});
|
||||||
@@ -103,9 +118,9 @@ router.post("/login", async ctx => {
|
|||||||
method: null
|
method: null
|
||||||
};
|
};
|
||||||
|
|
||||||
function success(method): void {
|
function success(authMethod): void {
|
||||||
log.method = method;
|
log.method = authMethod;
|
||||||
const token = jwt.sign({ username }, JWT_SECRET);
|
const token = jwt.sign({ username, authMethod }, JWT_SECRET);
|
||||||
ctx.cookies.set(JWT_COOKIE, token, { sameSite: "lax" });
|
ctx.cookies.set(JWT_COOKIE, token, { sameSite: "lax" });
|
||||||
ctx.body = JSON.stringify(token);
|
ctx.body = JSON.stringify(token);
|
||||||
logger.accessInfo(log);
|
logger.accessInfo(log);
|
||||||
@@ -118,9 +133,8 @@ router.post("/login", async ctx => {
|
|||||||
logger.accessWarn(log);
|
logger.accessWarn(log);
|
||||||
}
|
}
|
||||||
|
|
||||||
const roles = await authSimple(ctx.state.configSnapshot, username, password);
|
if (await authLocal(ctx.state.configSnapshot, username, password))
|
||||||
|
return void success("local");
|
||||||
if (roles) return void success("simple");
|
|
||||||
|
|
||||||
failure();
|
failure();
|
||||||
});
|
});
|
||||||
@@ -192,9 +206,7 @@ router.post("/init", async ctx => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
router.get("/", async ctx => {
|
router.get("/", async ctx => {
|
||||||
let permissionSets = [];
|
const permissionSets = ctx.state.authorizer.getPermissionSets();
|
||||||
if (ctx.state.user && ctx.state.user.username)
|
|
||||||
permissionSets = getPermissionSets(ctx);
|
|
||||||
|
|
||||||
let wizard = "";
|
let wizard = "";
|
||||||
if (!Object.keys(localCache.getUsers(ctx.state.configSnapshot)).length)
|
if (!Object.keys(localCache.getUsers(ctx.state.configSnapshot)).length)
|
||||||
|
|||||||
@@ -168,15 +168,15 @@ export async function putResource(resource, id, data): Promise<void> {
|
|||||||
await del("presets_hash");
|
await del("presets_hash");
|
||||||
}
|
}
|
||||||
|
|
||||||
export function authSimple(snapshot, username, password): Promise<string[]> {
|
export function authLocal(snapshot, username, password): Promise<boolean> {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const users = getUsers(snapshot);
|
const users = getUsers(snapshot);
|
||||||
const user = users[username];
|
const user = users[username];
|
||||||
if (!user || !user.password) return void resolve(null);
|
if (!user || !user.password) return void resolve(null);
|
||||||
hashPassword(password, user.salt)
|
hashPassword(password, user.salt)
|
||||||
.then(hash => {
|
.then(hash => {
|
||||||
if (hash === user.password) resolve(user.roles);
|
if (hash === user.password) resolve(true);
|
||||||
else resolve(null);
|
else resolve(false);
|
||||||
})
|
})
|
||||||
.catch(reject);
|
.catch(reject);
|
||||||
});
|
});
|
||||||
|
|||||||
+1
-1
@@ -577,7 +577,7 @@ router.put("/users/:id/password", async (ctx, next) => {
|
|||||||
if (!ctx.state.user) {
|
if (!ctx.state.user) {
|
||||||
// User not logged in
|
// User not logged in
|
||||||
if (
|
if (
|
||||||
!(await apiFunctions.authSimple(
|
!(await apiFunctions.authLocal(
|
||||||
ctx.state.configSnapshot,
|
ctx.state.configSnapshot,
|
||||||
username,
|
username,
|
||||||
ctx.request.body.authPassword
|
ctx.request.body.authPassword
|
||||||
|
|||||||
Reference in new issue
Block a user