<html xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office" xmlns:w="urn:schemas-microsoft-com:office:word" xmlns:x="urn:schemas-microsoft-com:office:excel" xmlns:m="http://schemas.microsoft.com/office/2004/12/omml" xmlns="http://www.w3.org/TR/REC-html40">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=us-ascii">
<meta name="Generator" content="Microsoft Word 14 (filtered medium)">
<style><!--
/* Font Definitions */
@font-face
{font-family:Calibri;
panose-1:2 15 5 2 2 2 4 3 2 4;}
/* Style Definitions */
p.MsoNormal, li.MsoNormal, div.MsoNormal
{margin:0in;
margin-bottom:.0001pt;
font-size:11.0pt;
font-family:"Calibri","sans-serif";}
a:link, span.MsoHyperlink
{mso-style-priority:99;
color:blue;
text-decoration:underline;}
a:visited, span.MsoHyperlinkFollowed
{mso-style-priority:99;
color:purple;
text-decoration:underline;}
p.MsoPlainText, li.MsoPlainText, div.MsoPlainText
{mso-style-priority:99;
mso-style-link:"Plain Text Char";
margin:0in;
margin-bottom:.0001pt;
font-size:11.0pt;
font-family:"Calibri","sans-serif";}
span.PlainTextChar
{mso-style-name:"Plain Text Char";
mso-style-priority:99;
mso-style-link:"Plain Text";
font-family:"Calibri","sans-serif";}
.MsoChpDefault
{mso-style-type:export-only;
font-family:"Calibri","sans-serif";}
@page WordSection1
{size:8.5in 11.0in;
margin:1.0in 1.0in 1.0in 1.0in;}
div.WordSection1
{page:WordSection1;}
--></style><!--[if gte mso 9]><xml>
<o:shapedefaults v:ext="edit" spidmax="1026" />
</xml><![endif]--><!--[if gte mso 9]><xml>
<o:shapelayout v:ext="edit">
<o:idmap v:ext="edit" data="1" />
</o:shapelayout></xml><![endif]-->
</head>
<body lang="EN-US" link="blue" vlink="purple">
<div class="WordSection1">
<p class="MsoPlainText">One option for making this super-easy to test is for this testing OP to implement WebFinger and use different identifiers for the different tests. Then it's easy to automatically connect the RP to the right OP for the test.<o:p></o:p></p>
<p class="MsoPlainText"><o:p> </o:p></p>
<p class="MsoPlainText">For instance, one of these WebFinger identifiers could be entered at the OP to connect to the test OP for the test
<b>RP-Response-code</b>:<o:p></o:p></p>
<p class="MsoPlainText"> <span style="font-family:"Courier New"">RP-Response-code@rp.certification.openid.net<o:p></o:p></span></p>
<p class="MsoPlainText"><span style="font-family:"Courier New""> https://rp.certification.openid.net/RP-Response-code<o:p></o:p></span></p>
<p class="MsoPlainText"><o:p> </o:p></p>
<p class="MsoPlainText">After that, the RP’s support for WebFinger and using .well-known/openid-configuration will do the rest automatically.<o:p></o:p></p>
<p class="MsoPlainText"><o:p> </o:p></p>
<p class="MsoPlainText">That should be easy to do, shouldn’t it, Roland?<o:p></o:p></p>
<p class="MsoPlainText"><o:p> </o:p></p>
<p class="MsoPlainText"> -- Mike<o:p></o:p></p>
<p class="MsoPlainText">-----Original Message-----<br>
From: Openid-specs-ab [mailto:openid-specs-ab-bounces@lists.openid.net] On Behalf Of Hans Zandbelt<br>
Sent: Thursday, March 26, 2015 2:45 PM<br>
To: Justin Richer; Roland Hedberg<br>
Cc: openid-specs-ab@lists.openid.net Ab<br>
Subject: Re: [Openid-specs-ab] RP testing</p>
<p class="MsoPlainText"><o:p> </o:p></p>
<p class="MsoPlainText">which in its turn means that the net effect is that both of Roland's approaches end up being the same: "a bunch of OP configured to work in slightly different ways", granted that they are implemented as a single "multi-tenant" service,
but the distinction is not visible to clients, right?<o:p></o:p></p>
<p class="MsoPlainText"><o:p> </o:p></p>
<p class="MsoPlainText">Hans.<o:p></o:p></p>
<p class="MsoPlainText"><o:p> </o:p></p>
<p class="MsoPlainText">On 3/25/15 4:39 PM, Justin Richer wrote:<o:p></o:p></p>
<p class="MsoPlainText">> I really like this approach. It makes it simple for RPs that can handle dynamic discovery (which is a very, very low bar), and it should be clear to developers/testers which test they’re trying to use at a given time.<o:p></o:p></p>
<p class="MsoPlainText">><o:p> </o:p></p>
<p class="MsoPlainText">> It also means that each RP test will effectively have a separate issuer, which is a good way to separate things cleanly.<o:p></o:p></p>
<p class="MsoPlainText">><o:p> </o:p></p>
<p class="MsoPlainText">> — Justin<o:p></o:p></p>
<p class="MsoPlainText">><o:p> </o:p></p>
<p class="MsoPlainText">><o:p> </o:p></p>
<p class="MsoPlainText">>> On Mar 25, 2015, at 6:03 AM, Roland Hedberg <<a href="mailto:roland.hedberg@umu.se"><span style="color:windowtext;text-decoration:none">roland.hedberg@umu.se</span></a>> wrote:<o:p></o:p></p>
<p class="MsoPlainText">>><o:p> </o:p></p>
<p class="MsoPlainText">>> On to the next challenge :-)<o:p></o:p></p>
<p class="MsoPlainText">>><o:p> </o:p></p>
<p class="MsoPlainText">>> In order to do RP testing you either need a bunch of OP configured to work in slightly different ways or you need an OP that can change behavior on command.<o:p></o:p></p>
<p class="MsoPlainText">>><o:p> </o:p></p>
<p class="MsoPlainText">>> I’ve chosen the later path.<o:p></o:p></p>
<p class="MsoPlainText">>> I’ve constructed an OP that can be ’steered’ by crafting the URLs used in a special way.<o:p></o:p></p>
<p class="MsoPlainText">>><o:p> </o:p></p>
<p class="MsoPlainText">>> The basic format of the path is:<o:p></o:p></p>
<p class="MsoPlainText">>><o:p> </o:p></p>
<p class="MsoPlainText">>> /<id>/<signalg>/<encalg>/<errtype>/<claims>/<endpoint><o:p></o:p></p>
<p class="MsoPlainText">>><o:p> </o:p></p>
<p class="MsoPlainText">>> To start from the end:<o:p></o:p></p>
<p class="MsoPlainText">>><o:p> </o:p></p>
<p class="MsoPlainText">>> endpoint<o:p></o:p></p>
<p class="MsoPlainText">>> is of course the different endpoints the OP presents
<o:p></o:p></p>
<p class="MsoPlainText">>> (authorization/token/userinfo/..) claims<o:p></o:p></p>
<p class="MsoPlainText">>> is normal/aggregated/distributed<o:p></o:p></p>
<p class="MsoPlainText">>> errtype<o:p></o:p></p>
<p class="MsoPlainText">>> this is errors the OP should perform. This is to make certain that the RP actually checks and<o:p></o:p></p>
<p class="MsoPlainText">>> understands what it receives. So far I’ve defined these errors:<o:p></o:p></p>
<p class="MsoPlainText">>> ath the at_hash is incorrect<o:p></o:p></p>
<p class="MsoPlainText">>> aud ID Token with invalid aud<o:p></o:p></p>
<p class="MsoPlainText">>> ch the c_hash is incorrect<o:p></o:p></p>
<p class="MsoPlainText">>> iat ID Token without iat claim<o:p></o:p></p>
<p class="MsoPlainText">>> idts the id_token signature is invalid<o:p></o:p></p>
<p class="MsoPlainText">>> issi the id_token iss value is not the same as the provider info issuer<o:p></o:p></p>
<p class="MsoPlainText">>> isso the provider info issuer is not the same as the discovery url<o:p></o:p></p>
<p class="MsoPlainText">>> itsub ID Token without sub claim<o:p></o:p></p>
<p class="MsoPlainText">>> kmm signing/encryption with a key the RP doesn't have access to<o:p></o:p></p>
<p class="MsoPlainText">>> nonce the nonce value returned is not the same as the received<o:p></o:p></p>
<p class="MsoPlainText">>> state the state value returned is not the same as the received<o:p></o:p></p>
<p class="MsoPlainText">>> encalg<o:p></o:p></p>
<p class="MsoPlainText">>> The encryption algorithms used, this is actually a tuple. The encryption alg<o:p></o:p></p>
<p class="MsoPlainText">>> and the encryption enc algorithms. The tuple are joined by a ':' so a typical<o:p></o:p></p>
<p class="MsoPlainText">>> value could be RSA1_5:A128CBC-HS256.<o:p></o:p></p>
<p class="MsoPlainText">>> signalg<o:p></o:p></p>
<p class="MsoPlainText">>> Specifies which algorithm that the OP should use for signing JWTs, this algorithm<o:p></o:p></p>
<p class="MsoPlainText">>> is use for all signing. So it will for instance be used both for id_token and user<o:p></o:p></p>
<p class="MsoPlainText">>> info signing. A typical value would be RSA256.<o:p></o:p></p>
<p class="MsoPlainText">>> id<o:p></o:p></p>
<p class="MsoPlainText">>> An identifier of the test run. This together with the IP address of the RP will<o:p></o:p></p>
<p class="MsoPlainText">>> be used to construct the filename in which the log of the test seen from the OP’s side<o:p></o:p></p>
<p class="MsoPlainText">>> will be stored.<o:p></o:p></p>
<p class="MsoPlainText">>><o:p> </o:p></p>
<p class="MsoPlainText">>><o:p> </o:p></p>
<p class="MsoPlainText">>> So if you would want to test rp-idt-iat (Reject ID Token without iat
<o:p></o:p></p>
<p class="MsoPlainText">>> claim) the path of the URL for the authorization endpoint could be:<o:p></o:p></p>
<p class="MsoPlainText">>><o:p> </o:p></p>
<p class="MsoPlainText">>> /rp-idt-iat/_/_/iat/normal/authorization_endpoint<o:p></o:p></p>
<p class="MsoPlainText">>><o:p> </o:p></p>
<p class="MsoPlainText">>> It’s obvious that testing a RP that does not support dynamic provider
<o:p></o:p></p>
<p class="MsoPlainText">>> configuration will be very laborious with the above setup so I’ve
<o:p></o:p></p>
<p class="MsoPlainText">>> worked with the assumption that all the RPs to test can read
<o:p></o:p></p>
<p class="MsoPlainText">>> configuration from a .well-known/openid-configuration URL and understand it.<o:p></o:p></p>
<p class="MsoPlainText">>><o:p> </o:p></p>
<p class="MsoPlainText">>> Now, Edmund Jay asked the question whether it would be possible to
<o:p></o:p></p>
<p class="MsoPlainText">>> make it even simpler for the RP and just request it to know the test IDs and not construct the whole path.<o:p></o:p></p>
<p class="MsoPlainText">>> And it can be done.<o:p></o:p></p>
<p class="MsoPlainText">>><o:p> </o:p></p>
<p class="MsoPlainText">>> It would mean that the RP would read for example <o:p>
</o:p></p>
<p class="MsoPlainText">>> <a href="https://example.com/rp-idt-iat/.well-known/openid-configuration">
<span style="color:windowtext;text-decoration:none">https://example.com/rp-idt-iat/.well-known/openid-configuration</span></a> and
<o:p></o:p></p>
<p class="MsoPlainText">>> the returned provider configuration would contain claims like this:<o:p></o:p></p>
<p class="MsoPlainText">>><o:p> </o:p></p>
<p class="MsoPlainText">>> {<o:p></o:p></p>
<p class="MsoPlainText">>> ”authorization_endpoint”: "<a href="https://example.com/rp-idt-iat/_/_/iat/normal/authorize"><span style="color:windowtext;text-decoration:none">https://example.com/rp-idt-iat/_/_/iat/normal/authorize</span></a>",<o:p></o:p></p>
<p class="MsoPlainText">>> ”token_endpoint”: ”<a href="https://example.com/rp-idt-iat/_/_/iat/normal/token"><span style="color:windowtext;text-decoration:none">https://example.com/rp-idt-iat/_/_/iat/normal/token</span></a>”,<o:p></o:p></p>
<p class="MsoPlainText">>> …<o:p></o:p></p>
<p class="MsoPlainText">>> }<o:p></o:p></p>
<p class="MsoPlainText">>><o:p> </o:p></p>
<p class="MsoPlainText">>> Questions/comments ?<o:p></o:p></p>
<p class="MsoPlainText">>><o:p> </o:p></p>
<p class="MsoPlainText">>> - Roland<o:p></o:p></p>
<p class="MsoPlainText">>><o:p> </o:p></p>
<p class="MsoPlainText">>> "It is the consequence of humanity. We are all formed of frailty and
<o:p></o:p></p>
<p class="MsoPlainText">>> error; let us pardon reciprocally each others’ folly - that is the
<o:p></o:p></p>
<p class="MsoPlainText">>> first law of nature.” - Voltaire<o:p></o:p></p>
<p class="MsoPlainText">>><o:p> </o:p></p>
<p class="MsoPlainText">>><o:p> </o:p></p>
<p class="MsoPlainText">>><o:p> </o:p></p>
<p class="MsoPlainText">>><o:p> </o:p></p>
<p class="MsoPlainText">>><o:p> </o:p></p>
<p class="MsoPlainText">>> _______________________________________________<o:p></o:p></p>
<p class="MsoPlainText">>> Openid-specs-ab mailing list<o:p></o:p></p>
<p class="MsoPlainText">>> <a href="mailto:Openid-specs-ab@lists.openid.net"><span style="color:windowtext;text-decoration:none">Openid-specs-ab@lists.openid.net</span></a><o:p></o:p></p>
<p class="MsoPlainText">>> <a href="http://lists.openid.net/mailman/listinfo/openid-specs-ab">
<span style="color:windowtext;text-decoration:none">http://lists.openid.net/mailman/listinfo/openid-specs-ab</span></a><o:p></o:p></p>
<p class="MsoPlainText">><o:p> </o:p></p>
<p class="MsoPlainText">><o:p> </o:p></p>
<p class="MsoPlainText">><o:p> </o:p></p>
<p class="MsoPlainText">> _______________________________________________<o:p></o:p></p>
<p class="MsoPlainText">> Openid-specs-ab mailing list<o:p></o:p></p>
<p class="MsoPlainText">> <a href="mailto:Openid-specs-ab@lists.openid.net"><span style="color:windowtext;text-decoration:none">Openid-specs-ab@lists.openid.net</span></a><o:p></o:p></p>
<p class="MsoPlainText">> <a href="http://lists.openid.net/mailman/listinfo/openid-specs-ab">
<span style="color:windowtext;text-decoration:none">http://lists.openid.net/mailman/listinfo/openid-specs-ab</span></a><o:p></o:p></p>
<p class="MsoPlainText">><o:p> </o:p></p>
<p class="MsoPlainText"><o:p> </o:p></p>
<p class="MsoPlainText">-- <o:p></o:p></p>
<p class="MsoPlainText">Hans Zandbelt | Sr. Technical Architect<o:p></o:p></p>
<p class="MsoPlainText"><a href="mailto:hzandbelt@pingidentity.com"><span style="color:windowtext;text-decoration:none">hzandbelt@pingidentity.com</span></a> | Ping Identity _______________________________________________<o:p></o:p></p>
<p class="MsoPlainText">Openid-specs-ab mailing list<o:p></o:p></p>
<p class="MsoPlainText"><a href="mailto:Openid-specs-ab@lists.openid.net"><span style="color:windowtext;text-decoration:none">Openid-specs-ab@lists.openid.net</span></a><o:p></o:p></p>
<p class="MsoPlainText"><a href="http://lists.openid.net/mailman/listinfo/openid-specs-ab"><span style="color:windowtext;text-decoration:none">http://lists.openid.net/mailman/listinfo/openid-specs-ab</span></a><o:p></o:p></p>
</div>
</body>
</html>