How to implement 3d secure payment securely - security

I'm wondering what's the best way of accepting payments from credit cards that require 3-D Secure verification. Currently the checkout flow is like this:
Customer submits payment
Payment gateway returns an error stating that the card requires 3-D secure code processing. Returns the ACS URL in the response
I redirect user to the issuing bank's verification site and I pass a callback URL for the ACS to redirect after completion of verification
Customer enters verification code and ACS redirects to the callback URL with an authorization token indicating successful verification
To complete the process, I have to resubmit the original request with the authorization token to the payment gateway
My problem is in the final step. As I need to resubmit the original request (which contains the credit card information of the customer), I need to store it somewhere temporarily so I can retrieve it when the callback URL is called. Is there an alternative to this?
I'm thinking of trying an iframe solution: The original form is never closed and I display the verification process in an iframe. When the process completes, i.e. the callback url is called, I hide the iframe and update the original form with the needed values and resubmit. Has anyone tried this technique before?

As you might already noticed in article you linked, presenting bank's page in iframe is a preferred option. Although if you read in further, it presents other security features, specifically in regard to phishing protection. Because your client won't know to whom is he really sending his password.
But going back to your proposition, if you present it in iframe or popup window, you would be able to store the original form on your base page and then resubmit it with received authentication token. It's a very good idea because you would not need to do any PCI compliance stuff. So not only it's easier for you it is recommended :).

With Sage Pay (and I would assume other payment providers) you don't need to pass the full order information again in the last step, just the response code from the 3D Secure form and a unique transaction reference. Storing the card details is therefore not necessary.
For me the process is:
Card details etc. and unique transaction reference submitted to payment gateway.
Payment gateway responds with 3D secure details (ACSURL and reference codes).
Redirect user to 3D Secure form (passing ref codes and callback URL) where they enter their details.
Verification code passed back to callback URL.
Server must send the verification code and same transaction reference from step 1 to the payment gateway.
Payment gateway responds with success/failure information.

I've done some recent work with 3d secure. From my personal experience:
I pass the credit card information with a forward url to the banks
3d secure url.
The user is redirected to the 3d secure url and prompted to type in his password.
When he clicks continue, the user is passed to the forward url with the authorization token -- the credit card information gets passed along as well.

Related

Protecting POST route without password possible?

Noob here working on first backend project.
What I’m trying to do...
Collect member data via my form (name, email)
User clicks paypal button to pay for membership
When payment approved by paypal, send post request with form data to my members endpoint to add new member
I now realize if I use postman to post to my members endpoint it works. So a malicious user could post data to my members endpoint regardless of paypals payment approval.
My understanding so far is that if my server allows CORS and I don’t password verify the user, anyone can post to that endpoint.
Is it possible to allow post requests only after payment approval without the use of a password?
I’m thinking of online stores that let you checkout without a password. How do they post the collected form data to their db without jeopardizing their post route?
Hope this wasn’t too vague. Pointers would be greatly appreciated!
I’m using node/express, but since it’s a general question I assume it doesn’t really matter..
These answers helped but still didn’t get me there.
Protecting post routes NodeJS
Can I only accept traffic from certain requesting domains with Expressjs?
So post / get request in general are functions of the browser and or server, I can create a simple html form and post to any URL I want to.. Now the question is, will it accept it or not.
When communicating between servers and web-services unless open to the public will use token based authentication to validate the request. So in terms of paypal, the typical flow would be.
(note, very oversimplification below and is just a sample of one such pattern)
User clicks paypal button from your site ( this will contain some type of paypal ID of sorts )
User is directed to paypal and after completing the transaction paypal redirects users back to your server with a token
your server reads the token ( sends API call to paypal with token to verify its valid, if success then process the post )
You can't prevent a user from posting data to a URL, however you can tell the server what to do if they do. So protecting your route from unauthorized post can be handled by sessions, tokens etc. For example, if you have a route on your server, lets call it user profile. This route first executes a check for the session, if its there keep processing, if its not, redirect the user.. Its really no different for callbacks / token auth.
Essentially, you will need to handle what the server does in your code because anyone can post to the endpoint.
To your other question about how companies handle guest checkouts, this can be done a few ways but one way is to create your own token, this token would be an encrypted string that may contain a cart ID, time etc.
When a user clicks 'checkout' the token is generated and passed to the server via a get or post request. From there your server decodes the token and if everything is correct processes the order otherwise it kicks it back.
Again, you see a lot of token based stuff here going on and that because there is an X factor in all of this.. the user.. We know who the server is but the user can be from anywhere and the user isn't a server so we need some way to maintain state between servers, hence tokens, encryption, JWT etc

How to automatically capture an authorized order in PAYPAL API using nodejs?

(Unfortunately, after a long research I could not find the answer for my question in stackoverflow).
I am currently integrating the PAYPAL REST API V2 in an e-commerce application and in principle it works fine, but not the way it is supposed to.
According to the documentation I am using the following steps:
Create order with user data and purchase details in the backend (nodejs)
Upon successful order creation, the front-end receives the approve_url and capture_url
The user is redirected to the approve_url and login with its credentials, and in case it is successful, the user is redirected to the predefined return_url (which is defined in the step 1)
If the user agrees with the order, the capture_url is manually called at the end of the checkout and the corresponding amount is transferred.
Since the data returned by the order is not persistent (url is being redirected), I am saving the order id and the capture_link in the local storage, which I don't think it is correct. Therefore, I have two questions:
Upon successful approval of the purchase, is it possible to redirect the user directly to capture?
If not, how can I get the order_id details in the return_url?
Thanks in advance
I figured out that the order Id was being appended to the return_url automatically. The misleading thing was that it was named token instead of order. With the order already approved by the user, I was able to complete the transaction without having to redirect the user again to the front-end.

paypal rest sdk - cancel a payment gives only token

so i've seen some question about this subject but no good answer
after creating a paypal payment via paypal api, the client is being redirected to paypal for payment approval
the payment object also gets a "approved" and "cancelled" urls so that paypal could let my server know what course of action took place within the client's approval process
if the client has cancelled the payment, the http request being sent from paypal looks like this:
/customerCancelled?token=EC-32W183225U612050A
when "customerCancelled" is a get method in my server of course
what paypal claims should be done here is just to cancel the payment in my DB because they already cancel it on theirs
the problem is here - what the hack is this token? its not the paymentID (which is the primary key of the payments in my database)
how does it help me identifying the payment object that was canceled?
it takes a lot of time until paypal answers questions.. so if anyone here has got a clue that would be helpful
thanks
I know this is old, but i dont think the Paypal .net API has improved much since this bug, and neither has the docs.
I noticed that the token you require was on the "approved_url"
I stripped it out, and saved it, so if the cancel is returned, you can look up your order via that token.
I have discovered it. When you enter the cancel URL first you have to ask for access token (if you dont have it stored), then get the payment information (here you can see) and the response contains a cart value, the cart value is same that the token without EC-, I mean, if cart value is 1234567890 the token you have is EC-1234567890.
When you create the payment store in your database (or elsewhere) the payment id, cart value and the final token. Then on cancel you search the cart value in your database and you obtain the Payment ID.
Did I explain?

Does my app need SSL on its Paypal redirection & landing pages?

I want to add Paypal functionality to my app but I'm kind of in the dark about some of the security issues.
Specifically, when the user wants to pay, I have to redirect them to Paypal and then Paypal sends me some kind of token/key to indicate whether the payment took place.
So, on the page where I pass the user to Paypal, do I need SSL? Why/why not?
What about the page where I receive the response token from Paypal?
Is it possible for a hacker, for example, to make up some random token and post it to my app to pretend that he paid?
If so, does this mean I need to make another call to Paypal after I receive the token - to make sure the token is real?
I've done this before using drupal e-commerce to sell app downloads via Paypal and used SSL neither on the redirection nor the landing page. While technically I suppose a hacker could intercept the token of someone who paid for the app and use it to pretend he paid, I don't think this is likely scenario because the average criminal is more interested in credit card numbers than one-time free access to some product/service. Further, one of the main reasons you would use Paypal in the first place is so that you wouldn't have to pay as much attention to security as you would if you had to process the users credit cards yourself since Paypal takes care of this for you (and their system is secured by SSL).
correct me if I'm wrong but I think that without ssl the following two scenarios are possible using a man-in-the-middle attack:
phishing:
the hacker redirects the user to a paypal-like site and receives his paypal user/pw or credit card details.
this attack isn't perfect as phishing sites do get found and pulled down.
hijacking the payment:
the hacker creates his own real paypal token (order data scrapped from your site) but with his own paypal account as the receiver and redirect the customer to that address. in this case paypal's policies might be enough to make this actions pointless.

Is Moneris Direct Post Secure?

I am looking at the Moneris Payment Processing and their Direct Post method. For the life of me, I can't figure out how the security on it works.
As best as I can tell it does this:
Web User comes to my site. They fill out their credit card information (https).
I show them a summary in a form. When they hit submit they go to Moneris (POST) - including my ID, credit card info, and a custom Transaction ID.
Moneris processes the transaction and sends them back to my site (as a POST)
If they arrive on failed.php or whatever URL you specify, the transaction failed. Else:
If they arrive on gotyourmoney.php then the transaction seemingly worked. Time to validate. (included in POST vars is a Unique ID for the transaction, date/time stamps, response_code (got money, didn't get money) and a few other miscellaneous items.
I redirect the user back to the moneris site with another POST. I include my ID again and the Unique ID returned in step 5 to verify the transaction.
User is redirected back to gotyourmoney_verified.php as a POST again with the unique ID, Transaction ID, and response_code.
What I can't figure out is this:
No where does there seem to be any information that I can validate that the web user can't just make up. Even though it is an https connection I'm trusting the user to pass all information. They could immediately go to the gotyourmoney.php page and never even go to the moneris payment gateway. They can just make up the ID's. When I send them back to moneris for the transaction verification, again they could just post a made-up response to my site.
What am I missing?
The Transaction Verification feature of DirectPost can be used to prevent spoofing.
Here's how it works
A customer enters their credit card information on your site and the information is sent to Moneris for processing
Moneris processes the transaction and sends the transaction result to your site
If transaction verification is enabled then there will be a special field in the transaction result called a "transaction key"
Then to verify that the transaction wasn't spoofed, your site would send the transaction key in a transaction verification request to Moneris
Moneris would then verify the transaction using the transaction key and respond with a result that lets you know if the transaction was spoofed
The Integration Guide for DirectPost has all the details on how to implement the Transaction Verification feature and can be download at http://developer.moneris.com (free registration required).
In addition to Transaction Verification you can also setup a referrer URL. If a referrer URL is setup then Moneris will verify if the transaction is coming from an allowed URL. It's possible to circumvent the referrer URL feature but having a referrer URL enabled is still useful as part of a defense in depth strategy because it makes it that much harder to spoof a transaction.
Indeed since all of those things go through the client, they can easily be spoofed. And the Moneris documentation doesn't tell you this. You need some sort of server-to-server step to be sure that everything is in order.
I would suggest doing a preauthorization using the hosted pay page and then doing a capture with the PHP API. Since you're doing the capture server-to-server, any attempt to spoof by the client will just result in a failed capture.

Resources