UI authentication improvements

This commit is contained in:
Zaid Abdulla committed 2019-10-24 17:43:24 -07:00
1 parent 77563fc85e
commit 8533ee7f2e
4 files changed
+44 -28

No files matched your search

+4
View File
@@ -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;
}
} }
+36 -24
View File
@@ -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)
+3 -3
View File
@@ -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
View File
@@ -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