Two comments:

* It would be better if the error message contained the complete expected and actual user data (otherwise it's easy to wonder what is wrong with the user data because one can't see that an expected value has ended up under a different key).

* I think this doesn't fail when the user has extra, unexpected keys.