[Remote] Actually fix auth (#260)

* fix favicon, basic auth

* actual fix......
This commit is contained in:
Kendall Garner 2023-09-25 00:31:33 +00:00 committed by GitHub
parent b375238baf
commit 9e3e038d42
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 125 additions and 103 deletions

View file

@ -34,6 +34,7 @@ interface MimeType {
interface StatefulWebSocket extends WebSocket { interface StatefulWebSocket extends WebSocket {
alive: boolean; alive: boolean;
auth: boolean;
} }
let server: Server | undefined; let server: Server | undefined;
@ -52,7 +53,7 @@ type SendData = ServerEvent & {
function send({ client, event, data }: SendData): void { function send({ client, event, data }: SendData): void {
if (client.readyState === WebSocket.OPEN) { if (client.readyState === WebSocket.OPEN) {
if (client.alive) { if (client.alive && client.auth) {
client.send(JSON.stringify({ data, event })); client.send(JSON.stringify({ data, event }));
} }
} }
@ -320,12 +321,13 @@ const enableServer = (config: RemoteConfig): Promise<void> => {
wsServer.on('connection', (ws) => { wsServer.on('connection', (ws) => {
let authFail: number | undefined; let authFail: number | undefined;
ws.alive = true;
if (!settings.username && !settings.password) { if (!settings.username && !settings.password) {
ws.alive = true; ws.auth = true;
} else { } else {
authFail = setTimeout(() => { authFail = setTimeout(() => {
if (!ws.alive) { if (!ws.auth) {
ws.close(); ws.close();
} }
}, 10000) as unknown as number; }, 10000) as unknown as number;
@ -334,29 +336,28 @@ const enableServer = (config: RemoteConfig): Promise<void> => {
ws.on('error', console.error); ws.on('error', console.error);
ws.on('message', (data) => { ws.on('message', (data) => {
if (!ws.alive) {
try { try {
const auth = data.toString().split(' ')[1]; const json = JSON.parse(data.toString()) as ClientEvent;
const event = json.event;
if (!ws.auth) {
if (event === 'authenticate') {
const auth = json.header.split(' ')[1];
const [login, password] = Buffer.from(auth, 'base64') const [login, password] = Buffer.from(auth, 'base64')
.toString() .toString()
.split(':'); .split(':');
if (login === settings.username && password === settings.password) { if (login === settings.username && password === settings.password) {
ws.alive = true; ws.auth = true;
} else { } else {
ws.close(); ws.close();
} }
clearTimeout(authFail); clearTimeout(authFail);
} catch (e) { } else {
console.error(e);
}
return; return;
} }
}
try {
const json = JSON.parse(data.toString()) as ClientEvent;
const event = json.event;
switch (event) { switch (event) {
case 'pause': { case 'pause': {

View file

@ -87,7 +87,7 @@ export const useRemoteStore = create<SettingsSlice>()(
devtools( devtools(
immer((set, get) => ({ immer((set, get) => ({
actions: { actions: {
reconnect: () => { reconnect: async () => {
const existing = get().socket; const existing = get().socket;
if (existing) { if (existing) {
@ -99,11 +99,17 @@ export const useRemoteStore = create<SettingsSlice>()(
existing.close(4001); existing.close(4001);
} }
} }
set(async (state) => {
let authHeader: string | undefined;
try { try {
const credentials = await fetch('/credentials'); const credentials = await fetch('/credentials');
const authHeader = await credentials.text(); authHeader = await credentials.text();
} catch (error) {
console.error('Failed to get credentials');
}
set((state) => {
const socket = new WebSocket( const socket = new WebSocket(
// eslint-disable-next-line no-restricted-globals // eslint-disable-next-line no-restricted-globals
location.href.replace('http', 'ws'), location.href.replace('http', 'ws'),
@ -152,7 +158,14 @@ export const useRemoteStore = create<SettingsSlice>()(
}); });
socket.addEventListener('open', () => { socket.addEventListener('open', () => {
socket.send(authHeader); if (authHeader) {
socket.send(
JSON.stringify({
event: 'authenticate',
header: authHeader,
}),
);
}
set({ connected: true }); set({ connected: true });
}); });
@ -178,12 +191,10 @@ export const useRemoteStore = create<SettingsSlice>()(
}); });
state.socket = socket; state.socket = socket;
} catch (err) {
console.error(err);
}
}); });
}, },
send: (data: ClientEvent) => { send: (data: ClientEvent) => {
console.log(data, get().socket);
get().socket?.send(JSON.stringify(data)); get().socket?.send(JSON.stringify(data));
}, },
toggleIsDark: () => { toggleIsDark: () => {

View file

@ -53,4 +53,14 @@ export interface ClientVolume {
volume: number; volume: number;
} }
export type ClientEvent = ClientSimpleEvent | ClientFavorite | ClientRating | ClientVolume; export interface ClientAuth {
event: 'authenticate';
header: string;
}
export type ClientEvent =
| ClientAuth
| ClientSimpleEvent
| ClientFavorite
| ClientRating
| ClientVolume;