Bad, vile and meaningless: Sampo form trouble from Alan's clob

Novelty in webdesign @ Sampo Pankki Oyj

About a week ago, Sampo updated their webbank. (They claim to have sent notice about this update, but of course it wasn't sent to us middle-men who actually do the work, just to our clients who never notified us.) I'm sad to report that due to the intricacies of the fix, it took us almost a week before we finally had a working fix rolled on to production that fixed the problem on every application we had.

  1. The use of session=our-system-session-id. Sending the parameter session=12345678 in the transition request confuses it, but you don't get to see it until you try to logon. Okay, that was our mistake, kinda—we aren't supposed to send a session, in the specs. But I think it isn't forbidden, either. This parameter is there because it's autogenerated on the forms of our web systems, and the transition to webbank is just one more form. So, this invalid session variable caused logins fail as soon as you provided a correct login, but not before.

  2. Returning to the merchant using a POST request, with query parameters like in GET urls. Okay, I admit being guilty to the convenience of using both, and browsers don't really seem to mind. However, in our uses it was specialized variables like session that sometimes was carried in URL, and not everything... Here, we get an empty POST, all the data is in the GET-style query parameters. At least in Perl, when you are handling a POST request, the GET parameters are actually ignored by CGI.pm. This can be fixed with some cost.

I actually quite understand why Sampo went this way. Looking at their source, on the return page it says like this:

<form method="POST" action="http://server/app?foo=bar&bar=baz&etc...">
    <input type="submit" value="continue">
</form>

They must have noticed that if you set method="GET", all the query parameters provided in the action must vanish. That's fine, but to patch it up by using a POST request is still rather unique sort of solution to that problem. One should really deparse the merchant's return URL parameters into key+value combinations and write them as hiddens on the form, or–better–do a 302 redirect from your own software. The server-side redirect is infinitely more preferrable than any too-buggy-beyond-words attempt in handling all the URLs your merchants will be giving you, so that would be my recommendation. Also, there's the collectively blame-shifting "everyone else is doing it that way, too"-argument.

Anyhow, things being like they are, we had to workaround this ourselves. We came up a code similar to this:

my $q = CGI->new();
if ($q->request_method() eq 'POST' &&
    defined($ENV{QUERY_STRING}) && length($ENV{QUERY_STRING}))
{
    foreach my $key ($q->url_param) {
        $q->param($key, $q->url_param($key));
    }
}

This also uncovered a bug in CGI.pm. Damn. That's why I test the length above. Without it, you'll get a spurious keywords key that has no value, when QUERY_STRING happens to be empty as it usually is. I notified the maintainer about it.