Problem with identifying user, Build chat app without login - cookies

I want to build an in-app chat application without any login.
So, the user communicates with the program (the backend), not with other user. So, it's a chatbot.
My question is: How to identify the user? Should I just log the IP address? Or, should I generate a random ID on server? Or, should I just generate it on the client?

As I understand, the purpose of identifying the user is for the server to keep track of who is sending the chat message and to send back the response to the appropriate client (user). IP address can't be reliably used as a way of uniquely identifying the user because of numerous reasons (it is a separate topic). One example of it would be this - A small company routes all the outgoing traffic from its office network via a single router that has a single IP address. In this case, the requests coming from different employees of that company would have same IP address as detected by the chat server. So it can't distinguish between these users.
The idea of generating unique identifier on the server for each user can work. A UUID or a JWT or something similar can be used to generate the id when the user initiates the chat for the very first time. This ID needs to be passed back to the client so that clients (users) can send the subsequent chat messages using the same ID. Thus, in this model, the client would need to have a place to store this ID so that it can keep passing it back to the server in its chat messages. Now the problem can happen when the client loses this ID. How can we recover from this situation? The answer would be similar to the approaches being used when someone loses their password. There are several recovery mechanisms such as sending the reset link on the trusted email address or sending it on user's phone as a code or generating a recovery key which is different from the ID and emailing it out to the user which can later be used to reset the ID. Basically, there should be an alternate and secure way (recovery flow) to identify the user if the ID is lost.
If the ID is generated on the client side, that can also work as long as all the clients are able to generate the ID that is guaranteed to be unique. Clients can pass in the generated ID to the server and server can check if it is already used and send a retry message to the client if it finds that it is already used. Or if the clients are using some hardware that has unique serial number and that serial number can be used to generate the ID.
In either cases, all the requests must pass in the ID to the server so that server can do the identification.
Hope this helps!

Related

Is it possible to send data from a client to a server without the API being public?

I'm currently trying to make an account signup page for a small project I'm working on and I don't know how to send data back to the server (I'm using the Flask framework) without also allowing everyone to send data. Let's say that I've set up an API endpoint on /createAccount. I can then send POST requests to that endpoint: {"username": "test", "password": "test"}. The web server will then handle that request by inserting that data into a database and responding with 201. The problem is, anybody would be able to send these requests, and I only want users to be able to register through the login page, and not by making an API call. Is there any way of doing this?
Edit: I've given this problem a bit more thought and I think that the only API that is difficult to secure is the signup API. When a user has created an account, I can just assign them an API key, which they will send to the API every time they want to make a request, which means that an account is required to make API calls. If a certain key is making too many requests, they can be rate limited or temporarily banned from making further requests. The problem with the signup API however, is that there is no information by witch a request sender could be identified. I could use the IP address, but that can be changed and wouldn't really help if multiple IPs are spamming the API at the same time. Is there a way I can identify non-registered users?
Short answer: no.
You have to check data to make sure the account being created is something legit and not trash data to fill your database or any other malicious intents.
This is the reason you usually have to confirm an account clicking on a confirmation link sent to your mail: this way the app is sure that your account is legit.
You could also check info on the front end, but that is never as secure as back end checking, because of your concern in the question: in the end, anyone who gets to know your endpoints could potentially send direct requests to your server with whatever data they wanted.
Assuming you have a trusted source of registrations, an if that source can make an ssh connection to the server where your Flask app is running, an alternative to trying to lock down a registration API is to provide a command line script to do the registration.
The trusted source does something like
ssh someuser#youripaddress /path/to/register.py "username" "password" "other info"
If you use a Flask custom command you can share model definitions db configuration.

How to use custom id as session id in Flask Socket IO

I am using flask socket-io for a basic chat app. But I have a problem. When my device connect to server, flask give to device a session id. But after disconnect and again connect, session id changes. So, this device can't receive old room's messages. I thought if I'd do if I assign custom session id to device.Is it true? Or what is your suggestions?
The session ids are supposed to be unique, even when a client reconnects. There is no way for an application to choose these ids, they are random numbers chosen by the server.
What you need to do is map a session id to your user information in the connect event, and remove the mapping in the disconnect event. That way at any time you can find out what session id a user is currently on. If you need specific room assignments, those need to be done upon connection, and undone on disconnection.

Recording Google Analytics Goal by API

Is it possible to use userID and the API to record a user having done an event (i.e. reached a goal) by API?
For example, if I set up my GA installation to record userID for logged in users, but the Goal I want to record is something that happens when the user is offline.
Can I use an API somehow to tell Google "User 001 completed Goal X"?
Or, alternatively, can I pull a unique identifier from a user's cookie, store it on my server side linked to the user id, and fake a js call back to Google once the goal is reached, as if the user were viewing a success page?
You can fetch the client id from the cookie. Google recommends to use their get function:
ga(function(tracker) {
var clientId = tracker.get('clientId');
});
as
developers should not directly access the cookie analytics.js sets as
the cookie format might change without warning.
You can then send an event or virtual url using the measurement protocol and set up a goal based on that url or event (btw. there is nothing "fake" about it, this is exactly the thing the measurement protocol is supposed to cover).
The caveat is that the data will probably end up in a new session, so the original source might get lost (that's an issue if you do advertising).
Another approach, if your users are usually logged in, would be the User-ID feature (despite it's name it does not ID individual users, but it allows to collect user data across devices as long as an unique ID is sent per user from each device. The Id is not exposed in the interface).
You would again use the measurement protocol but this time send along the user id (you still need to send a client id, but it will be overwritten by the user id). If you enable session unification the logged-in visits of the users (and your measurement protocol calls) will be stitched together into a user-level reporting (this required a special data view which will include only data from visits that have a User Id set). Unlike the client id, which is generated by the Google Analytics Javascript code, the User ID is generated on your server and passed in to GA.

Choosing the right place to write logic in a client/api/server solution

I'm currently designing a solution with this pretty standard pattern:
1 web-app using Django (it hosts the one and only DB)
1 client mobile app using AngularJS
This client app uses a REST API (implemented on the Django Server with Tastypie) to get and set data.
As a beginner in these architectures, I'm just asking myself where the logic should go and I'd like to use a simple example case to answer my concerns:
On the mobile client App, a client is asked to subscribe by entering only an email address in a form.
a) If the address is unused, inscription is done (stuff is written on the DB).
b) If the address is used, an error is raised, and the user is asked to try again.
What is the workflow to perform these simple operations?
I'm asking for example how to compare the entered e-mail address in the mobile app with the existing e-mail adresses in my DB:
Should I GET the list of all email adresses from the server, then perform the logic in my client app to state if the entered address already exists ? This seems really a bad way to do because getting lots of elements isn't performant with web services, and client should not be able to see all email adresses.
Should I send the entered e-mail address to the server and let it make the comparison? But if yes, how am I supposed to send the data? As far as I know, PUT/POST are made to write in the DB, not to just send data to server to analyse it and proceed some logic.
I have the feeling I am clearly missing something here...
Thanks a lot for help.
PUT and POST are designed to be used to create and update resources. The server may or may not have a database behind it. It might use a local filesystem, or it might handle anything in memory. It's none of the client's business. It is certainly common to have business logic on most servers which provide APIs.
Use PUT/POST to send up the email address to the server. The server checks to see if the email address is (a) valid, and (b) allowed. If it fails either check, return a relevant response to the client as documented in the RFC. I would go with 403 Forbidden, which indicates a problem with the data being sent up to the server. Use the entity in the response to detail what the problem was with the request.
I had done similar thing in a angular web app,
I have disabled the submit button, and added a check availability button beside the email field.
I have send the email to server and checked if it already exist and got the result to client,
then asked the user to enter an alternate email if not valid or enable the form's submit button
Alternatively
when the user leaves the email field, You can send the email to a service that validates the email, and get the response, and show a message that this email already exist and disable the submit, or enable the submit button otherwise

Sessions in REST services

I'm developing small REST service which should support client session persistence. As you know because of REST we can't store any client data on the server, data must be stored on client side and client's request must be self-sufficient. So...how we can store client sessions? Searching over the internet I've found some methods how to realize this. For example: we send to the client encrypted token which contains client's id(nick...etc), like token = AES(id, secretKey); and then we're authorize user every request decrypting token on the server with secret key. Can anyone advise anything? Maybe there is another good ways to do same functionality. Which crypto algorithm will be preferable for this? Thanks.
You mentioned:
As you know because of REST we can't store any client data on the
server, data must be stored on client side and client's request must
be self-sufficient.
REST doesn't say you can't store client data on the server; it just says you shouldn't store application state there, which you can think of as "what this client is in the middle of trying to do".
If you are primarily trying to just have a concept of authenticated users, then a standard login cookie will work just fine and is not "unRESTful".
It all comes down to your answer to this question: why do you need a "session" concept in the first place?
If you need to ensure that the client passes a cookie representing a set of credentials, consider instead having the client pass them as HTTPS authentication headers with each request instead.
If you need some sticky routing rules to be followed (to make sure that the client's request gets sent to a particular server), consider using this opportunity to get rid of that architectural straightjacket as it is the quickest way to kill your chances of future scalability. Instead, make your server choice arbitrary.
If you absolutely must route to a specific node, try requiring that the client pass enough identification data that you can use it to hash or shard the client down a particular "swim lane". You could split things up based on their username, for example.