Martin,<div><br></div><div>I didn&#39;t realize you were the author of the Perl library.  I probably would have been more gentle with my words. :(  Sorry.  It&#39;s often a thankless job as a library author (I know) and it&#39;s a very big job to get it done right and well.</div>

<div><br></div><div>Further discussion inline below, including the nonce discussion you asked for...  Good luck with your Perl implementation of the feature!</div><div><br><div class="gmail_quote">2009/3/31 Martin Atkins <span dir="ltr">&lt;<a href="mailto:mart@degeneration.co.uk">mart@degeneration.co.uk</a>&gt;</span><br>

<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><div><div></div><div class="h5">Andrew Arnott wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
    I&#39;m also somewhat curious about how many OpenID consumers actually<br>
    do nonce checking. Net::OpenID::Consumer for Perl actually ignores<br>
    the nonce altogether and implements its own timestamp checking due<br>
    to legacy code for OpenID 1.1, and seems to be vulnerable to replay<br>
    for up to 30 seconds after a positive assertion.<br>
<br>
<br>
The author of the Perl library ought to be ashamed. This kind of thing reduces my confidence in using OpenID at any site other than one that I wrote the library for myself.<br>
<br>
Although this is what OSIS testing is all about.  Hopefully there is a test to catch RPs and OPs that don&#39;t check the nonce for replays.<br>
</blockquote>
<br></div></div>
Yes. As the maintainer of that library (though not its original author), I am ashamed, which is what prompted the question in the first place.<br>
<br>
I&#39;d love to have a test in the test suite for this.<br>
<br>
RPs only need to do this checking when they&#39;re running in stateful mode, right? Since stateless RPs have nowhere to store state they can&#39;t retain a history of nonces.<br>
<br>
Can you share some high-level details about your nonce-checking implementation? Specifically how you persist the previous nonces, when you expire them, etc?</blockquote><div><br></div><div>Sure.  </div><div><b>Relying Party side of things</b></div>

<div>DNOI (dotnetopenid) generate nonces and add a &quot;dnoi.request_nonce&quot; parameter to the return_to url if discovery on the user supplied identifier suggests that the OP is a 1.x version of OpenID.  The RP does not store nonces it generates.  In stateless mode in never stores them at all, relying on the OP to check for unique nonces.  In stateful mode, the RP only stores nonces that are included in positive assertions it receives, whether those nonces are dnoi.request_nonce or openid.response_nonce values.  It uses a &#39;blacklist&#39; style instead of a whitelist style for these reasons:</div>

<div><ol><li>Causing an RP to generate an authentication request is cheap.  In a DoS attack, an RP could quickly fill its memory with nonces by just asking the RP to start an auth request without ever following up on it.  By waiting until there&#39;s a positive assertion carrying a nonce, it becomes more expensive to run such a DoS attack and thus mitigates the risk to the RP.  But it also means you will have a record of the claimed_id of each of the logins involved in the DoS, so you can block that OP endpoint later if it ever became a problem.</li>

<li>Since the RP sometimes generates the nonce (for openid 1.x) and sometimes does not (openid 2.0), it provides a single place to store and check the nonce in the code to only do so upon receipt of the assertion.</li><li>

The OP generates nonces that it never will store or check for openid 2.0, so again, it made sense for the nonce generation code to not store, and for the consumer of the nonce (whether RP or OP) to just add the nonce to a store and check for a conflict at that time and have cleaner code.</li>

</ol><div>Sure there are reasons to argue the other way, but the above is why I chose this way of doing it.</div><div>Oh, and here&#39;s a detail to be mindful of that DNOI had a bug regarding for a lot of versions: the nonce should be combined with the OP endpoint (in a secure way) to make a unique nonce that you store and check for collisions with.  The reason for this is to avoid an RP falsely detecting a replay attack when one OP endpoint happens to generate the same nonce as another OP endpoint.  An OP endpoint can legally just increment an integer (1, 2, 3) to be its nonce and be unique for itself.  If two OPs do this, you can imagine how likely a collision would be.  Nonces out there are typically more random than that, but it&#39;s still a slight concern.</div>

<div><br></div></div><div><span class="Apple-style-span" style="font-weight: bold; ">Provider side of things</span></div><div>On the OP side it gets much more interesting.  I have a blog post on it already.</div><div><a href="http://blog.nerdbank.net/2009/03/replay-protection-for-openid-1x-relying.html">http://blog.nerdbank.net/2009/03/replay-protection-for-openid-1x-relying.html</a></div>

<div>Basically, OpenID 1.1 Providers provide no replay protection for their customers. That wasn&#39;t good enough for me, so with DotNetOpenAuth 3.0 (DNOA, previously known as DNOI), I added replay protection from the Provider side even for customers logging into 1.1 RPs.  My blog post discusses how this is done.  </div>

<div>The basic 2.0 scenario though is that the OP generates nonces, and only stores the ones that come back in check_authentication messages.  </div><div>The advanced 1.1 scenario is that the OP always forces private associations for positive assertions (read: RPs are forced into dumb mode) and thus the check_auth comes back to the OP, and the OP can check its proprietary dnoi.response_nonce value.</div>

<div><br></div><div><b>Clearing of expired nonces</b></div><div>Since most web sites don&#39;t have associated services that run constantly or periodically (yes, there are cron jobs, but not on Windows as much as on Linux, and I&#39;m targeting Windows), I just had a simple algorithm that was roughly this: every 20th nonce check should also cause an expired nonce sweep to occur, where expired nonces are removed from the database.</div>

<div><b><br></b></div><div><b>Web farm considerations</b></div><div>It&#39;s vitally important that if your library is used by a site that is hosted by a web farm, that the nonce store is shared by all servers (including multiple processes on the same server, I think called a web garden) in a transaction supporting database.  Even if your web farm has a sense of affinity so the same user tends to be directed to the same server in the farm, a hacker will have a different IP address and therefore be directed to any random server, and if the nonce store is not shared, he will succeed at replaying a message and spoofing a user&#39;s identity!</div>

<div><b><br></b></div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;"><br>
<br>
I&#39;m wondering if it would instead be simpler to use a client-generated nonce in the return_to URL, as you note that DotNetOpenID is doing for 1.1 requests, thus allowing the nonce checking to be a whitelist rather than a blacklist and the nonces to be in a known format that I can optimize for.<div>

<div></div><div class="h5"><br>
<br>
_______________________________________________<br>
general mailing list<br>
<a href="mailto:general@openid.net" target="_blank">general@openid.net</a><br>
<a href="http://openid.net/mailman/listinfo/general" target="_blank">http://openid.net/mailman/listinfo/general</a><br>
</div></div></blockquote></div><br></div>