some fixes

This commit is contained in:
arp 2020-10-09 14:53:18 +02:00
parent 4af46b1b3f
commit 5e54fc2c26
6 changed files with 76 additions and 70 deletions

View file

@ -1,9 +1,9 @@
import Jwt from "jsonwebtoken";
import {ADMIN_API_TOKEN, ADMIN_API_URL, SECRET_KEY, URL_ROOM_STARTED} from "../Enum/EnvironmentVariable"; //TODO fix import by "_Enum/..."
import {URL_ROOM_STARTED} from "../Enum/EnvironmentVariable"; //TODO fix import by "_Enum/..."
import { uuid } from 'uuidv4';
import {HttpRequest, HttpResponse, TemplatedApp} from "uWebSockets.js";
import {BaseController} from "./BaseController";
import {adminApi, AdminApiData} from "../Services/AdminApi";
import {jwtTokenManager} from "../Services/JWTTokenManager";
export interface TokenInterface {
userUuid: string
@ -59,7 +59,7 @@ export class AuthenticateController extends BaseController {
newUrl = '_/global/'+mapUrlStart;
}
const authToken = Jwt.sign({userUuid: userUuid}, SECRET_KEY, {expiresIn: '24h'});
const authToken = jwtTokenManager.createJWTToken(userUuid);
res.writeStatus("200 OK").end(JSON.stringify({
authToken,
userUuid,

View file

@ -1,14 +1,11 @@
import {ExSocketInterface} from "../Model/Websocket/ExSocketInterface"; //TODO fix import by "_Model/.."
import Jwt from "jsonwebtoken";
import {SECRET_KEY, MINIMUM_DISTANCE, GROUP_RADIUS, ALLOW_ARTILLERY} from "../Enum/EnvironmentVariable"; //TODO fix import by "_Enum/..."
import {MINIMUM_DISTANCE, GROUP_RADIUS} from "../Enum/EnvironmentVariable"; //TODO fix import by "_Enum/..."
import {GameRoom} from "../Model/GameRoom";
import {Group} from "../Model/Group";
import {User} from "../Model/User";
import {isSetPlayerDetailsMessage,} from "../Model/Websocket/SetPlayerDetailsMessage";
import {Gauge} from "prom-client";
import {TokenInterface} from "../Controller/AuthenticateController";
import {PointInterface} from "../Model/Websocket/PointInterface";
import {uuid} from 'uuidv4';
import {Movable} from "../Model/Movable";
import {
PositionMessage,
@ -43,6 +40,8 @@ import {TemplatedApp} from "uWebSockets.js"
import {parse} from "query-string";
import {cpuTracker} from "../Services/CpuTracker";
import {ViewportInterface} from "../Model/Websocket/ViewportMessage";
import {jwtTokenManager} from "../Services/JWTTokenManager";
import {adminApi} from "../Services/AdminApi";
function emitInBatch(socket: ExSocketInterface, payload: SubMessage): void {
socket.batchedMessages.addPayload(payload);
@ -86,54 +85,7 @@ export class IoSocketController {
this.ioConnection();
}
private isValidToken(token: object): token is TokenInterface {
if (typeof((token as TokenInterface).userUuid) !== 'string') {
return false;
}
return true;
}
private async getUserUuidFromToken(token: unknown): Promise<string> {
if (!token) {
throw new Error('An authentication error happened, a user tried to connect without a token.');
}
if (typeof(token) !== "string") {
throw new Error('Token is expected to be a string');
}
if(token === 'test') {
if (ALLOW_ARTILLERY) {
return uuid();
} else {
throw new Error("In order to perform a load-testing test on this environment, you must set the ALLOW_ARTILLERY environment variable to 'true'");
}
}
return new Promise<string>((resolve, reject) => {
Jwt.verify(token, SECRET_KEY, {},(err, tokenDecoded) => {
const tokenInterface = tokenDecoded as TokenInterface;
if (err) {
console.error('An authentication error happened, invalid JsonWebToken.', err);
reject(new Error('An authentication error happened, invalid JsonWebToken. '+err.message));
return;
}
if (tokenDecoded === undefined) {
console.error('Empty token found.');
reject(new Error('Empty token found.'));
return;
}
if (!this.isValidToken(tokenInterface)) {
reject(new Error('Authentication error, invalid token structure.'));
return;
}
resolve(tokenInterface.userUuid);
});
});
}
ioConnection() {
this.app.ws('/room/*', {
@ -181,7 +133,12 @@ export class IoSocketController {
}
const userUuid = await this.getUserUuidFromToken(token);
const userUuid = await jwtTokenManager.getUserUuidFromToken(token);
const isGranted = await adminApi.memberIsGrantedAccessToRoom(userUuid, roomId);
if (!isGranted) {
throw Error('Client cannot acces this ressource.');
}
if (upgradeAborted.aborted) {
console.log("Ouch! Client disconnected before we could upgrade it!");
@ -256,11 +213,6 @@ export class IoSocketController {
// Let's join the room
this.handleJoinRoom(client, client.roomId, client.position, client.viewport, client.name, client.characterLayers);
/*const isGranted = await adminApi.memberIsGrantedAccessToRoom(client.userUuid, roomId);
if (!isGranted) {
throw Error('Client cannot acces this ressource.');
}*/
const setUserIdMessage = new SetUserIdMessage();
setUserIdMessage.setUserid(client.userId);

View file

@ -0,0 +1,60 @@
import {ALLOW_ARTILLERY, SECRET_KEY} from "../Enum/EnvironmentVariable";
import {uuid} from "uuidv4";
import Jwt from "jsonwebtoken";
import {TokenInterface} from "../Controller/AuthenticateController";
class JWTTokenManager {
public createJWTToken(userUuid: string) {
return Jwt.sign({userUuid: userUuid}, SECRET_KEY, {expiresIn: '24h'});
}
public async getUserUuidFromToken(token: unknown): Promise<string> {
if (!token) {
throw new Error('An authentication error happened, a user tried to connect without a token.');
}
if (typeof(token) !== "string") {
throw new Error('Token is expected to be a string');
}
if(token === 'test') {
if (ALLOW_ARTILLERY) {
return uuid();
} else {
throw new Error("In order to perform a load-testing test on this environment, you must set the ALLOW_ARTILLERY environment variable to 'true'");
}
}
return new Promise<string>((resolve, reject) => {
Jwt.verify(token, SECRET_KEY, {},(err, tokenDecoded) => {
const tokenInterface = tokenDecoded as TokenInterface;
if (err) {
console.error('An authentication error happened, invalid JsonWebToken.', err);
reject(new Error('An authentication error happened, invalid JsonWebToken. '+err.message));
return;
}
if (tokenDecoded === undefined) {
console.error('Empty token found.');
reject(new Error('Empty token found.'));
return;
}
if (!this.isValidToken(tokenInterface)) {
reject(new Error('Authentication error, invalid token structure.'));
return;
}
resolve(tokenInterface.userUuid);
});
});
}
private isValidToken(token: object): token is TokenInterface {
return !(typeof((token as TokenInterface).userUuid) !== 'string');
}
}
export const jwtTokenManager = new JWTTokenManager();

View file

@ -48,7 +48,7 @@ class ConnectionManager {
public connectToRoomSocket(roomId: string, name: string, characterLayers: string[], position: PositionInterface, viewport: ViewportInterface): Promise<RoomConnection> {
return new Promise<RoomConnection>((resolve, reject) => {
const connection = new RoomConnection(this.authToken as string, roomId, name, characterLayers, position, viewport);
const connection = new RoomConnection(this.authToken, roomId, name, characterLayers, position, viewport);
connection.onConnectError((error: object) => {
console.log('An error occurred while connecting to socket server. Retrying');
reject(error);

View file

@ -53,10 +53,10 @@ export class RoomConnection implements RoomConnection {
* @param token A JWT token containing the UUID of the user
* @param roomId The ID of the room in the form "_/[instance]/[map_url]" or "@/[org]/[event]/[map]"
*/
public constructor(token: string, roomId: string, name: string, characterLayers: string[], position: PositionInterface, viewport: ViewportInterface) {
public constructor(token: string|null, roomId: string, name: string, characterLayers: string[], position: PositionInterface, viewport: ViewportInterface) {
let url = API_URL.replace('http://', 'ws://').replace('https://', 'wss://');
url += '/room/'+roomId
url += '?token='+encodeURIComponent(token);
url += '?token='+(token ?encodeURIComponent(token):'');
url += '&name='+encodeURIComponent(name);
for (let layer of characterLayers) {
url += '&characterLayers='+encodeURIComponent(layer);

View file

@ -1,6 +0,0 @@
export class GameSceneDescriptor {
constructor(MapKey : string, MapUrlFile: string, instance: string, key: string) {
this.roomId = '';//
}
}