How to restrict access to Chatting service only to registered websites - django

I am making a chatting service (something like Zendesk) and a website must be registered in order to use the service. There will be a frame which the website owner places in the .html file and the rest is up to me.
Problem
Anyone can start using the service right now (by reading the requests and copying them in Postman). I want a method to restrict access only to those websites that have registered to use the service when the session is started or by the messages sent from that session.
Failed solutions (to give an idea of what I am trying to do)
A stupid idea was to read and send the website URL with JavaScript and check if it exists in the database, but that can easily be forged.
I also tried generating unique tokens for each registered website, but the token is something that must be send with the request for validation and since it is something that public can see (the token is placed with the frame) that token is indeed meaningless. (Maybe I don't understand how tokens work)
At this point, seems like this is inevitable, any Ideas?
(Back-end is written in Django 3.1 and My database tables look like this, if it helps - Ignore the details, just an overview)

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.

Understanding the Client's Responsibilities in OAuth 2.0

I've been trying to learn the inner workings of OAuth 2.0 in my own RESTful app, and I can't seem to find any good explanation of how my Javascript client handles the process.
At this point, I have the client (an Angular 2 SPA) ask the user for their username and password (running Django Rest Framework along with Django Oauth Toolkit). The client makes an AJAX post to the server (specifically to /o/token), and using the resource owner password credentials flow is authenticated and receives the response with the token.
Now, assuming I'm doing everything correctly up to this point, I'm unsure how to properly handle the token from that point forward.
At this point, I'm having my Angular app save the token in a variable and attach the authorization header (with the token) to the calls made to the API. This works as far as granting the correct permissions, but im having a hard time understanding how to maintain persistence of the header (so if the user navigates to a different page, the token is still callable). Initially I stored it in a cookie, but I have concerns with security.
So, first, am I understanding all this correctly? What kind of security concerns should I take into account here? And, of course, how can I save the token on the client?
Yes, you need to store access tokens as user session data because they should be persistent. For example if user leaves your site and then reopens he expects to see himself logged in.
It will be better if you make your sessions server-side: user-agent will store only session ID and all user data will be in your database. User don't need his access token, only your application does.
Instructions for implementation of server-side sessions for Django look pretty simple:
If you want to use a database-backed session, you need to add 'django.contrib.sessions' to your INSTALLED_APPS setting.
Once you have configured your installation, run manage.py migrate to install the single database table that stores session data.

Microsoft sync framework Authentication

I'm very novice when it comes to web applications and ASP.
Recently, I've been experimenting with the Microsoft Sync Toolkit to synchronize databases over a OData web service.
The obvious question here is: Once the service is set up and published - so it is open for anyone knowing the URL - how to prevent unauthorized users from accessing this service.
Please note: Basic authentication of forms authentication - as far my little web development knowledge reaches - doesn't seem to be appropriate for this task, as it's not a web page that the client is trying to reach - where the page can display / or re-direct a logon request - it's a service that we are accessing here.
To make things more difficult, for the client-side syncing I'm using a 3rd party library/sync-provider that only accepts a URL for the service. So, there's no way (I think) I can experiment with incorporating login credentials inside a request header etc.
I assume the best bet would be embedding the login credentials inside the URL and use that for the 3rd party library.
Can somebody please direct me how to to set up such thing on the server? I would prefer to have somehow somewhere in the server-side code a place where I can check for the credentials and based upon it to proceed or abort (return 401) the service request.
I could not find any place where to hook such code into the sync service. Although somebody in MSDN suggested to handle the _OnBeginSyncRequest event, there is no way to access the web-request header from within that method.
Is there by-any-chance a global object accessible from everywhere from which I can access the request header? Could anyone please help with this?
And last, I would prefer a plain User / Password string pair. It should not necessarily (or rather not) have anything to do with windows or directory accounts. I would prefer in my code to simple check against plain strings, such if(userStr == "Authenticated user" && passwordStr == "Correct Password").
if you are using SOAP web service, you can use WS-Security usernametoken which adds your user name and password to the request header, otherwise you can add username and password as parameters in your webservice and then simply validate it on the server side. i.e.
instead of
bool SyncData(datatable)
it becomes
bool SyncData(datatable, username, password)
note for web service you will authenticate per call, if you want to do it per session, you need first login with username password, retrieves a token than on each subsequent call your service with the token.
You would also use SSL to secure the channel so username and password aren't transmitted as plain text.

How do I implement login in a RESTful web service?

I am building a web application with a services layer. The services layer is going to be built using a RESTful design. The thinking is that some time in the future we may build other applications (iPhone, Android, etc.) that use the same services layer as the web application. My question is this - how do I implement login? I think I am having trouble moving from a more traditional verb based design to a resource based design. If I was building this with SOAP I would probably have a method called Login. In REST I should have a resource. I am having difficulty understanding how I should construct my URI for a login. Should it be something like this:
http://myservice/{username}?p={password}
EDIT: The front end web application uses the traditional ASP.NET framework for authentication. However at some point in the authentication process I need to validate the supplied credentials. In a traditional web application I would do a database lookup. But in this scenario I am calling a service instead of doing a database lookup. So I need something in the service that will validate the supplied credentials. And in addition to validating the supplied credentials I probably also need some sort of information about the user after they have successfully authenticated - things like their full name, their ID, etc. I hope this makes the question clearer.
Or am I not thinking about this the right way? I feel like I am having difficulty describing my question correctly.
Corey
As S.Lott pointed out already, we have a two folded things here: Login and authentication
Authentication is out-of-scope here, as this is widely discussed and there is common agreement. However, what do we actually need for a client successfully authenticate itself against a RESTful web service? Right, some kind of token, let's call it access-token.
Client) So, all I need is an access-token, but how to get such RESTfully?
Server) Why not simply creating it?
Client) How comes?
Server) For me an access-token is nothing else than a resource. Thus, I'll create one for you in exchange for your username and password.
Thus, the server could offer the resource URL "/accesstokens", for POSTing the username and password to, returning the link to the newly created resource "/accesstokens/{accesstoken}".
Alternatively, you return a document containing the access-token and a href with the resource's link:
<access-token
id="{access token id goes here; e.g. GUID}"
href="/accesstokens/{id}"
/>
Most probably, you don't actually create the access-token as a subresource and thus, won't include its href in the response.
However, if you do so, the client could generate the link on its behalf or not? No!
Remember, truly RESTful web services link resources together in a way that the client can navigate itself without the need for generating any resource links.
The final question you probably have is if you should POST the username and password as a HTML form or as a document, e.g. XML or JSON - it depends... :-)
You don't "login". You "authenticate". World of difference.
You have lots of authentication alternatives.
HTTP Basic, Digest, NTLM and AWS S3 Authentication
HTTP Basic and Digest authentication. This uses the HTTP_AUTHORIZATION header. This is very nice, very simple. But can lead to a lot of traffic.
Username/Signature authentication. Sometimes called "ID and KEY" authentication. This can use a query string.
?username=this&signature=some-big-hex-digest
This is what places like Amazon use. The username is the "id". The "key" is a digest, similar to the one used for HTTP Digest authentication. Both sides have to agree on the digest to proceed.
Some kind of cookie-based authentication. OpenAM, for example, can be configured as an agent to authenticate and provide a cookie that your RESTful web server can then use. The client would authenticate first, and then provide the cookie with each RESTful request.
Great question, well posed. I really like Patrick's answer. I use something like
-/users/{username}/loginsession
With POST and GET being handled. So I post a new login session with credentials and I can then view the current session as a resource via the GET.
The resource is a login session, and that may have an access token or auth code, expiry, etc.
Oddly enough, my MVC caller must itself present a key/bearer token via a header to prove that it has the right to try and create new login sessions since the MVC site is a client of the API.
Edit
I think some other answers and comments here are solving the issue with an out-of-band shared secret and just authenticating with a header. That's fine in many situations or for service-to-service calls.
The other solution is to flow a token, OAuth or JWT or otherwise, which means the "login" has already taken place by another process, probably a normal login UI in a browser which is based around a form POST.
My answer is for the service that sits behind that UI, assuming you want login and auth and user management placed in a REST service and not in the site MVC code. It IS the user login service.
It also allows other services to "login" and get an expiring token, instead of using a pre-shared key, as well as test scripts in a CLI or Postman.
Since quite a bit has changed since 2011...
If you're open to using a 3rd party tool, and slightly deviating from REST slightly for the web UI, consider http://shiro.apache.org.
Shiro basically gives you a servlet filter purposed for authentication as well as authorization. You can utilize all of the login methods listed by #S.Lott, including a simple form based authentication.
Filter the rest URLs that require authentication, and Shiro will do the rest.
I'm currently using this in my own project and it has worked pretty well for me thus far.
Here's something else people may be interested in.
https://github.com/PE-INTERNATIONAL/shiro-jersey#readme
The first thing to understand about REST is that its a Token based resource access.Unlike traditional ways, access is granted based on token validation. In simple words if you have right token, you can access resources.Now there is lot of whole other stuff for token creation and manipulation.
For your first question, you can design a Restfull API. Credentials(Username and password) will be passed to your service layer.Service layer then validates these credentials and grant a token.Credentials can be either simple username/password or can be SSL certificates. SSL certificates uses the OAUTH protocol and are more secure.
You can design your URI like this-
URI for token request-> http://myservice/some-directory/token?
(You can pass Credentilals in this URI for Token)
To use this token for resource access you can add this [Authorization:Bearer (token)] to your http header.
This token can be utilized by the customer to access different component of your service layer. You can also change the expiry period of this token to prevent misuse.
For your second question one thing you can do is that you grant different token to access different resource components of your service layer. For this you can specify resource parameter in your token, and grand permission based on this field.
You can also follow these links for more information-
http://www.codeproject.com/Articles/687647/Detailed-Tutorial-for-Building-ASP-NET-WebAPI-REST
http://www.vinaysahni.com/best-practices-for-a-pragmatic-restful-api
I have faced the same problem before. Login does not translate nicely to resource based design.
The way I usually handle it is by having Login resource and passing username and password on the parameter string, basically doing
GET on http://myservice/login?u={username}&p={password}
The response is some kind of session or auth string that can then be passed to other APIs for validation.
An alternative to doing GET on the login resource is doing a POST, REST purists will probably not like me now :), and passing in the creds in the body. The response would be the same.

How to stop people stealing from my website?

I consider myself newbie when it comes to securing my web applications.
I have built a website which updates the webpages regularly through an AJAX call. The Ajax call returns a decent JSON object to be used at the client side.
There is a simple problem I need to overcome: How can I prevent other people to use the same AJAX call without permission? What if they build a website, AND at the client side they allow their users to make the same AJAX call to my servers and grab what they need.. AND THEN parse it to their own needs at the client side?
I cannot put an extra layer of security like user authentication.
They won't be able to actually do this from the client directly because the browser will prevent cross domain AJAX requests for anything other than JSONP (scripts). That said, they can proxy it on their server if they want so it doesn't buy you much.
ASP.NET MVC has an antiforgery token mechanism that you should look at for inspiration. The basic idea is that you use both an encrypted cookie and an encrypted, hidden form input containing the same data that you write to each page that you want to secure. Do your AJAX calls using a POST and make sure to send back the form input. On the server-side decrypt the cookie and input and compare the data to ensure they're the same. Since the cookie is tied to your domain, it will be much harder to inject in the request that is being sent back. Use SSL and regenerate the cookie/input content periodically to make it even harder to fake the cookie/input.
You can check the HTTP_REFERER http header and see if the request originates from your page. This can however be spoofed, so don't think of it as a bulletproof solution. The best counter-meassure is user authentication, really.
You can't. That's because you can't differenciate between an AJAX call from your web app and another user's webapp.
Here are some things that might help a little bit.
Obscuring/encrypting your AJAX response. This fails mainly because you have to include the decryption code in your app as well.
Check the IP origin. If the IP didn't access your server before, you can assume that the AJAX call is not from your website. This doesn't work if a) the user switches the IP while being on your site / timing out or b) if another website sends a fake http request first before using your AJAX API.
Another idea would be to send Javascript instead of a JSON object. The Javascript should contain all the logic needed to update your website, and of course could check if the website is your own. (window.location). That has some disadvantages though: more work for you, higher traffic load and it can be broken anyways.
I don't think it's a bad thing actually. Another website could have just as easily scraped the info from your website.
If by "stealing" you mean getting some content from your website (using HTTP GET), that's more or less the same problem as hot-linking. You could have some basic protection technique using the HTTP Referer header (it can be worked around, but it works in most cases).
The other problem you have (making sure the requests come from your application) have to do with CSRF (Cross-Site Request Forgery). There are various protection mechanisms against this, mostly based on embedding tokens in forms for example.
You could potentially combine the two approaches, although the real protection against getting the content would come from user authentication (otherwise, the other site could also get the page from which you're delivering those tokens and proxy it).
(In addition, techniques that rely on remembering the IP address would probably not work well in the whole web architecture: it might cause problems if you get a pool of proxy servers or if the client is a mobile device that may change IP address between various requests, which would be perfectly legitimate.)