For my CMS component I'm implementing integration with Twitter API to fetch and display list of tweets (either connected to user or search query). I'm using Twitter Restful API v1.1, since the 1.0 version is going to be dropped in two months. Two interesting requests for me are user_timeline and search one.
Since my technology strongly relies on caching I need to avoid server-side processing as much as possible providing static html and piece of javascript. I've done it already for old version API and it worked fine. New approach however requires providing authentication data via OAuth. One of the property (oath_signature) is a hash of other properties (in which there are oauth_timestamp and oath_nonce, which should (should they?) be unique per each twitter request) and secret keys, thus make it unsecure to generate it on client side.
Is there any secure way to get list of tweets on client-side using new API?
The simple answer to your question is, "no, there is no secure way of doing this without server-side code." What I would do is set up a service to poll Twitter every xxxx seconds and retrieve the desired tweets. You should cache or store the results and then empty them each time you make your next request. If you are using C#, I have been working on a C# Twitter library that replicates Twitter's API and already has support for grabbing a user's timeline. I will be adding support for filter and search within the next two days (each one should take no more than ten minutes to implement, excluding testing, if you decide to do it yourself). You can reference this library in the service that I mentioned before.
If you do not have the server resources that you need for this, then I strongly caution you against using solutions that circumvent Twitter's intended securities, as it could leave you or your client in a vulnerable position.
You'll have to write a proxy web service on your server side. And as you say caching will be critical to avoid the 15 requests per 15 minutes for basic stuff like pulling tweets.
Definitely avoid doing any auth stuff on the front end. The new "application only" auth using OAuth 2 would allow you to embed bearer tokens in JavaScript meaning you don't need to do any of the signature stuff you're talking about. But don't. Anyone could use your bearer token and if your own users didn't exhaust the rate limit, other people stealing your token might.
If you don't have the server side resources to do this yoursefl, you might want to look at Flamingo. It'll do the auth and the caching for you, so you only need to work in JS like you used to.
Related
I have two applications settled up. One is a E-commerce (TrayCommerce) that has itself an Api (Oauth), from which I can get order, clients, products information, etc. The other one is a chatbot (Take Blip).
My goal is to make the chatbot retrieve information from the e-commerce's API so I can send it to final user.
I thought in two ways of doing it:
Hosting a javascript code inside the bot, so I can call the API whenever user requests data. However, I don't know how to implement the authentication flow on this approach and how I would, in the future, set up a system to receive notifications from the API to send information each time it is updated, since I can only host one js file per action.
Creating a NodeJS API, which will be hosted on a third party, and that will return the information I want, in a formatted way, to the chatbot. I don't know if this is over-engineering, because I already have an API from the e-commerce.
I am sorry if it is a dumb question, I am new to web development, but any information would be valuable for me to choose a workflow for this integration.
To be able to answer, the right question to ask yourself is the sensitiveness of the data inside the e-commerce; and the power granted to the generated token in the auth implementation.
Typically, a chatbot (assuming a web one) is a piece of Javascript held in the client (browser). This piece of code is perfectly readable by the user, thus you have to assume the generated token could be used to perform a request that you didn't intended him to perform.
So as a simple answer :
If — and only if — the implemented OAuth mecanism lets you limit the scope of authorization to the customer, then you can make the customer authenticate directly with TrayCommerce and the appropriate scopes (and use his token to perform on the API). Said differently, if typically TrayCommerce lets you register your Chatbot as a "client" (this is an OAuth keyword), and generate Auth journeys with appropriate 3-parties flows, granting only something like "orders:view:self" for customers, it's OK.
If the TrayCommerce API is more like a "management API"; with auth implemented in a way that you (yourself, not the customer) have to authenticate on it; then this auth mecanism is not suitable for your use-case. You then have to make an API like you described, that would act like a proxy to TrayCommerce. With considerations (see below).
In the case of you making a "Proxy API" to TrayCommerce; you are basically hiding the TrayCommerce Authentication on your server-side, and shifting that responsibility from TrayCommerce to yourself. In such a case, you have to implement your own authentication (+ authorization) mecanism on this API, to be able not to expose TrayCommerce data to the world.
I have a restaurant locater web application that mashes up the location of restaurants to a Google Maps.
I use JQuery sliders to limit the amount of restaurant to show on the map by having Search filter such as: price, type of food, locale.
These JQuery sliders call back via AJAX to an API I created to update the map without the web page having to refresh.
JQuery calls a RESTFUL API like so:
http://example.com/search/?city=NYC&max-price:50&cuisine=french
This returns a JSON string of restaurants which match this criteria so that my web application can display on the map all the restaurants which match the search.
What I don't want to have happen is for someone to come along and figure out my API and dumps out ALL of my restaurant listings.
Is there a way that I can limit who call the above HTTP API, so that only my web server calls the URL and not spamer/hackers looking to dump my database?
Thanks
First, declare your intentions in robots.txt.
Then, send a Set-Cookie header with a nonce or some kind of unique ID on the main page, but not on your API responses. If the cookie is never sent to your API endpoint, return a 401 Bad Request response, because it's a bot, a very broken browser, or somebody is rejecting your cookies. The Referer header can also be used as an additional check, but it's trivial to fake. Keep track of how many API calls have been made by that ID. You may also want to match IDs to IP addresses. If it goes above your threshold, spit back a 403 Forbidden response. Make your threshold high enough that legitimate users don't get caught by it.
Keep good logs, and highlight 401 and 403 responses.
Realistically, if someone is determined enough, they WILL be able to dump this information. Your goal shouldn't be to make this impossible, because you will never succeed. (See all the usual adages about achieving perfect security.) Instead, you want to make it abundantly clear that:
This behavior violates the terms of service.
You are actively trying to prevent this.
You know that the offender exists and roughly who they are.
Scary lawyers might start getting involved if this continues.
(You do have a lawyer, right?)
To achieve this, be sure the body of your 403 Forbidden response conveys a scary sounding message along the lines of "This request exceeds the maximum allowed usage of the API. Your IP address has been logged. Please refer to the terms of service and obey the directives in robots.txt."
IANAL, but I believe the DMCA can be made to apply in this situation if you claim copyright on your database. This essentially means that if you can track illegal usage of your API to an IP address, you can send a nastygram to their ISP. This should always be a last resort of course.
I don't encourage the use of assigned API keys/tokens because they turn out to be a barrier to adoption and kind of a pain in the neck to manage. As a counter-point to #womp's answer, Google is slowly moving away from their use. Also, I don't think they actually apply in this case, because it sounds like your "API" is more like a JSON call that's used mainly on your own site.
All the big REST API's tend to use tokenized authentication - basically before you do a REST request, you have to send some other request to the token service to fetch a token to include with your data request. Bing Maps does this, Amazon does this, Flickr does this... etc.
I don't know too much about it other than having worked with Bing Maps. You'll need to read up on tokenized authentication with REST. Here's a blog post to get you started: http://www.naildrivin5.com/daveblog5000/?p=35
I have an API that I would like to restrict access to. I can provide access keys and check them with each request, but I'm not sure how far this is really going to go.
The API is used by applications, but it is also used by a web app which someone can just view the source of. If they did, they would have the key and could easily make API calls.
Is there a more reliable way to secure access? I'm not sure what the standard practice here is.
Edit: After thinking about it, I could use a two-prong approach. The web app can use POST with CSRF, and applications can use API keys. Any other ideas, or is this a generally accepted solution? (Note, this still wouldn't work for third-party web apps.)
Your API is never private since it's used by a web app which I am assuming is available to the general public. If this is the case, there really is no impetus to secure it since anyone and everyone would have access to the API.
If on the other hand, this web app is only available to registered users, you can use a token system to check for authorization. When the user successfully logs in, you pass back a token (usually something 20 to 30 characters long). Every API request would require a valid token. Tokens can be set to expire automatically (using a database job) X hours after creation if your application requires higher security thresholds. If security isn't a big issue, they can be renewed automatically every time a request is made.
This is essentially a two tiered approach. Temporary tokens are generated for users to directly connect to your API so that permanent credentials are never sent to the client. Predefined keys are given to third party developers who build applications on top of your API and have their own back-end.
If it's your API you can simply do this.
1) Insert the following code into your API file(s)
$authToken = "APItoken"; //variables
if( !isset($_REQUEST["authToken"]) || $_REQUEST["authToken"] != $authToken )
die("Need auth token");
2) You will now need to GET/POST/PUT the URL like this:
http://www.yoursite.com/api1.php?authToken=APItoken&nextParam=¶mAfterThat=
If this helped please mark it as the answer
EDIT:
Nevermind, read it wrong. Updating answer in a few minutes.
Circumstances
I develope a WebApp with AngularJS.
I've an restful API on server-side with GET and POST commands.
I want to use the API within my module (means: in JavaScript) to display and edit my data.
I want to protect the API with some kind of authentication (basic auth with an API key for example)
I don't want to protect the API when a user uses the app itself
Actual question
Okay, I guess the last point is a bit unclear.
I want that a user can use the app with his browser without any authentication
But when a third-party app want to access the API it have to use authentication
Since JavaScript is executed on client-side of course I can't write a master key into js or something similar..
Is there any kind of pattern or solution to solve this problem?
More specifications
referring to #EliranMalka and #shaunhusain
On the server-side I do use Tornado with it's builtin template engine. I do use the template engine actually just to write the index page and insert CSS, JS dynamically.
The code for authentication would just something like:
def is_authenticated(request):
if 'api_key' in request.arguments:
return sql('SELECT id FROM keys WHERE key=%S' % request.arguments['api_key']).count == 1
My AngularJS module is doing something similar to:
$http.get('/api/foo?api_key=1234')
.then(function (result) {
$scope.data = result.data
});
As you can see I'm writing my API key into js at the moment. But I wan't to avoid this.
Also, what do you mean exactly by third-party?
not a third-party request would be: Using the App on http:/ /app.example.com with a browser
A third-party request would be from an Android app for example. Something that comes from outside or remote.
A JS request from the browser on the actual page would be not from remote (again: since it's JS it is actually from remote - but I hope it gets more clear now)
Oh and before I forget...
I'm aware of that my plan is a bit weird - but it's just a learning(-web-development)-by-doing project.
Also the API key is not absolutely to avoid abusion, it is rather to log 3rd-party usage.
PS I hope my question was clear for you
Hmm, well I'll try to address the questions but here's a few things.
Question isn't really appropriate in it's current format for stackoverflow.com (should be programming questions, I tried X and Y happened) perhaps closer to a StackExchange question but is still fairly open ended.
Include more information about specifics of the languages (and/or frameworks) your using server side and any code you have that is relevant (authentication code?).
Putting the key into the client code and transmitting it from the client means anyone with a web proxy (check out Charles or Wireshark) can grab the key so just to reiterate you're right there that's not the way to go.
Check out how other organizations allow you to get access to their APIs (for example Google, LinkedIn, Facebook, Twitter) to get a feel for how it works. In all of these cases you are signed into the service to be able to make an API key, in some cases you have to specify which domain the requests with that API key will come from. If you use the same precautions and check the API key sent with a request against a database of registered API users and verify the domain in the request then I'd say you're in pretty good shape.
As you may know, pinterest api seems down now.( api.pinterest.com )In this site: http://tijn.bo.lt/pinterest-api, it says that readonly access still works. What does exactly mean ?
I can build an application using this api but cannot use pinning or creating my own board ?
Sorry if my question is too ridiculous, i am very newbie to create an application with an API..
If the API permits read-only alone, that means you can consume data from the source, but you cannot write to it. You could probably get a list of items from your board, but you wouldn't be able to programmatically push a new item to your board.
It's a one-way road, until they open up another lane.
The information posted on that site is a bit out of date.
The API was until recently allowing read/write access, but about two weeks ago Pinterest stopped issuing new access tokens via their original authentication scheme. The new scheme requires API users to generate an oauth signature to receive an access token (needed to use the API), and consequently the API is only accessible to those who have received a client_id and client_secret for their application from Pinterest.
Caveat: if you happen to have an old access_key issued using the old API, you apparently can still use that to make API calls, though I'm guessing those tokens will expire soon.