Secure access to 3rd party API from a Javascript app - javascript

I am creating a web app in Angularjs which displays data from a 3rd party API (json). This is not a free API, I have to pay based on the amount of calls made.
I am given an API key which I call like this:
https://apiservice.com?key=1234567&p1=x&p2=y
I want to ensure that my api key is used only by my web app, so I created a proxy on my server. Now my angular app calls my server like this:
https://myserver.com/myapiproxy/?p1=x&p2=y , the server makes the call to the api using the key that is kept on the server, and returns the json data to the client. This way the key is kept secret.
However there is currently nothing to stop somebody else from calling "myapiproxy" and get the data.
Is there a way to ensure that only my app gets the data and that others can not make calls to the api on my expense?
I searched for a few hours and I couldn't find a truly secure answer. HTTP referer is not a good answer because it can be easily spoofed.

Take a look at JSON Web Tokens - https://jwt.io/
It is a good way to secure your calls. It has angular module - https://github.com/auth0/angular-jwt
When user loads your app you can provide a token jenerate on the backend and store it in local storage.
Than on each api call you can check if this token is authentic.

Related

How to authenticate as Google service account without a client library but only with HTTP Post?

I want to trigger my Cloud Function via HTTP but also authenticated with IAM and a service account auth0-hook I created therefore.
I generated a private key like this:
gcloud iam service-accounts keys create ~/.gcp-keys/auth0-hook-sa.key.json --iam-account=auth0-hooks#my-platform.iam.gserviceaccount.com
and applied this service-account to my cloud function.
On the outside - in the Auth0 Hook code - I know need to fetch the credentials first and send the fetched token with the POST request to the Cloud Function endpoint.
My problem here is that I can not use any of the Google Auth client libraries (Node.js in this case) because Auth0 Hooks can not import any fancy libraries as it seems.
I am hereby stuck with only using var request = require('request#2.56.0'); to make this all work.
I'd like to ask how I can manage this? There is some authentication service I can call right? But what is the API for that one? In the docs I could not find the manual way but only the client library documentations.
I am hereby stuck with only using var request =
require('request#2.56.0'); to make this all work. I'd like to ask how
I can manage this? There is some authentication service I can call
right?
Google does not provide a simple HTTP endpoint that you can call. If you think thru the process, you need the authorization to call an endpoint that generates authorization credentials. Chicken and Egg situation.
Google does not yet accept Auth0 credentials at an endpoint to exchange for Google credentials. However, keep reading for more information about Workload Identity Federation, which can/might provide that ability eventually.
There is no simple answer for your goal of creating an Auth0 hook that can generate a Google Access or Identity Token. Below are details to help understand what is possible.
To go from a Google Cloud service account JSON key file to an Access Token requires libraries also. The process is to create a JWT, sign the JWT, exchange the JWT for an access token. I wrote an article that shows how to do this in Python. The process for Node.js is similar. Your issue is that the process is too complicated for an Auth0 hook.
Google Cloud – Creating OAuth Access Tokens for REST API Calls
Google has recently introduced Google Workload Identity Federation which supports exchanging OIDC tokens for a Google OAuth access token via federation and service account impersonation. The process is just a series of HTTP method calls. I am authoring several articles on how to do this, but I am not finished at this time.
Accessing resources from an OIDC identity provider
One possibility is to create another Cloud Function or Cloud Run service that you can call in a single HTTP GET that creates the tokens for you. That way you can use Google Client libraries. Your Function/Run code would receive an HTTP GET request, interface with the client libraries to create the access token and return the token as the HTTP GET response.
However, that creates the Chicken and Egg situation. You need to authorize the request to the Function/Run code to get an access token.
You may want to change strategies and instead disable Cloud Functions authorization and verify the Auth0 Identity Token within your code and skip Google-based authorization.
Auth0: Validate ID Tokens
Auth0: Validate JSON Web Tokens
Pay attention to whatever process you choose as getting authorization correct and secure is not easy.
Note: Your question states "I want to trigger my Cloud Function via HTTP". I am not sure what method you plan to use. If you are using Cloud Functions Authorization, that requires an OAuth Identity Token. That adds more steps to the process. I have not figured out how to do that with Workload Identity Federation, but the Functions/Run code can easily handle that for you.
In summary, Cloud Functions are intended for small, light-weight code in a serverless framework. Once you add authorization, complexity grows. Provided you stick with Google Cloud authorization, everything is easy. Once you try to go from one identity system (Auth0) to another (Google Cloud IAM) the complexity jumps dramatically.

Flask API to provide JSON files to a simple HTML+JS+CSS webapp while keeping it secure

I've made a simple webapp that is going to show some data in a table, which will be updated weekly.
This update it done in the backend with some python code, that scrapes and alters some data, before putting it in a SQLite database.
After doing some reading I learned that to deliver that data to my webapp I should make a API with Flask, that can take that data and deliver it to the JS in my webapp in form of JSON, which then can use the data to populate the table. However, I should secure my API with username and pw. But as its a JS frontend that will retrieve data from the API, there is really no point, as the username and pw will have to be hardcoded into JS, which then can be read by the users. (I think)
Should I expose my API to everyone, or is this not the way to go to be able to use SQLite data as a backend for my webapp? I am fine keeping the API to a GET only.
You are correct, it is pointless for you to secure your API. Securing an API is only needed in certain circumstances.
If you are accessing data that you don't want anybody to see, perhaps through a backend call, then it would make sense to add in some form of security (normally an API key or Authorisation tokens in your request headers).
However, if you are making calls from your front-end (i.e. client side) to a backend API, then there is no point putting additional security there as the user can already see the request and already has access to the data the API is returning - so by securing it you are achieving nothing.
Normally, if the page the user is visiting contains sensitive data that you don't want everyone to see, you would take steps to secure your website instead (for example protecting it with a login for username and password before you can access that page). If you were to take this approach, where the website is protected by username and password, then you can update the API to make sure it does not respond to requests where the user is not authenticated (e.g. by generating a session token or something unique for each logged in user).
If you have a look around on websites that have lots of free data available, you will find they all have front end API calls that are completely unsecured (because it is pointless if the data is already free to access). Some websites do take steps to try to make sure it is their own website that is calling the API, but even then it is a bit pointless as web scrapers can always extract the data from the HTML.
Take a look at this page which outlines authentication headers. This simpler route is to hard code the header info in Flask to make it a little more secure. You could also try the more involved route of reading header info from your db. What's currently working for me to read from postgres db is below so you may modify it slightly for sqlite.
def valid():
headers = request.headers
auth = headers.get("X-Api-Key")
user = User.query.filter_by(apikey=auth).first_or_404()
print('from search of db ',user,'',auth)
return str(user)
As you mentioned, you plan to show a public data - then it can be used even
without authentication. Otherwise I think it can take too much unnecessary time spent on that.
As you have just a simple and single table from database, I believe that you don't need an API. You can just create HTML template and render it with data. Some examples can be found here and few more here.

How to create an API for our own database using WSO2 API manager

Actually, I want to offer my data from my own database (postgresql) through API.
I want to do it using WSO2 API manager.
I am not sure that I'm doing it in a right way, but suggest me the possibilities.
(i) First I've created a postgresql database.
(ii) did connections and performed CRUD operation using node js.
(iii) used the link ( for example GET verb and the link is http://localhost:8000/v1/api) as the REST endpoint in the WSO2 API manager while publishing the api.
(iv) *****step********
(v) developed a simple html and used Javascript to parse the JSON data and displayed it. ( but I've done it using direct JSON data not with the WSO2 API)
******step********
How to use the consumer key and consumer id to authenticate the API from WSO2 to parse the data through the Javascript
Since you're new to APIM, you should look at WSO2 tutorials.
On a related note:
You can use WSO2 Data Services Server to expose your data (in a database, for example) as a service (REST or SOAP). In your case, you can use it instead of your nodejs implementation. Once you expose your data as a REST services, you can use APIM to front them.
I think you've to register a new user to your api manager (the user that will use the api), the this user has to subscribe to your api.
Once this is done you'll get a token, this token should be provided in the header of your queries (in the js in your case).
You can see examples of call when you access your api in the api store.
Hope it helps

Building my own database of Facebook posts by calling Graph API via Server?

I want to build my own database of Facebook posts by periodically calling the Facebook Graph API and saving the results. User would then communicate with my own database instead of directly with Facebook.
I know that the API calls require an Access token that is generated from your Facebook login. From what I understand, this means the user logging in on the clientside would be using their own access token to make the calls. However, I want to make the calls from the server, which means using my own access token.
To illustrate the process flow:
*SERVER*
myFBAccessToken ---(API call every 15 mins)---> Facebook ---(returns)---> Fb posts ---(save to)---> myDatabase
*CLIENT*
viewFbPosts ---(db call)---> myDatabase
My questions are:
----------------------
1. Is it possible to use a single access token to regularly call the API from server? (Every 15 mins)
2. Will doing so violate any usage limitations on how frequently you can call the API?
3. Does Facebook allow for storing of their content on external databases?
Alternatively, if this is not recommended, does anyone know of a way to get more than the latest 25 posts from the facebook /feed?
I am using MEAN stack (mongodb, expressjs, angularjs, nodejs) with asynchronous functions.
Yes, you can use the same token for the same user multiple times. However, once it expires, you will have to re-login your user again to get a new access token.
There is not an official limitation of number of queries that you are sending to graph API. However, being involved in this sphere for a long time, I found out that 1 query per 1 second is workable for a single user. If you try to exceed it, you will most probably get JSON with error.
You do not have to notify facebook that you are going to store its data in external database. You simply get permitted information using graph API and, afterwards, it is totally up to you what you are going to do with the data. Facebook is responsible for flow of the data from their servers and making sure that you are the person who has a right to get that information on a legal basis.

How to make a web API private

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=&paramAfterThat=
If this helped please mark it as the answer
EDIT:
Nevermind, read it wrong. Updating answer in a few minutes.

Categories

Resources