2

I encounter a very strange behavior with Braintree dropin UI inside Ionic framework.

So I use the solution: Can't create Braintree client token with customer ID to create the logic for the first time and the return customer.

$http({
          method: 'POST',
          url: 'http://localhost:3000/api/v1/token',
          data: {
            customerId: braintreeReturnCustomerId
          }
        })

As I passed in the customerId in my client view. In my nodejs server, I has a logic to check to see if customerId is undefined. If it is undefined, it is first time customer. If customerId has value, it is return customer. Very straight forward like so:

app.post('/api/v1/token', jsonParser, function (request, response) {

var customerId = request.body.customerId;

 if (customerId == undefined) {

   gateway.clientToken.generate({}, function (err, res) {
    if (err) throw err;
     response.json({
      "client_token": res.clientToken
    });
  });
  } else {
    console.log ("using exsiting customer!");
    gateway.clientToken.generate({
        customerId: customerId
    }, function (err, res) {
    if (err) throw err;
    response.json({
      "client_token": res.clientToken
     });
   });
 }


 });

My client is in an Ionic View. So when I pay it the first time, it knows it is frist time user, then generate customerId for me and I store it in my database. All good. Then WITHOUT refreshing (as Ionic app do not refresh when state change), I go to a different state and go back to the payment state, it does not show the store credit card. Even my server log the customerId and I know FOR SURE the server code is running the "else" part with gateway.clientToken.generate({customerId: customerId} ...

If I force refresh in the view like using

$window.location.reload(true);

right after the first time payment successfully or I just manually refresh the page in my chrome browser (as I am in Ionic Serve), the payment Dropin UI page will show store credit card from the first time payment.

I try disable view caching like "cache: false". But it does not help. I have to force refresh to make the Dropin UI works for the second time. I think it is the javascript code in dropin UI causing this issue but I do not know how to fix it...

Community
  • 1
  • 1
Hugh Hou
  • 2,344
  • 5
  • 31
  • 55

1 Answers1

4

Full disclosure: I work at Braintree. If you have any further questions, feel free to contact support.

The approach you've posted is extremely unsafe as it is vulnerable to Insecure Direct Object Reference (OWASP Top 10) and can easily result in cross-user charging by a nefarious user. You've essentially allowed any user to use your server to generate client tokens for any customer.

Instead, you should only generate tokens on the server to avoid user agents from choosing the id of another user. Then serve up customer ids based on a user's credentialed login and not allow them to pass in parameters to be used during clientToken generation. There are many guides online on how to build authentication. But once you have the user created on the server you can:

if (userSession == undefined) {
    //or force login if you want them to sign up for your site before buying things
    gateway.clientToken.generate({}, function (err, res) {
        if (err) throw err;
        response.json({
            "client_token": res.clientToken
        });
    });
} else {
    console.log ("using exsiting customer!");
    gateway.clientToken.generate({
        customerId: userSession.user.BraintreeId
    }, function (err, res) {
        if (err) throw err;
        response.json({
            "client_token": res.clientToken
        });
    });
}

Whatever you do don't use this code, as-is, in production. I wouldn't advise debugging the front-end until you've rebuilt to fix this vulnerability as the approach will be quite different. However, if you do come back to this problem again it looks like there might be an open issue related this behavior.

Raymond Berg
  • 860
  • 5
  • 17
  • Wow. Thank you for pointing out this problem. But I do not do any server side authentication b/c I use Firebase. Here is my solution to address this issue: http://stackoverflow.com/questions/32573992/how-to-structure-my-app-to-use-firebase-braintree-ionic-angularjs-and-a-minim Could you tell me if this Firebase approach meet the OWASP standard? – Hugh Hou Sep 14 '15 at 23:24
  • @HughHou, while I don’t have experience with Firebase, the introduction of a trusted third party to perform authentication/id generation is akin to having your own server generating/storing this information. I can’t comment on your specific implementation, but generally that is a decent direction to avoid clients generating/faking customer ids. – Raymond Berg Sep 15 '15 at 14:18