PayPal and Microsoft WebAPI: best security approach - security

I'm creating a WebApi project that aims to handle payments in my project.
Actually, my approach is like:
CreatePaymentMethod(creates the payment, contact paypal and redirect the user to the payment page. If payment is done, redirect to PaymentApprovalMethod)
PaymentApprovalMethod (confirm the payment on my system, allowing the user to access the content)
What I'm wondering is... What if an users directly creates a message to invoke the PaymentApprovalMethod?
Suppose:
- CreatePaymentMethod is called, user sniffs with Fiddler the Transaction ID of the redirect
- Creates and adhoc call of the PaymentApprovalMethod like.
I see two possibles scenario to handle this situation:
Restrict (I don't know how) the calling of PaymentApprovalMethod to the messages from Paypal only
Cross Check the payment inside the PaymentApprovaMethod (ok, user, you said the transaction ID 123 is done, I'll contact paypal to verify this before trust this call)
The second one seems more safe but also more "time / resource" problematic..
Do I'm missing something? Is there something else I can do to avoid this problem?

Take a look at Instant Payment Notification (IPN). PayPal's system will POST transaction data to a listener script that you setup for all transactions on your account, be it a payment, refund, dispute, cleared payment (from pending), etc. You can use this to completely automate many post-payment procedures.
Part of your IPN listener will include a call back to PayPal's server to verify that the data actually came from them. You can then log IPN's separately, and only process verified IPN's, which means you know somebody didn't just POST directly to it on their own.
Some people do go a step further and only accept traffic to that script from PayPal's IP addresses, however, they do change their addresses quite a bit and I think that just becomes a hassle. The verification has always been enough for me.
IPN is definitely what I would recommend for you.

Related

Remote Signing (DocuSign) - Some recipients not receiving emails

Issue:
I have a working production process for initiating remote signing via the DocuSign REST API. For the most part, it works great. However, for the initial 20 contracts we've sent out, a few clients have not received their emails from DocuSign requesting their signature. I can confirm that DocuSign reports that they successfully SENT them to the signers even though clients have reported never receiving them (despite looking through spam/junk/deleted). In these few circumstances we're stuck at a dead-end because if they don't receive that email for whatever reason, we have to revert back to manual contracts.
Having read through the following article:
https://support.docusign.com/en/articles/Why-aren-t-my-signers-receiving-DocuSign-Notification-emails
It's clear that this is a common issue and the only options we have is to either send it to another email address, have the client reach out to their ISP and figure out why it might be rejected (This is not a good / professional option), or resort to a manual contract.
One thought I had...
was to use the API to obtain the link for the current signer that DocuSign provides in the emails they send and give my app's users an alternative option to send our branded email containing this link to the remote signing page from our email service since we have zero reputation issues.
Edit based on Inbar's reply
After reading through Larry's Blog as provided by Inbar in the comments below, my idea above would need to have my app send an email to the signer with a unique URL back to my App (so that this URL is Long-Lived / limited only based on business rules) which, when clicked, would make a request to EnvelopeViews:createRecipient (time-limited / must be used in 5 mins) to retrieve a url and redirect the user to the Remote Signing page which is governed by DocuSign's session policy.Should my client need to go away and click the link in their email again, the Long Lived ==> Time Limited & redirect would repeat starting a new session.
Support seems to be better here on SO than via ticketing, so I'm hoping a DocuSign rep/guru has some ideas on what I can do to handle these scenarios.
First off, yes there are cases where emails from DocuSign are rejected as SPAM by the ISP or by the email provider. These will not even show in the spam folder because they reject them before they send them to the end-user and we do need to work with these to fix the issue. Especially if these users will be receiving more than one contract etc. For that - you will need to contact support since we need to know the email address etc.
Your idea is possible, but you'll have to read Larry's blog here. This is because the URLs are typically very short lived and expire in 5 min so sending the regular URLs over email will not work very well.

How to handle Stripe 3D Secure when creating a PaymentMethod on the client for multiple charges on the server

In my marketplace I have a requirement to:
Have a customer enter their card details
Once card details are submitted, process multiple charges against that card on the server side
I'm using stripe.js and creating a PaymentMethod on the client side using stripe.createPaymentMethod()
The ID of the PaymentMethod is posted to the server, which then does the following via the Stripe API library for PHP:
Retrieves the PaymentMethod from Stripe using the posted ID
Creates a Customer on Stripe, specifying the 'payment_method'
Creates multiple PaymentIntents, specifying the 'payment_method', the 'customer', 'save_payment_method' as true and 'confirm' as true.
I'm now wanting to handle scenarios where Stripe requires the use of 3D Secure.
Is there any way that 3D Secure verification can take place on the client, prior to the request to the server, whilst using stripe.createPaymentMethod() ?
If not, what alternative do I have?
It seems that a user completing the 3D Secure steps returns only a PaymentIntent. I don't believe I'm able to use this to make multiple charges against the card. This is whole reason for using createPaymentMethod() on the client in the first place.
Any ideas on how to go about this?
Is there any way that 3D Secure verification can take place on the client, prior to the request to the server, whilst using stripe.createPaymentMethod() ?
The approach to handle 3D Secure authentication on the client is to either use the confirmCardPayment [0] or handleCardAction [1] methods on Stripe.js. Unless you have specific needs, you would most likely want to use confirmCardPayment and follow this guide here:
https://stripe.com/docs/payments/accept-a-payment
I should note, that both these methods only work to process one payment at a time. In your case, you have multiple payment intents, so you would need to call either of the methods once per transaction. That is, if you have three payment intents you would need to call confirmCardPayment three times, repeating the last step in the guide [2] that many times as well.
This means that it is technically possible (but unlikely) that your users may have to authenticate multiple times to process each of their payments.
Unfortunately, there are really no workarounds for this. Even if you were to setup a user's card with SetupIntents [3] and charge them off-session at a later date, there is still a risk that you would need to bring user's back on-session to authenticate each individual payment intent.
All this being said, the majority of your users probably won't run into a scenario where they would need to authenticate multiple times in a row.
The only other option would be to create a single payment intent that covers the full cost of your product/service, which would allow you to call confirmCardPayment just once.
[0] https://stripe.com/docs/js/payment_intents/confirm_card_payment
[1] https://stripe.com/docs/js/payment_intents/handle_card_action
[2] https://stripe.com/docs/payments/accept-a-payment#web-submit-payment
[3] https://stripe.com/docs/payments/save-and-reuse

Can SagePay's callback be validated to prevent hacking?

SagePay's form callback can be hacked by re-using the success URL that the user is directed to upon a successful transaction. This can create all sorts of problems with duplicate transactions, fake transactions etc.
You can check for a duplicate VPSTxId, but these can be generated anew by hacking around the crypt parameter of the callback URL.
The crypt parameter can also be manipulated to generate a different "Amount" field.
I have not tested what other field values can be changed by hacking the callback URL crypt parameter.
Is there any way (as per PayPal's IPN validation) of doing a double-check callback to SagePay to ensure that the transaction is new and unique?
Thanks for your post. In general we encourage clients to use Server integration where they can. We also constantly monitor transactions for suspicious behaviour and proactively contact our customers if we suspect any malicious activity.
We recommend customers make sure that they’re using the latest version of our integration protocol which is currently v3. Get the latest integration documents.
As Dan suggests you could use the Reporting and Admin API to validate that a transaction does indeed exist on the Sage Pay side but having an additional validation mechanism (like PayPal's IPN) is something we will actively explore.
If you'd like us to update you on this, then please get in contact with our customer services team at support#sagepay.com or 0845 111 44 55.
Sage Pay Support
You should always redirect a user from a success URL.
I personally use a fulfil page (success url), and a thank you page. On the fulfil page, you should obviously only ever process a transaction once (based on the transaction id), and you can store crypt sent with a transaction. The crypt will have to be valid and is only possible to encrypt if you have the encryption key.
So hacking would be extremely difficult unless you are being very security lax, and the hacker would have to know your encryption key to even begin trying to hack it.
Alternatively, you should use the server integration, so that the communications are server-server, not client-server. There is little difference between form and server.
10 immutable laws of security
http://technet.microsoft.com/library/cc722487.aspx

PayPal returnURL security

Summary: I want to use the returnUrl as a proof that the transaction has been accepted by PayPal.
I'm implementing a very basic purchase workflow based on PayPal.
Everything works nice, the User clicks on pay, the User goes to PayPal, PayPal sends the User to my returnURL... and I'm accepting the payment in this last step.
I know I would have to implement an IPN endpoint and accept the payment there, but this project is very basic and I'm too old or too lazy to implement all this asynchronous behavior which can be a hell of edge-cases.
Would be nice if I would just make the returnUrl more confident, difficult to fake.
I was thinking that there would be the possibility that in the returnURL there would be included a checksum signature based in a secret key stored in the PayPal account and in the actual transaction token
I don't know if this exists, I didn't find any of this into the documentation, any suggestion to make the returnUrl more confident is welcome.
Also if someone thinks I'm completely wrong and the returnUrl is never gonna be a proof that the transaction has been accepted please express your self.
When you're just doing the return URL you need to post to PayPal again to verify the transaction using your PDT token.
Say your return URL is Thanks.aspx:
"From the code-behind of Thanks.aspx, you'll parse the tx value and make an HTTP POST to https://www.paypal.com/cgi-bin/webscr with the following parameters: cmd=_notify-synch&tx=[TransactionID]&at=[PDTIdentityToken]."
This will respond with whether or not that request was valid.
The problem is that this page isn't guaranteed to get hit. The user could close their browser, or their internet could get cut off, or anything else.
The IPN will be getting hit from PayPals servers, and you really can't beat that.
It's pretty easy to set up, but I suggest reading through this document which will explain the PDT and IPN methods, and gives an easy way to figure out what you need.
http://www.codeproject.com/Articles/42894/Introduction-to-PayPal-for-C-ASP-NET-developers?msg=4382854#xx4382854xx
After completing an installation for Express Checkout I realised how it could be exploited.
Even though I am creating a unique invoice number and returning to mark that as paid, I found that it could still be exploited by a user changing the invoice parameter in the return link. Of course there were already checks to ensure that any invoice could only be paid once, but I needed to make it hack proof.
So what I finished up doing was adding some extra checks to ensure that the invoice in question was the last invoice assigned to that user. Yes, the same session ID is maintained aven after a visit to Paypal and back.

Securing a payment gateway POST

I'm setting up a payment gateway on our site that we can post information to via php (so all information is hidden from prying eyes) which will post to authorize.net, post back to our gateway and post back to our current page. The purpose for this is to give us a streamlined method of processing payments and easier debugging.
I have an auth key that is required to be posted to our gateway for the transaction to be processed. Is it worth it for me to secure a list of approved URLs to accept posts from, or is that too easily manipulated?
Do you have any other ideas on what I should focus on in regards to securing my gateway?
update
This gateway has a login/key pair used for authorize.net that it submits to. I have a 64 digit md5 encoded key that I use for domain.com to communicate with gateway.domain.com which happens of course over SSL. I'm inquiring as to whether that key is enough. Given, anyone with that key could run a transaction, but why would they... it would only be giving us money.
A list of approved URLs will do very little to protect your gateway:
curl -H "Referrer: http://happy.example.com" -D "pay_to=evil#example.com&amount=$100,000" http://example.com/gateway.php
You should take a look at using something like OAuth, where each request contains a unique token that only an authorized actor could provide.
Also remember that POSTing data only provides the illusion of security. It's easy (nay, trivial) to see what data is posted.
Oh, and this should be a no-brainer, but make sure you're using SSL.

Resources