rewrote the authorisation flow: give more responsability to gameManager and less to gameScene
This commit is contained in:
parent
032facb75f
commit
02c193a262
14 changed files with 244 additions and 170 deletions
|
@ -1,8 +1,7 @@
|
|||
import {URL_ROOM_STARTED} from "../Enum/EnvironmentVariable"; //TODO fix import by "_Enum/..."
|
||||
import { v4 } from 'uuid';
|
||||
import {HttpRequest, HttpResponse, TemplatedApp} from "uWebSockets.js";
|
||||
import {BaseController} from "./BaseController";
|
||||
import {adminApi, AdminApiData} from "../Services/AdminApi";
|
||||
import {adminApi} from "../Services/AdminApi";
|
||||
import {jwtTokenManager} from "../Services/JWTTokenManager";
|
||||
|
||||
export interface TokenInterface {
|
||||
|
@ -13,18 +12,19 @@ export class AuthenticateController extends BaseController {
|
|||
|
||||
constructor(private App : TemplatedApp) {
|
||||
super();
|
||||
this.login();
|
||||
this.register();
|
||||
this.anonymLogin();
|
||||
}
|
||||
|
||||
//permit to login on application. Return token to connect on Websocket IO.
|
||||
login(){
|
||||
this.App.options("/login", (res: HttpResponse, req: HttpRequest) => {
|
||||
//Try to login with an admin token
|
||||
register(){
|
||||
this.App.options("/register", (res: HttpResponse, req: HttpRequest) => {
|
||||
this.addCorsHeaders(res);
|
||||
|
||||
res.end();
|
||||
});
|
||||
|
||||
this.App.post("/login", (res: HttpResponse, req: HttpRequest) => {
|
||||
this.App.post("/register", (res: HttpResponse, req: HttpRequest) => {
|
||||
(async () => {
|
||||
this.addCorsHeaders(res);
|
||||
|
||||
|
@ -36,35 +36,25 @@ export class AuthenticateController extends BaseController {
|
|||
|
||||
//todo: what to do if the organizationMemberToken is already used?
|
||||
const organizationMemberToken:string|null = param.organizationMemberToken;
|
||||
const mapSlug:string|null = param.mapSlug;
|
||||
|
||||
|
||||
try {
|
||||
let userUuid;
|
||||
let mapUrlStart;
|
||||
let newUrl: string|null = null;
|
||||
if (typeof organizationMemberToken != 'string') throw new Error('No organization token');
|
||||
const data = await adminApi.fetchMemberDataByToken(organizationMemberToken);
|
||||
|
||||
if (organizationMemberToken) {
|
||||
const data = await adminApi.fetchMemberDataByToken(organizationMemberToken);
|
||||
|
||||
userUuid = data.userUuid;
|
||||
mapUrlStart = data.mapUrlStart;
|
||||
newUrl = this.getNewUrlOnAdminAuth(data)
|
||||
} else if (mapSlug !== null) {
|
||||
userUuid = v4();
|
||||
mapUrlStart = mapSlug;
|
||||
newUrl = null;
|
||||
} else {
|
||||
userUuid = v4();
|
||||
mapUrlStart = host.replace('api.', 'maps.') + URL_ROOM_STARTED;
|
||||
newUrl = '_/global/'+mapUrlStart;
|
||||
}
|
||||
const userUuid = data.userUuid;
|
||||
const organizationSlug = data.organizationSlug;
|
||||
const worldSlug = data.worldSlug;
|
||||
const roomSlug = data.roomSlug;
|
||||
const mapUrlStart = data.mapUrlStart;
|
||||
|
||||
const authToken = jwtTokenManager.createJWTToken(userUuid);
|
||||
res.writeStatus("200 OK").end(JSON.stringify({
|
||||
authToken,
|
||||
userUuid,
|
||||
organizationSlug,
|
||||
worldSlug,
|
||||
roomSlug,
|
||||
mapUrlStart,
|
||||
newUrl,
|
||||
}));
|
||||
|
||||
} catch (e) {
|
||||
|
@ -75,12 +65,32 @@ export class AuthenticateController extends BaseController {
|
|||
|
||||
})();
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private getNewUrlOnAdminAuth(data:AdminApiData): string {
|
||||
const organizationSlug = data.organizationSlug;
|
||||
const worldSlug = data.worldSlug;
|
||||
const roomSlug = data.roomSlug;
|
||||
return '/@/'+organizationSlug+'/'+worldSlug+'/'+roomSlug;
|
||||
//permit to login on application. Return token to connect on Websocket IO.
|
||||
anonymLogin(){
|
||||
this.App.options("/anonymLogin", (res: HttpResponse, req: HttpRequest) => {
|
||||
this.addCorsHeaders(res);
|
||||
|
||||
res.end();
|
||||
});
|
||||
|
||||
this.App.post("/anonymLogin", (res: HttpResponse, req: HttpRequest) => {
|
||||
(async () => {
|
||||
this.addCorsHeaders(res);
|
||||
|
||||
res.onAborted(() => {
|
||||
console.warn('Login request was aborted');
|
||||
})
|
||||
|
||||
const userUuid = v4();
|
||||
const authToken = jwtTokenManager.createJWTToken(userUuid);
|
||||
res.writeStatus("200 OK").end(JSON.stringify({
|
||||
authToken,
|
||||
userUuid,
|
||||
}));
|
||||
})();
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ import {cpuTracker} from "../Services/CpuTracker";
|
|||
import {ViewportInterface} from "../Model/Websocket/ViewportMessage";
|
||||
import {jwtTokenManager} from "../Services/JWTTokenManager";
|
||||
import {adminApi} from "../Services/AdminApi";
|
||||
import {RoomIdentifier} from "../Model/RoomIdentifier";
|
||||
|
||||
function emitInBatch(socket: ExSocketInterface, payload: SubMessage): void {
|
||||
socket.batchedMessages.addPayload(payload);
|
||||
|
@ -88,7 +89,7 @@ export class IoSocketController {
|
|||
|
||||
|
||||
ioConnection() {
|
||||
this.app.ws('/room/*', {
|
||||
this.app.ws('/room', {
|
||||
/* Options */
|
||||
//compression: uWS.SHARED_COMPRESSOR,
|
||||
maxPayloadLength: 16 * 1024 * 1024,
|
||||
|
@ -112,7 +113,12 @@ export class IoSocketController {
|
|||
const websocketProtocol = req.getHeader('sec-websocket-protocol');
|
||||
const websocketExtensions = req.getHeader('sec-websocket-extensions');
|
||||
|
||||
const roomId = req.getUrl().substr(6);
|
||||
const roomId = query.roomId;
|
||||
//todo: better validation: /\/_\/.*\/.*/ or /\/@\/.*\/.*\/.*/
|
||||
if (typeof roomId !== 'string') {
|
||||
throw new Error('Undefined room ID: ');
|
||||
}
|
||||
const roomIdentifier = new RoomIdentifier(roomId);
|
||||
|
||||
const token = query.token;
|
||||
const x = Number(query.x);
|
||||
|
@ -140,12 +146,14 @@ export class IoSocketController {
|
|||
const userUuid = await jwtTokenManager.getUserUuidFromToken(token);
|
||||
console.log('uuid', userUuid);
|
||||
|
||||
const isGranted = await adminApi.memberIsGrantedAccessToRoom(userUuid, roomId);
|
||||
if (!isGranted) {
|
||||
console.log('access not granted for user '+userUuid+' and room '+roomId);
|
||||
throw new Error('Client cannot acces this ressource.')
|
||||
} else {
|
||||
console.log('access granted for user '+userUuid+' and room '+roomId);
|
||||
if (roomIdentifier.anonymous === false) {
|
||||
const isGranted = await adminApi.memberIsGrantedAccessToRoom(userUuid, roomIdentifier);
|
||||
if (!isGranted) {
|
||||
console.log('access not granted for user '+userUuid+' and room '+roomId);
|
||||
throw new Error('Client cannot acces this ressource.')
|
||||
} else {
|
||||
console.log('access granted for user '+userUuid+' and room '+roomId);
|
||||
}
|
||||
}
|
||||
|
||||
if (upgradeAborted.aborted) {
|
||||
|
|
14
back/src/Model/RoomIdentifier.ts
Normal file
14
back/src/Model/RoomIdentifier.ts
Normal file
|
@ -0,0 +1,14 @@
|
|||
export class RoomIdentifier {
|
||||
public anonymous: boolean;
|
||||
public id:string
|
||||
constructor(roomID: string) {
|
||||
if (roomID.indexOf('_/') === 0) {
|
||||
this.anonymous = true;
|
||||
} else if(roomID.indexOf('@/') === 0) {
|
||||
this.anonymous = false;
|
||||
} else {
|
||||
throw new Error('Incorrect room ID: '+roomID);
|
||||
}
|
||||
this.id = roomID; //todo: extract more data from the id (like room slug, organization name, etc);
|
||||
}
|
||||
}
|
|
@ -1,5 +1,6 @@
|
|||
import {ADMIN_API_TOKEN, ADMIN_API_URL} from "../Enum/EnvironmentVariable";
|
||||
import Axios, {AxiosError} from "axios";
|
||||
import Axios from "axios";
|
||||
import {RoomIdentifier} from "../Model/RoomIdentifier";
|
||||
|
||||
export interface AdminApiData {
|
||||
organizationSlug: string
|
||||
|
@ -22,13 +23,14 @@ class AdminApi {
|
|||
return res.data;
|
||||
}
|
||||
|
||||
async memberIsGrantedAccessToRoom(memberId: string, roomId: string): Promise<boolean> {
|
||||
async memberIsGrantedAccessToRoom(memberId: string, roomIdentifier: RoomIdentifier): Promise<boolean> {
|
||||
if (!ADMIN_API_URL) {
|
||||
return Promise.reject('No admin backoffice set!');
|
||||
}
|
||||
try {
|
||||
//todo: send more specialized data instead of the whole id
|
||||
const res = await Axios.get(ADMIN_API_URL+'/api/member/is-granted-access',
|
||||
{ headers: {"Authorization" : `${ADMIN_API_TOKEN}`}, params: {memberId, roomIdentifier: roomId} }
|
||||
{ headers: {"Authorization" : `${ADMIN_API_TOKEN}`}, params: {memberId, roomIdentifier: roomIdentifier.id} }
|
||||
)
|
||||
return !!res.data;
|
||||
} catch (e) {
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue