add authenticate on socket connect

This commit is contained in:
Enrique Hernandez 2021-02-09 17:07:45 -06:00
commit e0da50eb27
7 changed files with 112 additions and 70 deletions

View file

@ -14,12 +14,6 @@ interface ipcRendererPayload {
*/
export function main(): void {
// Instantiate socket session with crimata-platorm.
initSession();
// mount auth-user listener
ipcMain.on('auth-user', authUser);
// create main window.
const win = createWindow({ width: 350, height: 525, resizable: false });
@ -34,18 +28,17 @@ export function main(): void {
}
const windowMount = (): void => {
// Instantiate socket session with crimata-platorm.
initSession();
windowEmitter.emit('window-active', true);
// ipc event handlers
ipcMain.on('send-message', handleMessage);
ipcMain.on('auth-login', authLogin);
}
const windowDismount = (): void => {
windowEmitter.emit('window-active', false);
// TODO: Gracefully close socket connection
ipcMain.removeAllListeners('send-message');
ipcMain.removeAllListeners('auth-login');
ipcMain.removeAllListeners('auth-user');
}
// Handle window mount and dismount.

View file

@ -1,5 +1,6 @@
import WebSocket from 'ws';
import { windowEmitter } from './windowEmitter';
import { ipcMain } from "electron";
type Message = {
type: string;
@ -14,85 +15,87 @@ interface RenderMessage extends Message {
time: string;
}
interface AuthMessage extends Message {
interface AuthUser extends Message {
email: string;
firstName: string;
lastName: string;
access_token: string;
}
interface AuthRequest {
token: string;
}
interface PostLogin {
email: string;
password: string;
}
interface PostMessage {
content: string;
}
const ip = 'ws://localhost';
const port = 8080;
const username = 'hernandeze2@xavier.edu';
const reconnectTimeout = 3000; //ms
let socket: WebSocket;
let success = false;
const receiveMessage = (message: string): void => {
// NOTE assuming message is JSON string
const parsed: RenderMessage | AuthMessage = JSON.parse(message);
if (message === 'locked') {
windowEmitter.emit('auth-resp', message);
return;
}
const parsed: RenderMessage | AuthUser = JSON.parse(message);
if (parsed.type === "render") {
windowEmitter.emit('ipc-renderer', {
endpoint: 'render-message',
message: parsed
});
} else if (parsed.type === "auth") {
windowEmitter.emit('auth-resp', parsed);
}
}
// Connect and send username
const authToken = async (event: any, token: string): Promise<string | AuthUser > => {
return new Promise((resolve, reject) => {
console.log('authenticating...');
windowEmitter.on('auth-resp', (arg: string | AuthUser) => {
if (arg === 'locked') {
reject(arg);
}
resolve(arg);
});
if (token) {
socket.send(token);
} else {
socket.send('no-token');
}
});
};
// Connect and authenticate
export function initSession() {
let success = false;
socket = new WebSocket(`${ip}:${port}`);
socket.binaryType = 'arraybuffer';
socket.on('open', () => {
console.log('Connected to crimata-platform');
socket.send(username);
success = true;
// handle renderer auth-token event
ipcMain.removeHandler('auth-token'); // avoid setting duplicate handlers
ipcMain.handle('auth-token', authToken);
// fetch token from renderer
windowEmitter.emit('ipc-renderer', {
endpoint: 'fetch-token',
message: null
});
})
socket.on("message", receiveMessage);
setTimeout(()=> {
if (!success) {
throw new Error('Unable to connect to crimata-platform')
// initSession();
throw new Error('Unable to connect to crimata-platform');
}
}, 3000)
}, reconnectTimeout);
}
export const authUser = (event: any, arg: AuthRequest) => {
console.log('sending token to socket', arg)
try {
sendMessage({
content: arg.token
});
windowEmitter.on('auth-resp', (payload: AuthMessage) => {
event.reply('auth-user-reply', payload);
})
} catch(e){
console.log('Error authenticating user! ' + e);
event.reply('auth-user-reply', e);
}
}
export const authLogin = (event: any, arg: PostLogin) => {
export const authLogin = (event: any, arg: any) => {
try {
sendMessage(arg)
windowEmitter.on('auth-resp', (payload: AuthMessage) => {
windowEmitter.on('auth-resp', (payload: AuthUser) => {
event.reply('auth-login-reply', payload);
})
} catch(e) {
@ -101,10 +104,10 @@ export const authLogin = (event: any, arg: PostLogin) => {
}
}
export const sendMessage = (content: PostMessage | Buffer | PostLogin) => {
export const sendMessage = (content: string | Buffer) => {
if (content instanceof Buffer) {
socket.send(content);
} else {
} else if (content){
socket.send(JSON.stringify(content));
}
}

View file

@ -24,10 +24,23 @@ const state = reactive<AuthState>({
const AUTH_KEY = 'crimata_token';
const token = window.localStorage.getItem(AUTH_KEY);
console.log('token: ',token)
// authenticate on socket connect
window.ipcRenderer.on("fetch-token", async (event, payload) => {
const { data, invoke } = useIpc('auth-token');
try {
await invoke(token);
state.user = data.value;
}
catch(e) {
state.error = e;
console.log('ERROR: failed authentication');
window.localStorage.removeItem(AUTH_KEY);
}
});
if (token) {
const { loading, error, data, send } = useIpc('auth-user');
const { loading, error, data, send, invoke } = useIpc('auth-user');
state.authenticating = true;

View file

@ -13,6 +13,20 @@ export const useIpc = (endpoint: string) => {
}
})
const invoke = (payload: any) => {
loading.value = true;
error.value = undefined;
return window.ipcRenderer.invoke(endpoint, payload).then(res => {
data.value = res;
}).catch(e => {
error.value = e;
throw e;
}).finally(() => {
loading.value = false;
})
}
const send = (payload?: Record<string, any>, callback?: (arg: any) => void) => {
loading.value = true;
error.value = undefined;
@ -46,6 +60,7 @@ export const useIpc = (endpoint: string) => {
data,
error,
errorMessage,
send
send,
invoke
}
}

17
src/modules/socket.ts Normal file
View file

@ -0,0 +1,17 @@
interface SocketState {
connection: WebSocket | null;
auth: boolean;
}
// Create WebSocket connection.
const socket = new WebSocket('ws://localhost:8080');
// Connection opened
socket.onopen = function (event) {
socket.send('Hello Server!');
}
socket.onmessage = function(event) {
console.debug("WebSocket message received:", event);
}

View file

@ -41,23 +41,20 @@ export default defineComponent({
rememberMe: true,
});
const { loading, data, send, errorMessage } = useIpc("auth-login");
//const { loading, data, send, errorMessage } = useIpc("auth-login");
const { loading, error, data, invoke, errorMessage } = useIpc('test');
const submit = async () => {
// console.log(toRefs(payload));
send({
await invoke({
request: "register",
email: payload.email,
password: payload.password,
});
console.log(data.value, "login");
};
watch(loading, () => {
console.log(data.value)
setUser(data.value, payload.rememberMe);
})
console.log('testing incoke', data.value.test)
// setUser(data.value, payload.rememberMe);
router.push({ name: "home" });
});
};
return {
loading,

View file

@ -14,12 +14,16 @@ const wss = new WebSocket.Server({
wss.on("connection", function connection(ws, req) {
ws.on("message", function incoming(message) {
console.log(message)
// const parsed = JSON.parse(message)
// console.log(parsed)
if (message === 'no-token') {
console.log('no token to authenticate');
ws.send('locked');
}
});
const ip = req.socket.remoteAddress;
console.log("received connection from", ip);
ws.send(JSON.stringify(testMessage));
// ws.send(JSON.stringify(testMessage));
});