A Rose by Any Other Name...

by coatta 2/25/2012 10:22:00 AM
Actually, in coding names do matter. A few months back we moved our application from one hosting provider to another and everything worked except OpenID authentication. In fact, we had both applications running simultaneously and talking to the same OpenID provider, and one worked and the other didn't.
We were actually getting an error message that indicated a packet had been rejected due to a problem with a "nonce". Here's a definition from Wikipedia: nonce is an arbitrary number used only once to sign a cryptographic communication. That pretty much matches my notion of what a nonce is as well.
I figured this must be due to some peculiar packet duplication that was causing a nonce to be used twice. Seemed like it should be easy to sort out with a network trace, so we slapped one on and collected the traces. They were isomorphic until they weren't. When OpenId failed, it appeared to be because they simply just stopped talking.
OK, so time to dive into the code.
We trace through the code looking for where the nonce was processed. I kept expecting to run into a table that preserved nonce values so the code could check if a nonce had been seen more than once. I couldn't find one. Eventually we got to exact place in the code where the error originated. The "nonce" was actually a timestamp, and the error was because of clock drift between the OpenID provider and the new server we were running on.
Needless to say, this would have all been a lot more straightforward if they had used the right word! An error message along the lines of "the timestamp on message X is out of date" would have made this a lot easier to figure out. Having the field called "timestamp" rather than "nonce" would have made the code a lot easier to understand.

Service Contracts and Global Constaints

by coatta 1/29/2008 7:54:00 PM

We ran into an interesting problem with one of our web service interfaces at work today. We had recently added code to enforce some business logic constraints, and this was causing some requests to fail that, from the perspective of the UI, should have been legal. The problem was a mismatch between the granularity of our service contract and the granularity of the constraints.

The constraints that we had added were ones that applied to collections of objects. An example of this type of constraint is that a collection of nodes in a graph cannot have any cycles. The interesting thing about this sort of constraint is that you cannot determine if the constraint is being violated by looking at a single node. You have to examine all of them at once.

Now suppose that you have a web service call that allows you to add/remove/update a single node. Superficially this doesn't seem like a bad idea. In addition to that, let's assume that the application making use of the service allows the user to modify one or more nodes and then save all the changes back to the server. No problem, when it comes time to save the changes to the server, you iterate through the modified nodes and then make an add/update/delete call for each one.

But what if the server validates the set of nodes as part of each add/update/delete call. Now you've got problems. The user can make a set of changes that are consistent when considered as a whole. That is, the graph resulting from all the changes has no cycles.  However, it is possible that one or more of the individual changes results in a cycle. So part way through saving the changes back to the server, you'll get an error indicating that the constraint has been violated.

The problem is that the granularity of the updates does not match the granularity of the constraint. To resolve the mismatch for the example above, you need a service method that allows all the changes to be sent to the server as a batch. The server will only validate the results after the entire batch of changes has been applied.

You might feel inclined to complain that a web service that allowed the nodes to be updated individually was a poor design in the first place. After all, most service interfaces should allow operations to be carried out in bulk. But even if you design the service to support bulk changes, it is still possible that the granularity of the interface does not match the granularity of constraints -- so when designing a service interface you need to be aware of the business constraints that will be enforced by the service implementation and design your interface accordingly.  


<<  April 2023  >>

View posts in large calendar


My opinions are my own, but you can borrow them if you like.

© Copyright 2023

Sign in