Authenticating with PKI in Angular - javascript

I'm wrestling with trying to authenticate in an AngularJS application using PKI. All of the questions and examples I've seen show authentication using a login/password instead. However, I am running on an intranet, where we use PKI keys consistently. I've read the various suggestions online, but none seem to discuss my particular architecture.
The Angular side contains multiple pages/controllers, and I have no way of controlling which page the user visits first. I need the authorization information on each page.
The application is set up with a NodeJS REST service to get the user's authorizations and other information based on the user's public key (passed in thru the certs). Since the NodeJS service must contact external servers, I want to only invoke it only once, and retain an authorizedUser object (probably in rootScope?)
I've looked at creating services, providers, etc. But none seem to fit this challenge. To summarize:
Authorization using PKI certs, not login/password
Certs used to reach NodeJS REST service, but must only be invoked once
Multiple Angular controllers/pages need authorization information
What would be the best approach here?

OK - I figured it out. My approach was to put the webservice call to the NodeJS backend in the module.run(), and set the $rootScope within the $http.get().success() block. The NodeJS backend gets the certs from the webservice call, and does the lookups it needs to do.
I'm not sure if that's the best approach, but it works for now.

Related

What is the best way to connect two applications using APIS? (An E-commerce and a chatbot)

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.

Implement Authorization in AngularJS

I want to implement authorization in AngularJS. In my project which is some kind of social media, different roles or even same roles may see a view file differently.
For example imagine we have two different roles: customer and company.
A customer and a company may have different things in a shared view file, for example a company can have rate on his profile while a customer can't. (different roles).
Or a customer may see a button in a page while another customer can't. (same roles)
As you can see I can't implement authorization by simply checking the roles, and in some situations I need to communicate to the server.
I have multiple choices:
Create a variable in my controller's scope with corresponding permissions, which they have default value of false:
$scope.auth = {
canRate: false,
isConnected: false
};
Then connect to server and change the value of auth object based on the response. And use ng-if in my view files to show or hide elements.
Create a directive and pass comma-separated permissions to it.
<button auth="canRate,isConnected"></button>
Then connect to server to check the permissions. If all of them where true, then show the element.
Use resolve: {...} and get all necessary data from the server when routing, which increases loading time of each page.
I want to know is there a better approach to solve this problem?
Any kind of help or comment would be greatly appreciated.
Note: Of course I have server side authentication and authorization! I just want to show some elements in a view file based on user roles or some other conditions which I explained. And this elements are something like a button or a link, otherwise instead of using a shared view and hiding elements, I could use different views for each situation.
Any how, I know this approaches are for display purposes only, and they can not solve security challenges.
First things first, I LOVE AngularJS. But, like all web client frameworks, in a strict sense you can't implement Authorization in AngularJS.
You can not trust the web client to hide data from the user. If the server sends the data to the client, they can still find a way to see it (using fiddler for example) even if you use ng-hide to avoid displaying it.
So, you must implement Authorization on the server side. Now then, assuming you do that:
AngularJS is great for building dynamic web interfaces based on the data you receive from the server. So, your server should only send the data your client is allowed to see. Then, you can use ng-hide or ng-if to avoid displaying the components that would otherwise show that data.
Furthermore, your server can even send an object that contains the list of possible actions available to the user. And then you could use ng-hide in your buttons so as not to show them when the action isn't available.
Even still, you will need to code your server side to ignore actions that the user isn't allowed to take.
Your approach will work, but it is not secure. I would make sure that the server handles the authentication as well. Personally, I've always used a server-side token based authentication system when working with AngularJS.
Instead of using ng-if, you should make your GET or POST requests require the token given on login. From there the server can determine whether or not to allow the request to succeed, with no chance of the user faking credentials. Both of your examples work fine, but use them as a means to hide things for display purposes only. The web client will NOT keep sensitive information safe or prevent the possibility of POST requests from unwanted users.

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.

Can I access an API without authentication in JavaScript?

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.

Multiple application instance authentication using OAuth?

First of all, I'm not sure whether this is a Dropbox API or an OAuth question, but maybe some of you can give me some insight of my problem.
I'll explain my scenario.
My application is written in Javascript, and its purpose is to run seamlessly on a screen (fullscreen/browser), fetching some pictures of my account and "slideshowing" them. Nothing too difficult at a first glance. I've managed to authorize my application, store the access token and secret on localstorage for later use. It is working so far.
However, this application will run on lots of screens. This means that on each first run of the app I must be there to enter me credentials in order for that particular application instance to have access to the API. Well, this isn't possible.
After the first run, and after my interaction by entering the credentials, the application would get an access token and then would be able to access the API.
Hard-coding the access token in all instances is possible, but I'm sure this isn't recommended as it poses some threat to my own account.
How can I give authentication to my every application instance (screen) without requiring the owner to interact once for each instance?
Am I missing something?
Thank you.

Categories

Resources