Monday, April 12, 2021
  • Setup menu at Appearance » Menus and assign menu to Top Bar Navigation
Advertisement
  • AI Development
    • Artificial Intelligence
    • Machine Learning
    • Neural Networks
    • Learn to Code
  • Data
    • Blockchain
    • Big Data
    • Data Science
  • IT Security
    • Internet Privacy
    • Internet Security
  • Marketing
    • Digital Marketing
    • Marketing Technology
  • Technology Companies
  • Crypto News
No Result
View All Result
NikolaNews
  • AI Development
    • Artificial Intelligence
    • Machine Learning
    • Neural Networks
    • Learn to Code
  • Data
    • Blockchain
    • Big Data
    • Data Science
  • IT Security
    • Internet Privacy
    • Internet Security
  • Marketing
    • Digital Marketing
    • Marketing Technology
  • Technology Companies
  • Crypto News
No Result
View All Result
NikolaNews
No Result
View All Result
Home Technology Companies

Authorize with a Cloudant proxy

January 17, 2019
in Technology Companies
Scan your app to find and fix OWASP Top 10
587
SHARES
3.3k
VIEWS
Share on FacebookShare on Twitter

Credit: IBM

Safeguard your application with another line of defense

You might also like

Day 1 inside the digital ops center – IBM Developer

AIOps & Integration on April 20 – IBM Developer

Build and run regulated workloads in the cloud – IBM Developer


SQL databases have fine-grained access control. (For an example, see the
article entitled “Row and column access control” in the IBM Knowledge Center.) In
contrast, a user in a Cloudant® database can have read and/or write
permissions to the whole database or not have them at all. This limitation
removes one of the safeguards on the information in the database, and
requires more trust in the application programmers.

In this tutorial, you learn how to create a Cloudant proxy in Node.js.
Because you write that proxy’s code, you can put whatever security checks
you want into it.

Try IBM Cloud for free

Build your next app quickly and easily with IBM Cloud Lite. Your free account never expires, and you get
256 MB of Cloud Foundry runtime memory, plus 2 GB with Kubernetes
Clusters. Get all the details and find out how to get started. And if
you’re new to IBM Cloud, check out the IBM Cloud Essentials course on developerWorks.

What you’ll need to build your
application

  • Basic knowledge of IBM Cloud, Node.js, Cloudant, and JavaScript
  • An IBM Cloud Lite account (it’s free!)

Run the appGet the code

The
sample application

The sample application is a bank account system. There are three accounts:
alice, bill, and carol. Each account has a certain balance. The desired
behavior is to allow users to transfer money to one another, but not to
themselves. This application is implemented by using Cloudant and
OpenWhisk. To learn how to write such an application, see sections 1, 2,
4, and 5 of “Build a smart lock for a connected environment.” You can also
access the source code that is associated with that tutorial.

“Note that this type of policy, which explicitly forbids
some actions and implicitly allows everything else, is acceptable here
only because the application is so simple. In a production system, it
is best practice to have a policy that explicitly allows actions that
are permitted, and implicitly denies everything else.”

Step 1. Capture and relay HTTPS traffic

Because
some of the parameters are encoded in the path name, the proxy cannot run
as an OpenWhisk API application—therefore, I chose to write it as a
Cloud Foundry Node.js application. I describe the method of doing this in
my article “Add your own authorization proxy to a third-party app.”

There is one important difference between the use case that is described in that
article and the use case discussed in this article. Cloudant uses HTTP basic
authentication. This means that authentication information is part of the
header the client sends to the proxy. That information needs to be removed
from the header before sending the request to the server:

headers["authorization"] = null;

When you create the proxied request, add the server’s authentication
information. The added lines are lines 7–10.

	// The options that go in the HTTP header
	var proxiedReqOpts = {
	      host: cloudantCred.host,
	      path: req.path + query,
	      method: req.method,
	      headers: headers,
	      auth: {
	      	type: "basic",
	      	username: cloudantCred.username,
	      	password: cloudantCred.password,	      	
	      }
	};

The easiest way to do authorization is by using a separate middleware call.
Use a
function that gets HTTP requests, such as
app.all("*", function(req,
res, next) { … });
. The third
parameter (here called next) is a function to call to return
the request for further processing.

            // The authorization logic
app.all("*", /* @callback */ function(req, res, next) {
.
.
.
	next();
});

If the request is not authorized, set the response code to 401, and respond
with Unauthorized.

if (   unauthorized   ) {
		res.status(401).send('Unauthorized');
		return ; // No need to continue this function
	}

Step 2. Get the relevant fields

The next step is to identify the fields in the request to make
authorization decisions.

Logging

It is useful to have a temporary log to be able to see the requests and how
they are parsed by the code. To do this, have a log string and display it
when asked:

var log = "";
app.get("/log", /* @callback */ function(req, res) {
	res.send(log);	
});

Anytime you want to add something to the log, you can add it as HTML. For
example, it is useful to have a line separating different requests:

log += "<hr />";

User and password

The user and password are available as the authorization parameter in the
HTTP header. The way that they are provided is a bit complicated, but this code retrieves
them:

	if (req.headers.authorized !== null) {
		var origAuth = new Buffer(req.headers.authorization.replace("Basic ", ""), 'base64').toString('ascii');  	
		var arr = origAuth.split(":");
		user = arr[0];
		password = arr[1];
	}

Request fields

	log += "<h2>User: " + user + "</h2>";
	log += req.method + " " + req.path;
	if (req.body !== undefined)
		log += "<h4>Body:</h4>" + req.body;

Look at the log—these are the results of a single transaction:

log results

log results

As you can see, the application first reads the account for one user,
updates the balance for that user, and then repeats for the other user.
For GET requests, the user ID is in the path. For POST requests, it is in
the body, which is in JSON, as the _id attribute.

The following code gets the ID and balance (if available) for both methods.
It uses the switch construct, and looks for the information
either in the path or the body.

	switch (req.method) {
		case "GET":
			id = req.path.replace(//.+//, "");
			break;
		case "POST":	
			var reqBody = JSON.parse(req.body);
			id = reqBody._id;
			balance = reqBody.balance;
			break;
	}

Context

You want to prevent users from increasing their own bank balance. However,
you can’t get that information from the GET and
POST requests. You need to know the existing balance before
the POST changes it. There are two ways to find out the
balance:

  • Submit a GET request from the proxy when you get a
    POST to modify an account balance.
  • Keep track of balances that you return to the application as responses
    to GET requests. There is no need to also look at
    POST requests because any request to update the balance
    is going to be preceded by a GET. (See “Document Versioning and
    MVCC
    .”)

If there is only one instance of the proxy running at a time, then the
second method is much more efficient. To do it, create an empty hash table
as a global variable:

var knownBalance = {};

In the code that returns a response to the application, check whether there is a
balance that is being reported and if so update the hash table. The added lines
are lines 4–9.

	var proxiedReq = http.request(proxiedReqOpts, function(proxiedRes) {		
		proxiedRes.on("data", function(chunk) {retVal += chunk;});
		proxiedRes.on("end", function() {
			var acctInfo = JSON.parse(retVal);
			
			// If we know about a user 
			if (acctInfo._id !== undefined) {
				knownBalance[acctInfo._id] = acctInfo.balance;
			}
			
			res.send(retVal);
		});
		proxiedRes.on("error", function(err) {res.send(JSON.stringify(err) + "<hr />" + retVal);});
	});

Step 3. Write the authorization code

Armed with all this information, you can now actually write the
authorization code. In this case, you need to check whether the user is the
same as the account that is being changed. If so, check if the balance is
increased and if that is so, deny the transaction:

	// The only case where we deny authorization
	if ((id === user) && (balance > knownBalance[id])) {
		res.status(401).send('Unauthorized');
		return ; // No need to continue this function
	}

Note that this type of policy, which explicitly forbids some actions and
implicitly allows everything else, is acceptable here only because the
application is so simple. In a production system, it is best practice to
have a policy that explicitly allows actions that are permitted, and
implicitly denies everything else.

Potential pitfall: Transaction rollback

An important consideration when you use such a proxy is that the application
must be able to roll back forbidden operations. For example, in
the case of the sample application, a transfer of money from Bill to Alice
looks at the proxy (and the database beyond it) as two change
operations:

  1. Deduct the money from Bill’s balance
  2. Add the money to Alice’s balance

If the first operation is allowed but the second is denied (for example,
because Alice is also the user), the money from Bill’s account disappears.
This is undesirable behavior, which is difficult to prevent in the
proxy.

A properly written application is written with the assumption that database
operations can fail, and has code to deal with it. Here, the
modifyAccount function has two callbacks: one called in the
case of success, the other in the case of failure.

// Modify a bank account
var modifyAccount = (user, amount, cloudantUrl, callback, errCallback) => {
    var db = require("cloudant")(cloudantUrl).db.use("accounts");
    
    db.get(user, (err, res) => {
        res.balance += amount;
        db.insert(res, (err, body) => {
            errMsg = JSON.stringify(err);
            if (err === null)
                callback();
            else
                errCallback();
        }); // end of db.insert
    });  // end of db.get
};

The function that calls modifyAccount uses the failure
callback of the inner call (the later one) to undo the outer call (the one
that happens first).

    modifyAccount(params.fromUser, -params.amount, cloudantUrl, 
        () => {
            modifyAccount(params.toUser, +params.amount, cloudantUrl, 
                () => { returnHtml(success); }, 
                () => { 
                    // Before reporting the error, undo the outer modifyAccount, which did succeed.
                    modifyAccount(params.fromUser, +params.amount, cloudantUrl, 
                        () => {errorMessage(success);},
                        () => {errorMessage(success);})   // End of undo modifyAccount
                }  // end of failure function for inner modifyAccount
            ); // end of inner modifyAccount call
        },
        () => { errorMessage(success); }
    ); // end of outer modifyAccount call

If the application is not written with such a rollback function, providing
authorization in a proxy without causing an inconsistent state is more
difficult. You might be able to do it by caching all the changes that
relate to a specific transaction, but to do so you would have to figure
out a way to identify individual transactions. This might be possible, but
it depends on the application itself. There is no general method to do
it.

Conclusion

A Cloudant proxy cannot replace security in the application because it has
a lot less information and a much more restricted ability to communicate
with the user. However, as a component of “defense in depth,” it can be
another line of defense that an attacker would need to break through. This
proxy can also provide for a log of operations that is independent from
the application, in case an attacker breaks into the application
server.


Downloadable resources

Related topics

Credit: IBM

Previous Post

Over 87GB of email addresses and passwords exposed in Collection 1 dump

Next Post

Sophia: The Overhyped Toaster – Becoming Human: Artificial Intelligence Magazine

Related Posts

Six courses to build your technology skills in 2021 – IBM Developer
Technology Companies

Day 1 inside the digital ops center – IBM Developer

April 10, 2021
Six courses to build your technology skills in 2021 – IBM Developer
Technology Companies

AIOps & Integration on April 20 – IBM Developer

April 10, 2021
Build and run regulated workloads in the cloud – IBM Developer
Technology Companies

Build and run regulated workloads in the cloud – IBM Developer

April 9, 2021
Six courses to build your technology skills in 2021 – IBM Developer
Technology Companies

How a growing ecosystem of 90+ partners creates opportunities for clients with IBM Cloud for Financial Services – IBM Developer

April 7, 2021
Six courses to build your technology skills in 2021 – IBM Developer
Technology Companies

Round 1 – IBM Developer

April 7, 2021
Next Post
Sophia: The Overhyped Toaster – Becoming Human: Artificial Intelligence Magazine

Sophia: The Overhyped Toaster – Becoming Human: Artificial Intelligence Magazine

Leave a Reply Cancel reply

Your email address will not be published. Required fields are marked *

Recommended

Plasticity in Deep Learning: Dynamic Adaptations for AI Self-Driving Cars

Plasticity in Deep Learning: Dynamic Adaptations for AI Self-Driving Cars

January 6, 2019
Microsoft, Google Use Artificial Intelligence to Fight Hackers

Microsoft, Google Use Artificial Intelligence to Fight Hackers

January 6, 2019

Categories

  • Artificial Intelligence
  • Big Data
  • Blockchain
  • Crypto News
  • Data Science
  • Digital Marketing
  • Internet Privacy
  • Internet Security
  • Learn to Code
  • Machine Learning
  • Marketing Technology
  • Neural Networks
  • Technology Companies

Don't miss it

Cambridge Quantum Computing Pioneers Quantum Machine Learning Methods for Reasoning
Machine Learning

Cambridge Quantum Computing Pioneers Quantum Machine Learning Methods for Reasoning

April 11, 2021
Why Machine Learning Over Artificial Intelligence?
Machine Learning

Why Machine Learning Over Artificial Intelligence?

April 11, 2021
27 million galaxy morphologies quantified and cataloged with the help of machine learning
Machine Learning

27 million galaxy morphologies quantified and cataloged with the help of machine learning

April 11, 2021
Machine learning and big data needed to learn the language of cancer and Alzheimer’s
Machine Learning

Machine learning and big data needed to learn the language of cancer and Alzheimer’s

April 11, 2021
Job Scope For MSBI In 2021
Data Science

Job Scope For MSBI In 2021

April 11, 2021
Basic laws of physics spruce up machine learning
Machine Learning

New machine learning method accurately predicts battery state of health

April 11, 2021
NikolaNews

NikolaNews.com is an online News Portal which aims to share news about blockchain, AI, Big Data, and Data Privacy and more!

What’s New Here?

  • Cambridge Quantum Computing Pioneers Quantum Machine Learning Methods for Reasoning April 11, 2021
  • Why Machine Learning Over Artificial Intelligence? April 11, 2021
  • 27 million galaxy morphologies quantified and cataloged with the help of machine learning April 11, 2021
  • Machine learning and big data needed to learn the language of cancer and Alzheimer’s April 11, 2021

Subscribe to get more!

© 2019 NikolaNews.com - Global Tech Updates

No Result
View All Result
  • AI Development
    • Artificial Intelligence
    • Machine Learning
    • Neural Networks
    • Learn to Code
  • Data
    • Blockchain
    • Big Data
    • Data Science
  • IT Security
    • Internet Privacy
    • Internet Security
  • Marketing
    • Digital Marketing
    • Marketing Technology
  • Technology Companies
  • Crypto News

© 2019 NikolaNews.com - Global Tech Updates