ASP.NET MVC - Secure Temporary Storage of Credit Card Data - asp.net-mvc

I have a checkout process for a shopping cart that is currently storing credit card data in the session for retrieval once the user finalizes the purchase. The purchase process is set up such that the user inputs the credit card, views a confirmation page, and then finalizes the order. The confirmation and finalization actions are the only two actions that need access to the credit card data and to be safe all other actions should discard it.
Short of doing reflection in a base controller to check the current action the user is calling, I cannot think of an elegant way to discard the data on the disallowed requests. Additionally, if the user fails to make another request after entering the data it will linger in the session until they come back to the website- whenever that happens. One suggestion I was offered was encrypting the data into a hidden field and relying on the SSL ticket to prevent caching the markup. This seems like a fairly safe approach, but I don't much like the idea of placing the credit card data in a user-accessible location encrypted or not. Storing in the database is out because the client does not want credit card data saved.
What is the ideal approach to temporarily persisting sensitive data like credit card information across more than one page request?
Perhaps someone can tell me if this is a sufficient approach. I have set my Shopping Cart which is stored in the session to have a unique Guid generated every time the object is newed and that Guid is used as a key to encrypt and decrypt the credit card data which i am serializing with the Rijndael algorithm. The encrypted card data is then passed to the user in a hidden field and deserialized after finalize is clicked. The end result is a string much like this:
VREZ%2bWRPsfxhNuOMVUBnWpE%2f0AaX4hPgppO4hHpCvvwt%2fMQu0hxqA%2fCJO%2faOEi%2bX3n9%2fP923mVestb7r8%2bjkSVZDVccd2AJzCr6ak7bbZg8%3d
public static string EncryptQueryString(object queryString, Guid encryptionKey)
{
try
{
byte[] key = Encoding.UTF8.GetBytes(ShortGuid.Encode(encryptionKey).Truncate(16));//must be 16 chars
var rijndael = new RijndaelManaged
{
BlockSize = 128,
IV = key,
KeySize = 128,
Key = key
};
ICryptoTransform transform = rijndael.CreateEncryptor();
using (var ms = new MemoryStream())
{
using (var cs = new CryptoStream(ms, transform, CryptoStreamMode.Write))
{
byte[] buffer = Encoding.UTF8.GetBytes(queryString.ToString());
cs.Write(buffer, 0, buffer.Length);
cs.FlushFinalBlock();
cs.Close();
}
ms.Close();
return HttpUtility.UrlEncode(Convert.ToBase64String(ms.ToArray()));
}
}
catch
{
return null;
}
}

The best way to handle this scenario is to use a payment service that supports two things:
Authorization -> Completion semantics.
Tokenization
Authorization allows you to reserve the designated charge amount at the time the payment information is received, and then Completion allows you to commit the charge to the payment batch once the payment/order is confirmed. If the order is canceled, you don't have to issue a Completion and you can also attempt to delete the authorization as well.
Regarding tokenization, most gateways that support the aforementioned method of handling payments will return a token, typically a numeric id, for the pending transaction. The token may then be handled however you wish, as it has no value to anyone without access to your authentication credentials at the gateway. This transfers the burden of safety to the gateway as well.
Storing the actual credit card information in any way other than relaying a charge to a gateway/processor is a bad idea. Beyond the problems of securing the data, this will also put your application into card information storage scope for PCI/PABP, which entails a lot of rules and regulations that you won't want to deal with in your application. I believe there is also a regulatory fee that will be imposed in the coming year for compliant applications, reputedly $10k USD. All of this is likely not worth the trouble to you or your client.
Last, during intermediate processing (in-page/event/route handlers), you can use a SecureString to hold the contents of the data until you no longer need them.
SecureString class (System.Security) # MSDN

What about using TempData? You'd need to put the value back into TempData between the confirmation and finalization actions, but at least it will be discarded with each request. Note that TempData uses the Session for storage so it's no more secure while it's being stored, but it does have the automatic removal feature. I, too, would resist storing the number on the page. I suspect that this violates the PCI rules.
Another alternative would be to store the card info in a database. If you keep it at all in your application you're probably already subject to the PCI rules anyway. Storing it in the DB makes it easier as then you only need to put the billing card id in subsequent requests. This could easily be in a hidden field.

What country is this based in and what credit card companies are involved? The entire approach of actually sending full credit card numbers back to the client (in whatever form) makes this sound like you have not dealt with professional credit card handling (please don't take that as an insult).
Is your client willing to run afoul of Visa/MasterCard/AMC/Discover's collective rules for online credit card processing (PCI DSS)? Your client could end being barred by the major credit card companies from doing transactions with them. In general it is a very bad idea to try rolling your own online credit card handling solution - it's worse then rolling your own cryptographic algorithm, as there can be serious fines applied to your client (fine print in their merchant agreement). A true PCI DSS solution requires tens of thousands of dollars in certifications and audits to ensure it handles credit card data in a truly secure fashion - this is why almost everyone uses an existing online processor.

Related

Designing safe and efficient API for item state updates via events

Recently I've been working on a simple state-tracking system, its main purpose is to persist updates, sent periodically from a mobile client in relational database for further analysis/presentation.
The mobile client uses JWTs issued by AAD to authenticate against our APIs. I need to find a way to verify if user has permissions to send an update for a certain Item (at this moment only its creator should be able to do that).
We assume that those updates could be sent by a lot of clients, in small intervals (15-30 seconds). We will only have one Item in active state per user.
The backend application is based on Spring-Boot, uses Spring Security with MS AAD starter and Spring Data JPA.
Obviously we could just do the following:
User_1 creates Item_1
User_1 sends an Update for Item_1
Item has an owner_ID field, before inserting Update we simply check if Item_1.owner_ID=User_1.ID - this means we need to fetch the original Item before every insert.
I was wondering if there was a more elegant approach to solving these kind of problems. Should we just use some kind of caching solution to keep allowed ID pairs, eg. {User_1, Item_1}?
WHERE clause
You can include it as a condition in your WHERE clause. For example, if you are updating record X you might have started with:
UPDATE table_name SET column1 = value1 WHERE id = X
However, you can instead do:
UPDATE table_name SET column1 = value1 WHERE id = X AND owner_id = Y
If the owner isn't Y, then the value won't get updated. You can introduce a method in your Spring Data repository that looks up the Spring Security value:
#Query("UPDATE table_name SET column1 = ?value1 WHERE id = ?id AND owner_id = ?#{principal.ownerId}")
public int updateValueById(String value1, String id);
where principal is whatever is returned from Authentication#getPrincipal.
Cache
You are correct that technically a cache would prevent the first database call, but it would introduce other complexities. Keeping a cache fresh is enough of a challenge that I would try it only when it's obvious that introducing the complexity of a cache brings the required, observed performance gains.
#PostAuthorize
Alternatively, you can make the extra call and use the framework to simplify the boilerplate. For example, you can use the #PostAuthorize annotation, like so, in your controller:
#PutMapping("/updatevalue")
#Transactional
#PostAuthorize("returnObject?.ownerId == authentication.principal.ownerId")
public MyWidget update(String value1, String id) {
MyWidget widget = this.repository.findById(id);
widget.setColumn1(value1);
return widget;
}
With this arrangement, Spring Security will check the return value's ownerId against the logged-in user. If it fails, then the transaction will be rolled back, and the changes won't make it into the database.
For this to work, ensure that Spring's transaction interceptor is placed before Spring Security's post authorize interceptor like so:
#EnableMethodSecurity
#EnableTransactionManagement(order=-1)
The downside to this solution is that there are still the same two DB calls. I like it because it's allowing the framework to enforce the authorization rule. To learn more, take a look at this sample application that follows this pattern.

Are Firebase queries scalable

In my app to check for if an email (and username) is taken when signing up I use queries like this...
let emailRef = Firebase(url: "https://photocliq5622144.firebaseio.com/users")
emailRef.queryOrderedByChild("email").queryEqualToValue(email.text!.lowercaseString).observeEventType(.Value, withBlock: { email in
Would this work well with hundreds or even thousands of users (is this scalable)?
Hundreds: yes
Thousands: yes
Tens of thousands... probably (and congratulations on the success of your app)
Hundreds of thousands... you're likely better off with a non query-based data model. For example: if you want to access some data for the user by their email address, store a map from email address to uid:
emailToUid
"HelixProbe#stackoverflow,com": "uid6479958"
"puf#stackoverflow.com": "uid209103"
With such a simple list, you can read the user's data from their email address with two direct lookups, instead of one query (which will get slower as more and more items are added).
Scalable or not is determined by your user.
Behind the scene Firebase library is just downloading JSON string and you know exactly what happen if the string is too long and the file size to be downloaded reach (for example 3MByte)
If your user is able and okay with 3MByte for a request, than you can go with it. But I don't if I am your user.

Fetch a list of portfolio positions from a brokerage account?

Use case which we want to built is a user will be presented with a list of financial institutions and when he selects anyone of it he needs to provide credentials to authenticate for selected institutions. Then brokerage account will be shown, clicking on it results into fetching of all portfolio positions.
So far what we have achieved:
Fetching list of all institutions, this we can achieve using
API method: getInstitutions
Selects an institution and authentication is performed (I am not sure this is the correct way of doing, if there is another way to do it then please let me know)
API method: discoverAndAddAccounts
Get all accounts associated with it and using Brokerage account id fetch all positions:
API method: getInvestmentPositions
Using above will return all positions but we can not differentiate between 'buy' and 'sell' action of a position.
Note: We are using this gem for the same: https://github.com/cloocher/aggcat
Thanks in advance.
First you have to know the definition of an option:
DEFINITION of 'Option'
A financial derivative that represents a contract sold by one party (option writer) to another party (option holder). The contract offers the buyer the right, but not the obligation, to buy (call) or sell (put) a security or other financial asset at an agreed-upon price (the strike price) during a certain period of time or on a specific date (exercise date).
Then by looking at the Intuit documenation we can see that:
positionType string
This is used to explain how long a position is held and differentiate between writers and holders of an option or other security.
E.g. SHORT = Writer for options,
Short - Write for all other securities,
LONG = Holder for options,
Long = Holder for all other securities. For Bonds, it is always "LONG".

MVC 3 - Sessionless controllers datastore options

i've been reading about sessionless controllers lately and it seems an interesting idea, since it improves perfomance and let ajax calls to be asynchronous, as usually they should be.
However, i can't figure a nice way to store data that would previously stored by a session. I have a lot of single-fetch data that i get once and walks with it through several pages. My first thought was to use MemoryCache, but reading this post i begin to doubt it, since IIS can let go my data anytime.
Because of this, i got a little confused on what should i do to store data in a session like way. I read a couple of thing about NoSQL and MongoDB, but wouldn't that be the same as to fetch data all the time i need it?
Can you give me some clarifications and technologies i can use to serve as temporary datastore?
Have you considered using the HttpContext.Cache? As you're saying in a session like way, there is no reason you couldn't create a cache key based upon the sessionid of the current request:
// cache key
var cacheKey = string.Format("{0}-{1}", "SomeKey", Session.SessionID);
// save to cache
HttpContext.Cache.Insert(cacheKey, <yourobject>, null, Cache.NoAbsoluteExpiration, TimeSpan.FromMinutes(20));
From there it would simply be a matter of passing along the sessionid and retrieving at a later time:
HttpContext.Cache[cacheKey]

How can I store user information in MVC between requests

I have an MVC2-site using Windows authentication.
When the user requests a page I pull some user information from the database. The class I retrieve is a Person class.
How can get this from the database when the user enters the site, and pick up the same class without touching the db on all subsequent page requests?
I must admit, I am pretty lost when it comes to session handling in ASP.net MVC.
You can store that kind of information in HttpContextBase.Session.
One option is to retrieve the Person object from your database on the first hit and store it in System.Web.HttpContext.Current.Cache, this will allow extremely fast access and your Person data will be temporarily stored in RAM on the web server.
But be careful: If you are storing significantly large amount of user data in this way, you could eat up a lot of memory. Nevertheless, this will be perfectly fine if you only need to cache a few thousand or so. Clearly, it depends upon how many users you expect to be using your app.
You could add like this:
private void CachePersonData (Person data, string storageKey)
{
if (HttpContext.Current.Cache[storageKey] == null)
{
HttpContext.Current.Cache.Add(storageKey,
data,
null,
Cache.NoAbsoluteExpiration,
TimeSpan.FromDays(1),
CacheItemPriority.High,
null);
}
}
... and retrieve like this:
// Grab data from the cache
Person p = HttpContext.Current.Cache[storageKey];
Don't forget that the object returned from the cache could be null, so you should check for this and load from the database as necessary (then cache).
First of all, if you are using a load balanced environment, I wouldn't recommend any solution that you try without storing it in a database, because it will eventually fail.
If you are not in a load balancing environment, you can use TempData to store your object and then retrieve it in the subsequent request.
HttpContext.Current.Session[key];

Resources