forked from engineering/cloudservices
Change Bearer methods (verify to encrypt)
parent
ba214c5335
commit
b0fe33f98a
|
@ -1,15 +1,23 @@
|
||||||
import crypto from 'crypto';
|
import crypto from 'crypto';
|
||||||
import { Request } from 'express';
|
import { Request } from 'express';
|
||||||
import { Client } from '..';
|
import { Client } from '..';
|
||||||
|
import { AccountInterface } from '../models';
|
||||||
|
|
||||||
export default class Security {
|
export default class Security {
|
||||||
public client: Client;
|
public client: Client;
|
||||||
|
|
||||||
public keyPair: { publicKey: string, privateKey: string };
|
private keyBase: { key: string, iv: string };
|
||||||
|
|
||||||
constructor(client: Client) {
|
constructor(client: Client) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.keyPair = require(`${process.cwd()}/keys.json`);
|
this.keyBase = require(`${process.cwd()}/keys.json`);
|
||||||
|
}
|
||||||
|
|
||||||
|
get keys() {
|
||||||
|
return {
|
||||||
|
key: Buffer.from(this.keyBase.key, 'base64'),
|
||||||
|
iv: Buffer.from(this.keyBase.iv, 'base64'),
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -19,26 +27,22 @@ export default class Security {
|
||||||
public async createBearer(_id: string): Promise<string> {
|
public async createBearer(_id: string): Promise<string> {
|
||||||
const account = await this.client.db.Account.findOne({ _id });
|
const account = await this.client.db.Account.findOne({ _id });
|
||||||
if (!account) throw new Error(`Account [${_id}] cannot be found.`);
|
if (!account) throw new Error(`Account [${_id}] cannot be found.`);
|
||||||
const bearer = crypto.randomBytes(12).toString('base64');
|
const cipher = crypto.createCipheriv('aes-256-gcm', this.keys.key, this.keys.iv);
|
||||||
const sign = crypto.createSign('sha3-224');
|
let encrypted = cipher.update(JSON.stringify(account), 'utf8', 'base64');
|
||||||
sign.update(bearer);
|
encrypted += cipher.final('base64');
|
||||||
sign.end();
|
return encrypted;
|
||||||
const signature = sign.sign(this.keyPair.privateKey, 'hex');
|
|
||||||
await account.updateOne({ bearerSignature: signature });
|
|
||||||
return bearer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public async checkBearer(_id: string, bearer: string): Promise<boolean> {
|
public async checkBearer(bearer: string): Promise<null | AccountInterface> {
|
||||||
const account = await this.client.db.Account.findOne({ _id });
|
const decipher = crypto.createDecipheriv('aes-256-gcm', this.keys.key, this.keys.iv);
|
||||||
if (!account) return false;
|
|
||||||
if (!account.bearerSignature) return false;
|
|
||||||
const verify = crypto.createVerify('sha3-224');
|
|
||||||
verify.update(bearer);
|
|
||||||
verify.end();
|
|
||||||
try {
|
try {
|
||||||
return verify.verify(this.keyPair.publicKey, account.bearerSignature, 'hex');
|
let decrypted = decipher.update(bearer, 'base64', 'utf8');
|
||||||
|
decrypted += decipher.final('utf8');
|
||||||
|
const json = JSON.parse(decrypted);
|
||||||
|
const account = await this.client.db.Account.findOne({ username: json.username });
|
||||||
|
return account;
|
||||||
} catch {
|
} catch {
|
||||||
return false;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
import express from 'express';
|
||||||
|
import { AccountInterface } from '../models';
|
||||||
|
|
||||||
|
export interface Req extends express.Request {
|
||||||
|
account: AccountInterface
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
/* eslint-disable consistent-return */
|
/* eslint-disable consistent-return */
|
||||||
import { Server } from '..';
|
import { Server } from '..';
|
||||||
import { Route } from '../../class';
|
import { Route } from '../../class';
|
||||||
|
import { Req } from '../interfaces';
|
||||||
|
|
||||||
export default class Account extends Route {
|
export default class Account extends Route {
|
||||||
constructor(server: Server) {
|
constructor(server: Server) {
|
||||||
|
@ -9,26 +10,34 @@ export default class Account extends Route {
|
||||||
|
|
||||||
public bind() {
|
public bind() {
|
||||||
this.router.use(async (req, res, next) => {
|
this.router.use(async (req, res, next) => {
|
||||||
const account = await this.server.client.db.Account.findOne({ username: req.query.username });
|
const account = await this.server.security.checkBearer(this.server.security.extractBearer(req));
|
||||||
if (!account) return res.status(401).json({ code: this.constants.codes.ACCOUNT_NOT_FOUND, message: 'UNAUTHORIZED' });
|
if (!account) return res.status(401).json({ code: this.constants.codes.UNAUTHORIZED, message: 'BEARER_TOKEN_INVALID' });
|
||||||
// eslint-disable-next-line no-underscore-dangle
|
Object.defineProperty(req, 'account', { value: account, writable: true, enumerable: true, configurable: true });
|
||||||
const authResult = await this.server.security.checkBearer(account._id, this.server.security.extractBearer(req));
|
|
||||||
if (!authResult) return res.status(401).json({ code: this.constants.codes.UNAUTHORIZED, message: 'UNAUTHORIZED' });
|
|
||||||
next();
|
next();
|
||||||
});
|
});
|
||||||
|
|
||||||
this.router.get('/', async (req, res) => {
|
this.router.get('/', async (req: Req, res) => {
|
||||||
const account = await this.server.client.db.Account.findOne({ username: req.query.username });
|
|
||||||
const acc: any = {};
|
const acc: any = {};
|
||||||
acc.username = account.username;
|
acc.username = req.account.username;
|
||||||
acc.userID = account.userID;
|
acc.userID = req.account.userID;
|
||||||
acc.email = account.emailAddress;
|
acc.email = req.account.emailAddress;
|
||||||
acc.locked = account.locked;
|
acc.locked = req.account.locked;
|
||||||
acc.root = account.root;
|
acc.root = req.account.root;
|
||||||
acc.createdAt = account.createdAt;
|
acc.createdAt = req.account.createdAt;
|
||||||
acc.createdBy = account.createdBy;
|
acc.createdBy = req.account.createdBy;
|
||||||
acc.permissions = account.permissions;
|
acc.permissions = req.account.permissions;
|
||||||
res.status(200).json({ code: this.constants.codes.SUCCESS, message: acc });
|
res.status(200).json({ code: this.constants.codes.SUCCESS, message: acc });
|
||||||
});
|
});
|
||||||
|
|
||||||
|
this.router.get('/moderations/:id', async (req: Req, res) => {
|
||||||
|
const moderations = await this.server.client.db.Moderation.find({ username: req.account.username });
|
||||||
|
if (!moderations.length) res.sendStatus(204);
|
||||||
|
if (req.params.id) {
|
||||||
|
const filtered = moderations.filter((moderation) => moderation.logID === req.params.id);
|
||||||
|
res.status(200).json({ code: this.constants.codes.SUCCESS, message: { filtered } });
|
||||||
|
} else {
|
||||||
|
res.status(200).json({ code: this.constants.codes.SUCCESS, message: moderations });
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,7 +7,6 @@ export interface AccountInterface extends Document {
|
||||||
createdBy: string,
|
createdBy: string,
|
||||||
createdAt: Date,
|
createdAt: Date,
|
||||||
locked: boolean,
|
locked: boolean,
|
||||||
bearerSignature: string,
|
|
||||||
permissions: {
|
permissions: {
|
||||||
support: boolean,
|
support: boolean,
|
||||||
staff: boolean,
|
staff: boolean,
|
||||||
|
@ -26,7 +25,6 @@ const Account: Schema = new Schema({
|
||||||
createdBy: String,
|
createdBy: String,
|
||||||
createdAt: Date,
|
createdAt: Date,
|
||||||
locked: Boolean,
|
locked: Boolean,
|
||||||
bearerSignature: String,
|
|
||||||
permissions: {
|
permissions: {
|
||||||
support: Boolean,
|
support: Boolean,
|
||||||
staff: Boolean,
|
staff: Boolean,
|
||||||
|
|
Loading…
Reference in New Issue