Best Practices for Processing Credit Cards in Rails

This article defines a real-life scenario for a payment processing flow that allows an organization to process online donations for multiple charities. Each charity will have donation widgets embedded on numerous and diverse web sites, allowing users to select a a donation amount and then click a button to initiate a payment.

A set of rules were defined to ensure the security of the payment processing flow, i.e - the set of web pages involved in accomplishing the transaction. The payment processing flow was implemented in Rails, and some of the technical details are therefore Rails-specific, but the general lessons are applicable to any technology used to manipulate data securely.

  1. Minimize external entry points. The payment processing flow needs to be secure, with strict controls on where and how users can enter the flow. In this case, there should be a defined URL to which information (including the relevant charity and the selected donation amount) can be posted by the donation widgets.

    This Payment Data Entry page will show users the posted information about the donation, plus allow users to enter additional information, such as credit card data, to complete the transaction. The Rails controller action to display this page should be the only page in the payment flow that has the Rails authenticity token turned off.

    In general, the authenticity token ensures that a Rails-based form cannot be driven remotely by an external site or program. In this case, it has to be turned off so remotely hosted forms (the donation widgets) can post information to the web page.

    The Rails authenticity token can be turned off for a controller action by adding the following code to a controller:

       skip_before_filter :verify_authenticity_token, :only => [ :create ]

    In Rails, the authenticity token is on by default.

  2. Use the Rails authenticity token whenever possible. All other payment-related pages, other than a clearly defined initiation page (our Payment Data Entry page), should use the Rails authenticity token so they can't be remotely driven by external sites or programs. The authenticity token allows Rails to verify that data was posted to a web page by another web page on the local web site.

    Note: This means that the Payment Data Entry page will accept only limited information from a remote location (so it can show the relevant charity and payment amount). However, the data entry form on that page does use the authenticity token, so that page must be submitted manually by a user.

  3. Credit card information is carried from page to page via POST actions. No credit card information is stored in the local database. The purpose of the payment processing flow is to facilitate transactions in a customer-friendly way. The payment processing gateway (such as PayPal, ProfitStars or a credit card gateway) with which the payment flow is integrated will be the database of record for detailed transactions, and the security of credit card data will ultimately be their problem.

  4. Use a session variable to store the transaction ID. A transaction is recorded in the local database for a payment, and includes only relatively non-sensitive information such as the name of the customer, the charity to receive the donation, the amount and the date. Once a transaction has been created, the ID is carried from page to page via a session variable. Users will have no external way to specify a transaction ID in order to view data that does not belong to them.

    Note: Why have a local transaction? Well, some transactions might fail or there could be problems with the payment processing gateway. The local transaction provides sufficient information to correlate with the corresponding transaction recorded by the gateway. So, it's really needed for data integrity checking and debugging if necessary.

  5. "Parameter Filtering" must be turned on so that fields related to credit cards are not stored in the site's log file. This little detail is often forgotten by individuals implementing payment processing flows, and can result in credit card information being left in plain text in log files.

    The following code can be used to turn off logging of specified data elements:

       filter_parameter_logging :credit_card, :expiration, :name_on_card, :security_code

  6. SSL is used for communication between pages and for communications with a payment processing gateway. This ensures that the traffic is encrypted and greatly reduces the odds that anybody (other than maybe the NSA) can access sensitive data in transit.

  7. Non-SSL access to any of these web pages will be rejected with an appropriate error message. Users cannot elect, either accidentally or on purpose, to perform a transaction without using SSL.

In combination, these rules allowed me to successfully create a secure payment processing flow for a client. In the event of a security audit, these rules allow me to: 1) clearly define for an auditor the risks associated with using and managing the data, and 2) demonstrate that the risk of any sort of data loss from the payment processing flow has been minimized to acceptable industry standards.


No comments yet. Be the first.

Leave a Comment

Comments are moderated and will not appear on the site until reviewed.

(not displayed)