Share your repls and programming experiences

← Back to all posts
EekChat - a secure online chatroom
tussiez (1558)

EekChat!

Recently, I've been seeing more and more chatrooms on Repl.it, so I guess I'll add mine to the list.

My friends and I usually used Gmail for conversations, but it tended to be slow at responding, and since almost everything was blocked on school computers, it was our only way to communicate "quickly". So I decided to make EekChat! It's a basic chatting application written in JavaScript with node.js and socket.io.

UPDATE

I rewrote all of the server and client script code, and with this, we have the following changes:

  • 12/24/2020: Chatroom should be fixed :)
  • Repl.it authentication, no more need to log in with your Google account!
  • Way less bugs and random crashes!
  • Optimizations
  • Way cleaner code
  • Profanity is censored
  • All of the account verification is done solely on the server, which makes it impossible to hack or impersonate, as the server will only accept usernames from Repl.it's auth headers.
  • The Send button works!

Features

  • Markdown support!
  • Anti-hack
  • Censors
  • Anti-spam
  • Repl.it login
  • <script> and HTML elements are blocked!
  • "X person is typing".. box
  • Chat saves
  • Automatic re-logon
  • (Coming soon): Messages and login data saved will be encrypted
  • In forked Repls with custom group members set, theoretically it should be difficult for outsiders to join

DISCLAIMER

Here are some things you may want to be aware of when using this app:

  • As I stated earlier, messages are saved indefinitely and can be viewed by others long after you leave the chatroom. Keep this in mind when writing messages.
  • Messages sent are encrypted, but messages saved aren't (sending with HTTPS, saving in plain text)

Have fun!

Comments
hotnewtop
tussiez (1558)

@CyberHacker101 Yeah
You got 10 cycles from us just clicking upvote on the comments :)

CyberHacker101 (113)

wow, I just said "don't expose me" a billion times. @tussiez

Baconman321 (1083)

@tussiez But srsly, try making session tokens. Might take a bit to figure out, but basically you generate a token for a user and send that token to the server. If the token isn't valid, don't send the message because it might be an impersonator. Also, make the token expire after some time as to make it harder to hack.

tussiez (1558)

@Baconman321 I've added session tokens, they don't expire, but they're never passed to other users. It stays on client and server, and they're deleted after the user leaves.

tussiez (1558)

@CyberHacker101
Reminds me of SortaCraft, genius concept, terrible programming

tussiez (1558)

@Baconman321 Theoretically, it should be impossible to acquire these session keys without listening to the socket, which is already encrypted, which encrypts the messages and account data.

Baconman321 (1083)

@tussiez That's great! Also, change the chat.txt to chat.json and encrypt it using an encryption method. You can store the key in an env file.

Baconman321 (1083)

@tussiez IDK much about sockets because I never really need to use them...

CyberHacker101 (113)

yup also ur very bad at organizing @tussiez

tussiez (1558)

@Baconman321 Socket.IO makes it really easy, if you ever need to learn.. the entire library can be used in simple send and recieve event handlers.

tussiez (1558)

@CyberHacker101 It isn't my best programming, but it works!
@Baconman321 I'm going to add the save encryption soon. I need to do my homework right now though, so I'll come back to it later.

Baconman321 (1083)

@tussiez Anything with .io is blocked for me, but only if I look it up or in an iframe (HaHa adults think kids are dum, well I just outsmurted them. Just fetch the webpage and display it as srcdoc LOL).

Baconman321 (1083)

LOL it will happen if anyone replies to ur comment. As you see, I left out your name. This should still ping you though :/

tussiez (1558)

@Baconman321 oof I just realized that the link really is socket.io

tussiez (1558)

Yeah, if it's on the correct thread.

CyberHacker101 (113)

Now seriously stop with the pings T^T @Baconman321

CyberHacker101 (113)

Right now I'm getting pinged by 40 different people @tussiez

Baconman321 (1083)

@tussiez Remember, it only works on web browsers/iframes. If I link socket.io it will work because it is a web asset, not an iframe or a web search. It will work on nodejs because that is backend, not client side. However, like I said it will work on client side as long as I don't put it in an iframe.

Baconman321 (1083)

@tussiez Imagine knowing more about the monitoring equipment the school uses than the school.
oh and cyberhacker, just click the notifications and wait like 1 second. Then the notifications alert goes away.

tussiez (1558)

Yeah. I read a book for 5 minutes and repl blows up lol

CyberHacker101 (113)

I really don't like the part where it says "mostly" secure @tussiez

CyberHacker101 (113)

And plz add the part where we can change our username
@tussiez

tussiez (1558)

@CyberHacker101 Oof
When I finish my schoolwork, I'll get to encrypting saved chat messages

tussiez (1558)

@CyberHacker101 Hommmeeewwwoooooorrrrrk

Please waiiiittt

CyberHacker101 (113)

Every single comment gives u a upvote @tussiez

CyberHacker101 (113)

Confusing Comments are illegal

Whippingdot (603)

Can you make a sign in with repl.it. @tussiez

CyberHacker101 (113)

I don't know what to say after someone says ? @tussiez

tussiez (1558)

@CyberHacker101 I'm confused about what you're talking about, I can only see the current comment
sorry :)

CyberHacker101 (113)

Woah didn't you have 300 cycles? @tussiez

CyberHacker101 (113)

Hmmm did you fix the chat? Did you make it to sign in with repl? @tussiez

CyberHacker101 (113)

HURRY UP AND CHANGE IT IMA GET EXPOSED @tussiez

tussiez (1558)

@CyberHacker101 It seems like it'll take some time to figure out exactly how to use Repl.it auth (it's in Python) I'll figure it out soon enough.
However chat is working, I'll just anem everyone 'annonymous'

CyberHacker101 (113)

NOooooo name everybody "anonymous or cyberhacker" @tussiez

CyberHacker101 (113)

You also spelled "anonymous" wrong. HAHHAHHA ME AM BIG BRAIN @tussiez

CyberHacker101 (113)

It failed the comments don't show @tussiez

CyberHacker101 (113)

Hmmmm.... We Couldn't Reach Your Repl
Make sure your repl has a port open and is ready to receive HTTP traffic.
Return to Repl.it? @tussiez

CyberHacker101 (113)

ur gonna have to change this <meta name="google-signin-client_id" content="561624177260-9gge9gc015oeqqhbkf907s872uomi8sd.apps.googleusercontent.com">

<script src="https://apis.google.com/js/platform.js" async defer></script>

@tussiez

CyberHacker101 (113)

Again spelling ME AM ULTIMATE BIG BRAIN @tussiez

CyberHacker101 (113)

Yoo i figured it out in python @tussiez

CyberHacker101 (113)

Holy cow one day you have 249 cycles and the next you got 366 cycles @Baconman321

Baconman321 (1083)

@CyberHacker101 It's been almost a month... -_-

CyberHacker101 (113)

Oof I've been on repl for the past weeks @Baconman321

tussiez (1558)

@CyberHacker101 duuuude repl is blowing up with notifications
SPelling?

Baconman321 (1083)

@CyberHacker101 XD u must not have seen me a lot then.

HimanshuShekha4 (50)

@tussiez why did you named it as "Eek chat" ?

tussiez (1558)

@HimanshuShekha4 It’s 11:21 PM where I live :)
I used to name my apps with Eek for some strange reason a while ago, so I don’t really know

RyanGardiner1 (142)

@tussiez Sry, but this doesnt work :/

tussiez (1558)

@RyanGardiner1 Used to... I’ll try to fix it later today. Stay tuned! :)

johnnyfrancis (22)

Error: ENOENT: no such file or directory, stat '/home/runner/EekChatlogin.html'

tussiez (1558)

@johnnyfrancis I have no idea what's pointing to that file, but it doesn't exist. The error is harmless though..

Squirrel777 (139)

This is great! Could use some CSS though...

foodandmoarfood (14)

Who here is "Santa Claus" in the chat?!

foodandmoarfood (14)

Great chat program though
Maybe add a way to change your name viewed, instead of creating a fake Google account?

Bookie0 (6113)

Do we have to sign in with google? What about using repl auth? ;)

and maybe a favicon?

and why is everything squished to that side lol? center it, make it longer!!


try making the text box a bit nicer, and a bit higher up so it kinda "connects" with the chats above.

You could also try adding markdown.

And also the ability to either choose a name that will display as your username as some folks don't really want to use their google account name. And what if you don't have google...

and maybe a language filter for bad words..?

Anyways pretty good job! :D

tussiez (1558)

@Bookie0
1. Yeah, I've have to familiarize myself with Repl.it authentication
2. It was written quickly since I was tired of Gmail, so isn't super polished
3. It should have been centered. Weird, I'll look into it later.
4. Again, I wrote this in a night or two, it has pretty simplistic CSS.
5. Sure!
6. I'll probably add this with Repl auth
7. Sure!
8.Yay! Thanks for the review

tussiez (1558)

@Bookie0 By the way, is it possible to use Repl.it auth on just node.js? I'm a noob at Python :)

Bookie0 (6113)

@tussiez
ok
ok
ok
ok
yay
ok
yay
ok np! :D

Bookie0 (6113)

@tussiez yeye i think so, ive seen some chats already with repl auth

check this (but it uses express

and this maybe it could help! :D

tussiez (1558)

@Bookie0 Express is a node.js library, should work.
Thanks!

CyberHacker101 (113)

this is funny to a normal person not that funny to a coder

CyberHacker101 (113)

eh it really looks like a deformed cat @tussiez

CyberHacker101 (113)

Hey, wanna see something I made? @tussiez

zplusfour (896)

@CyberHacker101 css programmers in a nutshell

CyberHacker101 (113)

Hmmm, how's sorta-craft?

Baconman321 (1083)

@CyberHacker101 We're working on gravity (I'm collaborating with tussiez). Later on we might make a saving option...

CyberHacker101 (113)

Hmmm goood I'm working on Minecraft clone try 6842 mk 2kxY343 @Baconman321

tussiez (1558)

@CyberHacker101 What do you mean by 23427r2u9g

tussiez (1558)

@tussiez merry christmas >40cycles!

CyberHacker101 (113)

Ur chat is broken uh I really think it not a good idea to let people to login with google ig its better if ya make it login with repl or let you change ur username

CyberHacker101 (113)

And this is very good for people who want to stay anonymous. @tussiez

tussiez (1558)

@CyberHacker101 Yeah, it was intended to be a private chat.
I'm fixing the anti-spam, pelas wait

CyberHacker101 (113)

well just dont change the part where you can change your name @tussiez

CyberHacker101 (113)

well you still don't know my first name eh

CyberHacker101 (113)

also this came up... Authorization Error
Error 400: redirect_uri_mismatch
The JavaScript origin in the request, https://eekchat--tussiez.repl.co, does not match the ones authorized for the OAuth client. Visit https://console.developers.google.com/apis/credentials/oauthclient/${your_client_id}?project=${your_project_number} to update the authorized JavaScript origins.
Learn more

CyberHacker101 (113)

I don't want to login with google

tussiez (1558)

@CyberHacker10 It was intended to be a private chat, but that's K! I'll see if I can disable it but will probably break something else

CyberHacker101 (113)

yo it says my full real name @tussiez

tussiez (1558)

@CyberHacker101 yeah, I made a fake Google account for this

CyberHacker101 (113)

I don't want to be exposed @tussiez

tussiez (1558)

@tussiez I can remove your message if you wish to stay private :)

CyberHacker101 (113)

Ehh nah just tell me how to sign [email protected]

tussiez (1558)

@CyberHacker101 Close the tab, your information shouldn't be saved

tussiez (1558)

Please!There's too much

tussiez (1558)

@CyberHacker101 Lol, replit had too many save issues

CyberHacker101 (113)

bro ive never seen someone use a comma in replit are you ok? @tussiez

CyberHacker101 (113)

Yeah forget what i said lol @tussiez

DerpBurgerPlayz (0)

how did you get image and video support? can you tell me where to go to learn how to do this?

tussiez (1558)

@DerpBurgerPlayz Send an image URL on server, client makes an img element and displays

DerpBurgerPlayz (0)

@tussiez wat -confused derp noises-

tussiez (1558)

@DerpBurgerPlayz ?

  1. Send the url of the image e.g https://hey.foodandmoarfood.repl.co/img/wheat.png

  2. On the website, load the img

const makeImage = (url) => {
return new Promise((resolve,reject) => {
let img = document.createElement('img');
img.setAttribute('src',url);
img.onload = () => { resolve(img) }
});
}
DerpBurgerPlayz (0)

[email protected] oofs, it wont work thanks for the help!

DerpBurgerPlayz (0)

@tussiez in return for helping me, do you want me to tell you how to make a basic custom context menu?

tussiez (1558)

@DerpBurgerPlayz F, here's another

function img(url){
let im = document.createElement('img');
im.setAttribute('src',url);
document.body.appendChild(im);
return im;
}
img('https://hey.foodandmoarfood.repl.co/img/wheat.png');

Try that

CyberHacker101 (113)

When you open this on another tab in doesn't work

inyourface3445 (37)

i get an error when i try to join:

Error: ENOENT: no such file or directory, stat '/home/runner/EekChatlogin.html'
tussiez (1558)

@inyourface3445 try: https://EekChat.tussiez.repl.co
?However this error pops up in Safari. Try Chrome

inyourface3445 (37)

@tussiez it still happens:

Error: ENOENT: no such file or directory, stat '/home/runner/EekChatlogin.html'

using chrome on a mac mini also happens on firefox and safari and chromeinuim

CyberHacker101 (113)

Yoo tussiez ya fixed it. I can help with the CSS I really got a good idea with the profile pic

CyberHacker101 (113)

Why do u keep leaving and coming? @tussiez

ironblockhd (427)

To fix impersonating, set socket.username as the username on the serverside, then you can just read it on every request instead of giving the client control over it

JBloves27 (1753)

Pretty cool! But there is an error with the google login :(

CyberHacker101 (113)

@tussiez yoooooo I just noticed that ur profile pic looks like a deformed cat

programmeruser (580)

This can be spammed to hell with devtools console:

const socket = io();
Array(1000).fill(null).forEach((_,i) => socket.emit('msg', {
  name:'Someone',
  profileImg:'https://repl.it',
  msg:String(i+1),
  time: 'Sorry (can you put a rate limit on msgs?)',
}));
tussiez (1558)

@programmeruser lol
Fixing right now, thanks for telling me about the hack!

Baconman321 (1083)

@programmeruser That's why I now put everything in an anonymous function XD.

programmeruser (580)

@Baconman321 you can just use the io() function to get a reference to a socket.

Baconman321 (1083)

@programmeruser Can't they just use that then?

tussiez (1558)

@Baconman321 The anti-spam is server side

programmeruser (580)

@tussiez

Date.now-sinceLastChat

Date.now() not Date.now

Baconman321 (1083)

@tussiez Good idea. That way they can't tamper with it client side!

programmeruser (580)

@Baconman321 it's so easy to impersonate people

const socket = io();
socket.emit('msg', {
  name:"tussiez's testaccount",
  profileImg:'https://lh6.googleusercontent.com/-dgT6Ex2alT0/AAAAAAAAAAI/AAAAAAAAAAA/AMZuuclrj2vdCjdQSgn1o71wgTFdbZZzdQ/s96-c/photo.jpg',
  msg: 'Hi there!',
  time: new Date().toLocaleString("en-US", {timeZone: "America/New_York"}),
});
tussiez (1558)

@Baconman321 YOu can impersonate people though, will be fixing that will sign on keys or someting

tussiez (1558)

@programmeruser adding signon "keys" thanks again
It sounds sarcastic but this is super helpful

Baconman321 (1083)

@programmeruser If he doesn't enforce strict checking (seeing if that user is in fact registered), then yeah it's quite easy. I don't think encrypting would do the trick, as people can just send the encrypted message. Might want to set a session token so as to make sure people don't impersonate you. That would require bit of effort though...

Baconman321 (1083)

@tussiez Like I mentioned to programmeruser, use session tokens and send that to server-side to make sure people can't impersonate you without the token.

programmeruser (580)

@tussiez also, image xss:

const socket = io();
socket.emit('msg', {
  name:"tussiez's testaccount",
  profileImg:'https://repl.it/logout',
  msg: 'Hi there!',
  time: new Date().toLocaleString("en-US", {timeZone: "America/New_York"}),
});

Check the MIME type of the url:

const url = 'https://repl.it/logout'; //or whatever the url is
(async () => {
  const res = await fetch(url);
  if (res.headers.get('Content-Type').indexOf('image/') === -1) alert('invalid url'); // or whatever
})();
tussiez (1558)

@Baconman321 Should be working now..Idk

programmeruser (580)

@tussiez still insecure:

const socket = io();
const key = Math.floor(Math.random() * 9999);
socket.on('goodtogo', code => {
  socket.emit('checkcode', {code, key, name: window.atob(window.location.href.split('?')[1].split('&')[1])});
  socket.emit('msg', {
    name: "tussiez's testaccount",
    profileImg: 'https://lh3.googleusercontent.com/a-/AOh14GiU7DtwESR0DLRj5aAkBn5DhacdE2HD5B-wMWEN=s96-c',
    msg:'Hi There',
    time: (new Date()).toLocaleString('en-US', {timeZone: "America/New_York"}),
    key
  });
});
socket.emit('account', '');
tussiez (1558)

@programmeruser Maybe key isn't working, but it should be

tussiez (1558)

@tussiez Key is working now, try impersonating again
However, you can see session keys in chat.txt. I'll encrypt that soon.

tussiez (1558)

@tussiez Wait, I don't think so. Nevermind

inyourface3445 (37)

@programmeruser i managed to crash it with this bookmarklet:

javascript: (function(){const socket = io(); Array(1000).fill(null).forEach((_,i) => socket.emit('msg', { name:'Someone', profileImg:'https://repl.it', msg:String(i+1), time: 'Sorry (can you put a rate limit on msgs?)', }));})();
programmeruser (580)

@inyourface3445 that's the exact same thing that I posted before.

tussiez (1558)

@inyourface3445 Should only crash your client, but hmm

programmeruser (580)

@tussiez impersonating still works.

programmeruser (580)

@tussiez solution: use session cookies.

programmeruser (580)

@tussiez also, I think I just broke the chat.

const send = (msg, username) => socket.emit('msg', {
  msg,
  name: username,
  profileImg: '',
  time: ''
});
socket.on('msg', msg => send('Beep boop! You said: ' + msg.msg, 'EekChat Bot #1'));
socket.on('msg', msg => send('Beep boop! You said: ' + msg.msg, 'EekChat Bot #2'));
tussiez (1558)

@programmeruser Absolutely no checks whatsoever! However these kinds of hacks can't really be "blocked"

tussiez (1558)

@tussiez You can only make it more difficult :/