Server.php 93 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393239423952396239723982399240024012402240324042405240624072408240924102411241224132414241524162417241824192420242124222423242424252426242724282429243024312432243324342435243624372438243924402441244224432444244524462447244824492450245124522453245424552456245724582459246024612462246324642465
  1. <?php
  2. /**
  3. * Tests for Auth_OpenID_Server
  4. */
  5. require_once "PHPUnit.php";
  6. require_once "Tests/Auth/OpenID/MemStore.php";
  7. require_once "Auth/OpenID.php";
  8. require_once "Auth/OpenID/DiffieHellman.php";
  9. require_once "Auth/OpenID/Server.php";
  10. require_once "Auth/OpenID/Consumer.php";
  11. function altModulus()
  12. {
  13. $lib =& Auth_OpenID_getMathLib();
  14. static $num = null;
  15. if (!$num) {
  16. $num = $lib->init("1423261515703355186607439952816216983770".
  17. "5735494988446894302176757360889904836136".
  18. "0422513557553514790045512299468953431585".
  19. "3008125488594198571710943663581589034331".
  20. "6791551733211386105974742540867014420109".
  21. "9811846875730766487278261498262568348338".
  22. "4764372005569983660877797099908075182915".
  23. "81860338635288400119293970087"
  24. );
  25. }
  26. return $num;
  27. }
  28. global $ALT_GEN;
  29. $ALT_GEN = 5;
  30. function arrayToString($arr)
  31. {
  32. $s = "Array(";
  33. $parts = array();
  34. foreach ($arr as $k => $v) {
  35. if (is_array($v)) {
  36. $v = arrayToString($v);
  37. }
  38. $parts[] = sprintf("%s => %s", $k, $v);
  39. }
  40. $s .= implode(", ", $parts);
  41. $s .= ")";
  42. return $s;
  43. }
  44. function _Auth_OpenID_NotAuthorized()
  45. {
  46. return false;
  47. }
  48. class Tests_Auth_OpenID_Test_ServerError extends PHPUnit_TestCase {
  49. function test_browserWithReturnTo()
  50. {
  51. $return_to = "http://rp.unittest/consumer";
  52. // will be a ProtocolError raised by Decode or CheckIDRequest.answer
  53. $args = array(
  54. 'openid.mode' => 'monkeydance',
  55. 'openid.identity' => 'http://wagu.unittest/',
  56. 'openid.return_to' => $return_to);
  57. $e = new Auth_OpenID_ServerError(
  58. Auth_OpenID_Message::fromPostArgs($args),
  59. "plucky");
  60. $this->assertTrue($e->hasReturnTo());
  61. $expected_args = array(
  62. 'openid.mode' => 'error',
  63. 'openid.error' => 'plucky');
  64. $encoded = $e->encodeToURL();
  65. if (Auth_OpenID_isError($encoded)) {
  66. $this->fail($encoded->toString());
  67. return;
  68. }
  69. list($rt_base, $_result_args) = explode("?", $e->encodeToURL(), 2);
  70. $result_args = Auth_OpenID::getQuery($_result_args);
  71. $this->assertEquals($result_args, $expected_args);
  72. }
  73. function test_browserWithReturnTo_OpenID2_GET()
  74. {
  75. $return_to = "http://rp.unittest/consumer";
  76. // will be a ProtocolError raised by Decode or
  77. // CheckIDRequest.answer
  78. $args = Auth_OpenID_Message::fromPostArgs(array(
  79. 'openid.ns' => Auth_OpenID_OPENID2_NS,
  80. 'openid.mode' => 'monkeydance',
  81. 'openid.identity' => 'http://wagu.unittest/',
  82. 'openid.claimed_id' => 'http://wagu.unittest/',
  83. 'openid.return_to' => $return_to));
  84. $e = new Auth_OpenID_ServerError($args, "plucky");
  85. $this->assertTrue($e->hasReturnTo());
  86. $expected_args = array('openid.ns' => Auth_OpenID_OPENID2_NS,
  87. 'openid.mode' => 'error',
  88. 'openid.error' => 'plucky');
  89. list($rt_base, $result_args_s) = explode('?', $e->encodeToURL(), 2);
  90. $result_args = Auth_OpenID::parse_str($result_args_s);
  91. $this->assertEquals($result_args, $expected_args);
  92. }
  93. function test_browserWithReturnTo_OpenID2_POST()
  94. {
  95. $return_to = "http://rp.unittest/consumer" . str_repeat('x', Auth_OpenID_OPENID1_URL_LIMIT);
  96. // will be a ProtocolError raised by Decode or
  97. // CheckIDRequest.answer
  98. $args = Auth_OpenID_Message::fromPostArgs(array(
  99. 'openid.ns' => Auth_OpenID_OPENID2_NS,
  100. 'openid.mode' => 'monkeydance',
  101. 'openid.identity' => 'http://wagu.unittest/',
  102. 'openid.claimed_id' => 'http://wagu.unittest/',
  103. 'openid.return_to' => $return_to));
  104. $e = new Auth_OpenID_ServerError($args, "plucky");
  105. $this->assertTrue($e->hasReturnTo());
  106. $expected_args = array('openid.ns' => Auth_OpenID_OPENID2_NS,
  107. 'openid.mode' => 'error',
  108. 'openid.error' => 'plucky');
  109. $this->assertTrue($e->whichEncoding() == Auth_OpenID_ENCODE_HTML_FORM);
  110. $msg = $e->toMessage();
  111. $this->assertTrue($e->toFormMarkup() ==
  112. $msg->toFormMarkup($args->getArg(Auth_OpenID_OPENID_NS, 'return_to')));
  113. }
  114. function test_browserWithReturnTo_OpenID1_exceeds_limit()
  115. {
  116. $return_to = "http://rp.unittest/consumer" . str_repeat('x', Auth_OpenID_OPENID1_URL_LIMIT);
  117. // will be a ProtocolError raised by Decode or
  118. // CheckIDRequest.answer
  119. $args = Auth_OpenID_Message::fromPostArgs(array(
  120. 'openid.mode' => 'monkeydance',
  121. 'openid.identity' => 'http://wagu.unittest/',
  122. 'openid.return_to' => $return_to));
  123. $this->assertTrue($args->isOpenID1());
  124. $e = new Auth_OpenID_ServerError($args, "plucky");
  125. $this->assertTrue($e->hasReturnTo());
  126. $expected_args = array('openid.mode' => 'error',
  127. 'openid.error' => 'plucky');
  128. $this->assertTrue($e->whichEncoding() == Auth_OpenID_ENCODE_URL);
  129. list($rt_base, $result_args_s) = explode('?', $e->encodeToURL(), 2);
  130. $result_args = Auth_OpenID::parse_str($result_args_s);
  131. $this->assertEquals($result_args, $expected_args);
  132. }
  133. function test_noReturnTo()
  134. {
  135. // will be a ProtocolError raised by Decode or CheckIDRequest.answer
  136. $args = array(
  137. 'openid.mode' => 'zebradance',
  138. 'openid.identity' => 'http://wagu.unittest/');
  139. $e = new Auth_OpenID_ServerError(
  140. Auth_OpenID_Message::fromPostArgs($args),
  141. "waffles");
  142. $this->assertFalse($e->hasReturnTo());
  143. $expected = "error:waffles\nmode:error\n";
  144. $this->assertEquals($e->encodeToKVForm(), $expected);
  145. }
  146. function test_noMessage()
  147. {
  148. $e = new Auth_OpenID_ServerError();
  149. $this->assertFalse($e->hasReturnTo());
  150. $this->assertEquals($e->whichEncoding(), null);
  151. $this->assertEquals($e->getReturnTo(), null);
  152. }
  153. }
  154. class Tests_Auth_OpenID_Test_Decode extends PHPUnit_TestCase {
  155. function setUp()
  156. {
  157. $this->id_url = "http://decoder.am.unittest/";
  158. $this->rt_url = "http://rp.unittest/foobot/?qux=zam";
  159. $this->tr_url = "http://rp.unittest/";
  160. $this->assoc_handle = "{assoc}{handle}";
  161. $this->claimed_id = 'http://de.legating.de.coder.unittest/';
  162. $this->op_endpoint = 'http://endpoint.unittest/encode';
  163. $this->store = new Tests_Auth_OpenID_MemStore();
  164. $this->server = new Auth_OpenID_Server($this->store,
  165. $this->op_endpoint);
  166. $this->decoder = new Auth_OpenID_Decoder($this->server);
  167. }
  168. function test_none()
  169. {
  170. $args = array();
  171. $r = $this->decoder->decode($args);
  172. $this->assertEquals($r, null);
  173. }
  174. function test_irrelevant()
  175. {
  176. $args = array(
  177. 'pony' => 'spotted',
  178. 'sreg.mutant_power' => 'decaffinator');
  179. $r = $this->decoder->decode($args);
  180. $this->assertTrue(is_a($r, 'Auth_OpenID_ServerError'));
  181. }
  182. function test_bad()
  183. {
  184. $args = array(
  185. 'openid.mode' => 'twos-compliment',
  186. 'openid.pants' => 'zippered');
  187. // Be sure that decoding the args returns an error.
  188. $result = $this->decoder->decode($args);
  189. $this->assertTrue(Auth_OpenID_isError($result));
  190. }
  191. function test_checkidImmediate()
  192. {
  193. $args = array(
  194. 'openid.mode' => 'checkid_immediate',
  195. 'openid.identity' => $this->id_url,
  196. 'openid.assoc_handle' => $this->assoc_handle,
  197. 'openid.return_to' => $this->rt_url,
  198. 'openid.trust_root' => $this->tr_url,
  199. # should be ignored
  200. 'openid.some.extension' => 'junk');
  201. $r = $this->decoder->decode($args);
  202. $this->assertTrue(is_a($r, 'Auth_OpenID_CheckIDRequest'));
  203. $this->assertEquals($r->mode, "checkid_immediate");
  204. $this->assertEquals($r->immediate, true);
  205. $this->assertEquals($r->identity, $this->id_url);
  206. $this->assertEquals($r->trust_root, $this->tr_url);
  207. $this->assertEquals($r->return_to, $this->rt_url);
  208. $this->assertEquals($r->assoc_handle, $this->assoc_handle);
  209. }
  210. function test_checkidSetup()
  211. {
  212. $args = array(
  213. 'openid.mode' => 'checkid_setup',
  214. 'openid.identity' => $this->id_url,
  215. 'openid.assoc_handle' => $this->assoc_handle,
  216. 'openid.return_to' => $this->rt_url,
  217. 'openid.trust_root' => $this->tr_url);
  218. $r = $this->decoder->decode($args);
  219. $this->assertTrue(is_a($r, 'Auth_OpenID_CheckIDRequest'));
  220. $this->assertEquals($r->mode, "checkid_setup");
  221. $this->assertEquals($r->immediate, false);
  222. $this->assertEquals($r->identity, $this->id_url);
  223. $this->assertEquals($r->trust_root, $this->tr_url);
  224. $this->assertEquals($r->return_to, $this->rt_url);
  225. }
  226. function test_checkidSetupOpenID2()
  227. {
  228. $args = array(
  229. 'openid.ns' => Auth_OpenID_OPENID2_NS,
  230. 'openid.mode' => 'checkid_setup',
  231. 'openid.identity' => $this->id_url,
  232. 'openid.claimed_id' => $this->claimed_id,
  233. 'openid.assoc_handle' => $this->assoc_handle,
  234. 'openid.return_to' => $this->rt_url,
  235. 'openid.realm' => $this->tr_url
  236. );
  237. $r = $this->decoder->decode($args);
  238. $this->assertTrue(is_a($r, 'Auth_OpenID_CheckIDRequest'));
  239. $this->assertEquals($r->mode, "checkid_setup");
  240. $this->assertEquals($r->immediate, False);
  241. $this->assertEquals($r->identity, $this->id_url);
  242. $this->assertEquals($r->claimed_id, $this->claimed_id);
  243. $this->assertEquals($r->trust_root, $this->tr_url);
  244. $this->assertEquals($r->return_to, $this->rt_url);
  245. }
  246. function test_checkidSetupNoClaimedIDOpenID2()
  247. {
  248. $args = array(
  249. 'openid.ns' => Auth_OpenID_OPENID2_NS,
  250. 'openid.mode' => 'checkid_setup',
  251. 'openid.identity' => $this->id_url,
  252. 'openid.assoc_handle' => $this->assoc_handle,
  253. 'openid.return_to' => $this->rt_url,
  254. 'openid.realm' => $this->tr_url
  255. );
  256. $result = $this->decoder->decode($args);
  257. $this->assertTrue(is_a($result, "Auth_OpenID_ServerError"));
  258. }
  259. function test_checkidSetupNoIdentityOpenID2()
  260. {
  261. $args = array(
  262. 'openid.ns' => Auth_OpenID_OPENID2_NS,
  263. 'openid.mode' => 'checkid_setup',
  264. 'openid.assoc_handle' => $this->assoc_handle,
  265. 'openid.return_to' => $this->rt_url,
  266. 'openid.realm' => $this->tr_url);
  267. $r = $this->decoder->decode($args);
  268. $this->assertTrue(is_a($r, 'Auth_OpenID_CheckIDRequest'));
  269. $this->assertEquals($r->mode, "checkid_setup");
  270. $this->assertEquals($r->immediate, false);
  271. $this->assertEquals($r->identity, null);
  272. $this->assertEquals($r->trust_root, $this->tr_url);
  273. $this->assertEquals($r->return_to, $this->rt_url);
  274. }
  275. function test_checkidSetupNoReturnOpenID1()
  276. {
  277. $args = array(
  278. 'openid.mode' => 'checkid_setup',
  279. 'openid.identity' => $this->id_url,
  280. 'openid.assoc_handle' => $this->assoc_handle,
  281. 'openid.trust_root' => $this->tr_url);
  282. $result = $this->decoder->decode($args);
  283. if (!Auth_OpenID_isError($result)) {
  284. $this->fail("Expected Auth_OpenID_ServerError");
  285. }
  286. }
  287. function test_checkidSetupNoReturnOpenID2()
  288. {
  289. // Make sure an OpenID 2 request with no return_to can be
  290. // decoded, and make sure a response to such a request raises
  291. // NoReturnToError.
  292. $args = array(
  293. 'openid.ns' => Auth_OpenID_OPENID2_NS,
  294. 'openid.mode' => 'checkid_setup',
  295. 'openid.identity' => $this->id_url,
  296. 'openid.claimed_id' => $this->id_url,
  297. 'openid.assoc_handle' => $this->assoc_handle,
  298. 'openid.realm' => $this->tr_url);
  299. $req = $this->decoder->decode($args);
  300. $this->assertTrue(is_a($req,
  301. 'Auth_OpenID_CheckIDRequest'));
  302. $this->assertTrue(is_a($req->answer(false), 'Auth_OpenID_NoReturnToError'));
  303. $this->assertTrue(is_a($req->encodeToURL('bogus'), 'Auth_OpenID_NoReturnToError'));
  304. $this->assertTrue(is_a($req->getCancelURL(), 'Auth_OpenID_NoReturnToError'));
  305. }
  306. function test_checkidSetupRealmRequiredOpenID2()
  307. {
  308. // Make sure that an OpenID 2 request which lacks return_to
  309. // cannot be decoded if it lacks a realm. Spec: This value
  310. // (openid.realm) MUST be sent if openid.return_to is omitted.
  311. $args = array(
  312. 'openid.ns' => Auth_OpenID_OPENID2_NS,
  313. 'openid.mode' => 'checkid_setup',
  314. 'openid.identity' => $this->id_url,
  315. 'openid.assoc_handle' => $this->assoc_handle);
  316. $this->assertTrue(is_a($this->decoder->decode($args),
  317. 'Auth_OpenID_ServerError'));
  318. }
  319. function test_checkidSetupBadReturn()
  320. {
  321. $args = array(
  322. 'openid.mode' => 'checkid_setup',
  323. 'openid.identity' => $this->id_url,
  324. 'openid.assoc_handle' => $this->assoc_handle,
  325. 'openid.return_to' => 'not a url');
  326. $result = $this->decoder->decode($args);;
  327. if (Auth_OpenID_isError($result)) {
  328. $this->assertTrue($result->message);
  329. } else {
  330. $this->fail(sprintf("Expected ProtocolError, instead " .
  331. "returned with %s", gettype($result)));
  332. }
  333. }
  334. function test_checkidSetupUntrustedReturn()
  335. {
  336. $args = array(
  337. 'openid.mode' => 'checkid_setup',
  338. 'openid.identity' => $this->id_url,
  339. 'openid.assoc_handle' => $this->assoc_handle,
  340. 'openid.return_to' => $this->rt_url,
  341. 'openid.trust_root' => 'http://not-the-return-place.unittest/');
  342. $result = $this->decoder->decode($args);
  343. $this->assertTrue(is_a($result, 'Auth_OpenID_UntrustedReturnURL'));
  344. }
  345. function test_checkAuth()
  346. {
  347. $args = array(
  348. 'openid.mode' => 'check_authentication',
  349. 'openid.assoc_handle' => '{dumb}{handle}',
  350. 'openid.sig' => 'sigblob',
  351. 'openid.signed' => 'foo,bar,mode',
  352. 'openid.foo' => 'signedval1',
  353. 'openid.bar' => 'signedval2',
  354. 'openid.baz' => 'unsigned');
  355. $r = $this->decoder->decode($args);
  356. $this->assertTrue(is_a($r, 'Auth_OpenID_CheckAuthRequest'));
  357. $this->assertEquals($r->mode, 'check_authentication');
  358. $this->assertEquals($r->sig, 'sigblob');
  359. }
  360. function test_checkAuthMissingSignature()
  361. {
  362. $args = array(
  363. 'openid.mode' => 'check_authentication',
  364. 'openid.assoc_handle' => '{dumb}{handle}',
  365. 'openid.signed' => 'foo,bar,mode',
  366. 'openid.foo' => 'signedval1',
  367. 'openid.bar' => 'signedval2',
  368. 'openid.baz' => 'unsigned');
  369. $r = $this->decoder->decode($args);
  370. $this->assertTrue(is_a($r, 'Auth_OpenID_ServerError'));
  371. }
  372. function test_checkAuthAndInvalidate()
  373. {
  374. $args = array(
  375. 'openid.mode' => 'check_authentication',
  376. 'openid.assoc_handle' => '{dumb}{handle}',
  377. 'openid.invalidate_handle' => '[[SMART_handle]]',
  378. 'openid.sig' => 'sigblob',
  379. 'openid.signed' => 'foo,bar,mode',
  380. 'openid.foo' => 'signedval1',
  381. 'openid.bar' => 'signedval2',
  382. 'openid.baz' => 'unsigned');
  383. $r = $this->decoder->decode($args);
  384. $this->assertTrue(is_a($r, 'Auth_OpenID_CheckAuthRequest'));
  385. $this->assertEquals($r->invalidate_handle, '[[SMART_handle]]');
  386. }
  387. function test_associateDH()
  388. {
  389. if (defined('Auth_OpenID_NO_MATH_SUPPORT')) {
  390. print "(Skipping test_associateDH)";
  391. return;
  392. }
  393. $args = array(
  394. 'openid.mode' => 'associate',
  395. 'openid.session_type' => 'DH-SHA1',
  396. 'openid.dh_consumer_public' => "Rzup9265tw==");
  397. $r = $this->decoder->decode($args);
  398. $this->assertTrue(is_a($r, 'Auth_OpenID_AssociateRequest'));
  399. $this->assertEquals($r->mode, "associate");
  400. $this->assertEquals($r->session->session_type, "DH-SHA1");
  401. $this->assertEquals($r->assoc_type, "HMAC-SHA1");
  402. $this->assertTrue($r->session->consumer_pubkey);
  403. }
  404. function test_associateDHMissingKey()
  405. {
  406. if (defined('Auth_OpenID_NO_MATH_SUPPORT')) {
  407. print "(Skipping test_associateDHMissingKey)";
  408. return;
  409. }
  410. $args = array(
  411. 'openid.mode' => 'associate',
  412. 'openid.session_type' => 'DH-SHA1');
  413. // Using DH-SHA1 without supplying dh_consumer_public is an error.
  414. $result = $this->decoder->decode($args);
  415. if (!Auth_OpenID_isError($result)) {
  416. $this->fail(sprintf("Expected Auth_OpenID_ServerError, got %s",
  417. gettype($result)));
  418. }
  419. }
  420. /**
  421. * XXX: Cannot produce a value to break base64_decode
  422. function test_associateDHpubKeyNotB64()
  423. {
  424. $args = array(
  425. 'openid.mode' => 'associate',
  426. 'openid.session_type' => 'DH-SHA1',
  427. 'openid.dh_consumer_public' => "donkeydonkeydonkey");
  428. $r = $this->decoder->decode($args);
  429. $this->assertTrue(is_a($r, 'Auth_OpenID_ServerError'));
  430. }
  431. */
  432. function test_associateDHModGen()
  433. {
  434. if (defined('Auth_OpenID_NO_MATH_SUPPORT')) {
  435. print "(Skipping test_associateDHModGen)";
  436. return;
  437. }
  438. global $ALT_GEN;
  439. // test dh with non-default but valid values for dh_modulus
  440. // and dh_gen
  441. $lib =& Auth_OpenID_getMathLib();
  442. $args = array(
  443. 'openid.mode' => 'associate',
  444. 'openid.session_type' => 'DH-SHA1',
  445. 'openid.dh_consumer_public' => "Rzup9265tw==",
  446. 'openid.dh_modulus' => $lib->longToBase64(altModulus()),
  447. 'openid.dh_gen' => $lib->longToBase64($ALT_GEN));
  448. $r = $this->decoder->decode($args);
  449. $this->assertTrue(is_a($r, 'Auth_OpenID_AssociateRequest'));
  450. $this->assertEquals($r->mode, "associate");
  451. $this->assertEquals($r->session->session_type, "DH-SHA1");
  452. $this->assertEquals($r->assoc_type, "HMAC-SHA1");
  453. $this->assertTrue($lib->cmp($r->session->dh->mod, altModulus()) === 0);
  454. $this->assertTrue($lib->cmp($r->session->dh->gen, $ALT_GEN) === 0);
  455. $this->assertTrue($r->session->consumer_pubkey);
  456. }
  457. /**
  458. * XXX: Can't test invalid base64 values for mod and gen because
  459. * PHP's base64 decoder is much too forgiving or just plain
  460. * broken.
  461. function test_associateDHCorruptModGen()
  462. {
  463. // test dh with non-default but valid values for dh_modulus
  464. // and dh_gen
  465. $args = array(
  466. 'openid.mode' => 'associate',
  467. 'openid.session_type' => 'DH-SHA1',
  468. 'openid.dh_consumer_public' => "Rzup9265tw==",
  469. 'openid.dh_modulus' => 'pizza',
  470. 'openid.dh_gen' => 'gnocchi');
  471. $r = $this->decoder->decode($args);
  472. print_r($r);
  473. $this->assertTrue(is_a($r, 'Auth_OpenID_ServerError'));
  474. }
  475. */
  476. function test_associateDHMissingModGen()
  477. {
  478. if (defined('Auth_OpenID_NO_MATH_SUPPORT')) {
  479. print "(Skipping test_associateDHMissingModGen)";
  480. return;
  481. }
  482. // test dh with non-default but valid values for dh_modulus
  483. // and dh_gen
  484. $args = array(
  485. 'openid.mode' => 'associate',
  486. 'openid.session_type' => 'DH-SHA1',
  487. 'openid.dh_consumer_public' => "Rzup9265tw==",
  488. 'openid.dh_modulus' => 'pizza');
  489. $r = $this->decoder->decode($args);
  490. $this->assertTrue(is_a($r, 'Auth_OpenID_ServerError'));
  491. }
  492. function test_associateWeirdSession()
  493. {
  494. $args = array(
  495. 'openid.mode' => 'associate',
  496. 'openid.session_type' => 'FLCL6',
  497. 'openid.dh_consumer_public' => "YQ==\n");
  498. $r = $this->decoder->decode($args);
  499. $this->assertTrue(is_a($r, 'Auth_OpenID_ServerError'));
  500. }
  501. function test_associatePlain()
  502. {
  503. $args = array('openid.mode' => 'associate');
  504. $r = $this->decoder->decode($args);
  505. $this->assertTrue(is_a($r, 'Auth_OpenID_AssociateRequest'));
  506. $this->assertEquals($r->mode, "associate");
  507. $this->assertEquals($r->session->session_type, "no-encryption");
  508. $this->assertEquals($r->assoc_type, "HMAC-SHA1");
  509. }
  510. function test_nomode()
  511. {
  512. $args = array(
  513. 'openid.session_type' => 'DH-SHA1',
  514. 'openid.dh_consumer_public' => "my public keeey");
  515. $result = $this->decoder->decode($args);
  516. if (!Auth_OpenID_isError($result)) {
  517. $this->fail(sprintf("Expected Auth_OpenID_Error. Got %s",
  518. gettype($result)));
  519. }
  520. }
  521. function test_invalidns()
  522. {
  523. $args = array('openid.ns' => 'Tuesday',
  524. 'openid.mode' => 'associate');
  525. $result = $this->decoder->decode($args);
  526. $this->assertTrue(is_a($result, 'Auth_OpenID_ServerError'));
  527. // Assert that the ProtocolError does have a Message attached
  528. // to it, even though the request wasn't a well-formed Message.
  529. $this->assertTrue($result->message);
  530. // The error message contains the bad openid.ns.
  531. $this->assertTrue(strpos($result->text, 'Tuesday') != -1);
  532. }
  533. }
  534. class Tests_Auth_OpenID_Test_Encode extends PHPUnit_TestCase {
  535. function setUp()
  536. {
  537. $this->encoder = new Auth_OpenID_Encoder();
  538. $this->encode = $this->encoder;
  539. $this->op_endpoint = 'http://endpoint.unittest/encode';
  540. $this->store = new Tests_Auth_OpenID_MemStore();
  541. $this->server = new Auth_OpenID_Server($this->store,
  542. $this->op_endpoint);
  543. }
  544. function encode($thing) {
  545. return $this->encoder->encode($thing);
  546. }
  547. function test_id_res_OpenID2_GET()
  548. {
  549. /* Check that when an OpenID 2 response does not exceed the
  550. OpenID 1 message size, a GET response (i.e., redirect) is
  551. issued. */
  552. $request = new Auth_OpenID_CheckIDRequest(
  553. 'http://bombom.unittest/',
  554. 'http://burr.unittest/999',
  555. 'http://burr.unittest/',
  556. false,
  557. $this->server->op_endpoint);
  558. $response = new Auth_OpenID_ServerResponse($request);
  559. $response->fields = Auth_OpenID_Message::fromOpenIDArgs(array(
  560. 'ns' => Auth_OpenID_OPENID2_NS,
  561. 'mode' => 'id_res',
  562. 'identity' => $request->identity,
  563. 'claimed_id' => $request->identity,
  564. 'return_to' => $request->return_to));
  565. $this->assertFalse($response->renderAsForm());
  566. $this->assertTrue($response->whichEncoding() == Auth_OpenID_ENCODE_URL);
  567. $webresponse = $this->encode($response);
  568. $this->assertTrue(array_key_exists('location', $webresponse->headers));
  569. }
  570. function test_id_res_OpenID2_POST()
  571. {
  572. /* Check that when an OpenID 2 response exceeds the OpenID 1
  573. message size, a POST response (i.e., an HTML form) is
  574. returned. */
  575. $request = new Auth_OpenID_CheckIDRequest(
  576. 'http://bombom.unittest/',
  577. 'http://burr.unittest/999',
  578. 'http://burr.unittest/',
  579. false,
  580. $this->server->op_endpoint);
  581. $response = new Auth_OpenID_ServerResponse($request);
  582. $response->fields = Auth_OpenID_Message::fromOpenIDArgs(array(
  583. 'ns' => Auth_OpenID_OPENID2_NS,
  584. 'mode' => 'id_res',
  585. 'identity' => $request->identity,
  586. 'claimed_id' => $request->identity,
  587. 'return_to' => str_repeat('x', Auth_OpenID_OPENID1_URL_LIMIT)));
  588. $this->assertTrue($response->renderAsForm());
  589. $this->assertTrue(strlen($response->encodeToURL()) > Auth_OpenID_OPENID1_URL_LIMIT);
  590. $this->assertTrue($response->whichEncoding() == Auth_OpenID_ENCODE_HTML_FORM);
  591. $webresponse = $this->encode($response);
  592. $this->assertEquals($webresponse->body, $response->toFormMarkup());
  593. }
  594. function test_id_res_OpenID1_exceeds_limit()
  595. {
  596. /* Check that when an OpenID 1 response exceeds the OpenID 1
  597. message size, a GET response is issued. Technically, this
  598. shouldn't be permitted by the library, but this test is in
  599. place to preserve the status quo for OpenID 1. */
  600. $request = new Auth_OpenID_CheckIDRequest(
  601. 'http://bombom.unittest/',
  602. 'http://burr.unittest/999',
  603. 'http://burr.unittest/',
  604. false,
  605. $this->server->op_endpoint);
  606. $response = new Auth_OpenID_ServerResponse($request);
  607. $response->fields = Auth_OpenID_Message::fromOpenIDArgs(array(
  608. 'mode' => 'id_res',
  609. 'identity' => $request->identity,
  610. 'return_to' => str_repeat('x', Auth_OpenID_OPENID1_URL_LIMIT)));
  611. $this->assertFalse($response->renderAsForm());
  612. $this->assertTrue(strlen($response->encodeToURL()) > Auth_OpenID_OPENID1_URL_LIMIT);
  613. $this->assertTrue($response->whichEncoding() == Auth_OpenID_ENCODE_URL);
  614. $webresponse = $this->encode($response);
  615. $this->assertEquals($webresponse->headers['location'], $response->encodeToURL());
  616. }
  617. function test_id_res()
  618. {
  619. $request = new Auth_OpenID_CheckIDRequest(
  620. 'http://bombom.unittest/',
  621. 'http://burr.unittest/',
  622. 'http://burr.unittest/999',
  623. false,
  624. $this->server);
  625. $response = new Auth_OpenID_ServerResponse($request);
  626. $response->fields = Auth_OpenID_Message::fromOpenIDArgs(
  627. array(
  628. 'mode' => 'id_res',
  629. 'identity' => $request->identity,
  630. 'return_to' => $request->return_to));
  631. $webresponse = $this->encoder->encode($response);
  632. $this->assertEquals($webresponse->code, AUTH_OPENID_HTTP_REDIRECT);
  633. $this->assertTrue(array_key_exists('location',
  634. $webresponse->headers));
  635. $location = $webresponse->headers['location'];
  636. $this->assertTrue(strpos($location, $request->return_to) === 0);
  637. // "%s does not start with %s" % ($location,
  638. // $request->return_to));
  639. $parsed = parse_url($location);
  640. $query = array();
  641. $query = Auth_OpenID::parse_str($parsed['query']);
  642. $expected = $response->fields->toPostArgs();
  643. $this->assertEquals($query, $expected);
  644. }
  645. function test_cancel()
  646. {
  647. $request = new Auth_OpenID_CheckIDRequest(
  648. 'http://bombom.unittest/',
  649. 'http://burr.unittest/',
  650. 'http://burr.unittest/999',
  651. false, null,
  652. $this->server);
  653. $response = new Auth_OpenID_ServerResponse($request);
  654. $response->fields = Auth_OpenID_Message::fromOpenIDArgs(array('mode' => 'cancel'));
  655. $webresponse = $this->encoder->encode($response);
  656. $this->assertEquals($webresponse->code, AUTH_OPENID_HTTP_REDIRECT);
  657. $this->assertTrue(array_key_exists('location', $webresponse->headers));
  658. }
  659. function test_cancelToForm()
  660. {
  661. $request = new Auth_OpenID_CheckIDRequest(
  662. 'http://bombom.unittest/',
  663. 'http://burr.unittest/999',
  664. 'http://burr.unittest/',
  665. false, null,
  666. $this->server);
  667. $response = new Auth_OpenID_ServerResponse($request);
  668. $response->fields = Auth_OpenID_Message::fromOpenIDArgs(array('mode' => 'cancel'));
  669. $form = $response->toFormMarkup();
  670. $pos = strpos($form, 'http://burr.unittest/999');
  671. $this->assertTrue($pos !== false, var_export($pos, true));
  672. }
  673. function test_assocReply()
  674. {
  675. if (!defined('Auth_OpenID_NO_MATH_SUPPORT')) {
  676. $message = new Auth_OpenID_Message(Auth_OpenID_OPENID2_NS);
  677. $message->setArg(Auth_OpenID_OPENID2_NS, 'session_type',
  678. 'no-encryption');
  679. $request = Auth_OpenID_AssociateRequest::fromMessage($message,
  680. $this->server);
  681. $response = new Auth_OpenID_ServerResponse($request);
  682. $response->fields = Auth_OpenID_Message::fromOpenIDArgs(
  683. array('assoc_handle' => "every-zig"));
  684. $webresponse = $this->encoder->encode($response);
  685. $body = "assoc_handle:every-zig\n";
  686. $this->assertEquals($webresponse->code, AUTH_OPENID_HTTP_OK);
  687. $this->assertEquals($webresponse->headers, array());
  688. $this->assertEquals($webresponse->body, $body);
  689. }
  690. }
  691. function test_checkauthReply()
  692. {
  693. $request = new Auth_OpenID_CheckAuthRequest('a_sock_monkey',
  694. 'siggggg',
  695. array());
  696. $response = new Auth_OpenID_ServerResponse($request);
  697. $response->fields = Auth_OpenID_Message::fromOpenIDArgs(array(
  698. 'is_valid' => 'true',
  699. 'invalidate_handle' => 'xXxX:xXXx'));
  700. $body = "invalidate_handle:xXxX:xXXx\nis_valid:true\n";
  701. $webresponse = $this->encoder->encode($response);
  702. $this->assertEquals($webresponse->code, AUTH_OPENID_HTTP_OK);
  703. $this->assertEquals($webresponse->headers, array());
  704. $this->assertEquals($webresponse->body, $body);
  705. }
  706. function test_unencodableError()
  707. {
  708. $args = array('openid.identity' => 'http://limu.unittest/');
  709. $e = new Auth_OpenID_ServerError(Auth_OpenID_Message::fromPostArgs($args),
  710. "wet paint");
  711. $result = $this->encoder->encode($e);
  712. if (!Auth_OpenID_isError($result, 'Auth_OpenID_EncodingError')) {
  713. $this->fail(sprintf("Expected Auth_OpenID_ServerError, got %s",
  714. gettype($result)));
  715. }
  716. }
  717. function test_encodableError()
  718. {
  719. $args = array(
  720. 'openid.mode' => 'associate',
  721. 'openid.identity' => 'http://limu.unittest/');
  722. $body="error:snoot\nmode:error\n";
  723. $err = new Auth_OpenID_ServerError(Auth_OpenID_Message::fromPostArgs($args),
  724. "snoot");
  725. $webresponse = $this->encoder->encode($err);
  726. $this->assertEquals($webresponse->code, AUTH_OPENID_HTTP_ERROR);
  727. $this->assertEquals($webresponse->headers, array());
  728. $this->assertEquals($webresponse->body, $body);
  729. }
  730. }
  731. class Tests_Auth_OpenID_SigningEncode extends PHPUnit_TestCase {
  732. function setUp()
  733. {
  734. // Use filestore here instead of memstore
  735. $this->store = new Tests_Auth_OpenID_MemStore();
  736. $this->op_endpoint = 'http://endpoint.unittest/encode';
  737. $this->server = new Auth_OpenID_Server($this->store,
  738. $this->op_endpoint);
  739. $this->request = new Auth_OpenID_CheckIDRequest(
  740. 'http://bombom.unittest/',
  741. 'http://burr.unittest/',
  742. 'http://burr.unittest/999',
  743. false,
  744. null,
  745. $this->server);
  746. $this->response = new Auth_OpenID_ServerResponse($this->request);
  747. $this->response->fields = Auth_OpenID_Message::fromOpenIDArgs(array(
  748. 'mode' => 'id_res',
  749. 'identity' => $this->request->identity,
  750. 'return_to' => $this->request->return_to));
  751. $this->signatory = new Auth_OpenID_Signatory($this->store);
  752. $this->dumb_key = $this->signatory->dumb_key;
  753. $this->normal_key = $this->signatory->normal_key;
  754. $this->encoder = new Auth_OpenID_SigningEncoder($this->signatory);
  755. }
  756. function test_idres()
  757. {
  758. $assoc_handle = '{bicycle}{shed}';
  759. $assoc = Auth_OpenID_Association::fromExpiresIn(60, $assoc_handle,
  760. 'sekrit', 'HMAC-SHA1');
  761. $this->store->storeAssociation($this->normal_key, $assoc);
  762. $this->request->assoc_handle = $assoc_handle;
  763. $webresponse = $this->encoder->encode($this->response);
  764. $this->assertEquals($webresponse->code, AUTH_OPENID_HTTP_REDIRECT);
  765. $this->assertTrue(array_key_exists('location',
  766. $webresponse->headers));
  767. $location = $webresponse->headers['location'];
  768. $parsed = parse_url($location);
  769. $query = Auth_OpenID::getQuery($parsed['query']);
  770. $this->assertTrue(array_key_exists('openid.sig', $query));
  771. $this->assertTrue(array_key_exists('openid.assoc_handle', $query));
  772. $this->assertTrue(array_key_exists('openid.signed', $query));
  773. }
  774. function test_idresDumb()
  775. {
  776. $webresponse = $this->encoder->encode($this->response);
  777. $this->assertEquals($webresponse->code, AUTH_OPENID_HTTP_REDIRECT);
  778. $this->assertTrue(array_key_exists('location', $webresponse->headers));
  779. $location = $webresponse->headers['location'];
  780. $parsed = parse_url($location);
  781. $query = Auth_OpenID::getQuery($parsed['query']);
  782. $this->assertTrue(array_key_exists('openid.sig', $query));
  783. $this->assertTrue(array_key_exists('openid.assoc_handle', $query));
  784. $this->assertTrue(array_key_exists('openid.signed', $query));
  785. }
  786. function test_forgotStore()
  787. {
  788. $this->encoder->signatory = null;
  789. $result = $this->encoder->encode($this->response);
  790. if (!is_a($result, 'Auth_OpenID_ServerError')) {
  791. $this->fail(sprintf("Expected Auth_OpenID_ServerError, got %s",
  792. gettype($result)));
  793. }
  794. }
  795. function test_cancel()
  796. {
  797. $request = new Auth_OpenID_CheckIDRequest(
  798. 'http://bombom.unittest/',
  799. 'http://burr.unittest/',
  800. 'http://burr.unittest/999',
  801. false,
  802. null,
  803. $this->server);
  804. $response = new Auth_OpenID_ServerResponse($request, 'cancel');
  805. $webresponse = $this->encoder->encode($response);
  806. $this->assertEquals($webresponse->code, AUTH_OPENID_HTTP_REDIRECT);
  807. $this->assertTrue(array_key_exists('location', $webresponse->headers));
  808. $location = $webresponse->headers['location'];
  809. $parsed = parse_url($location);
  810. $query = Auth_OpenID::getQuery($parsed['query']);
  811. $this->assertFalse(array_key_exists('openid.sig', $query));
  812. }
  813. function test_assocReply()
  814. {
  815. if (!defined('Auth_OpenID_NO_MATH_SUPPORT')) {
  816. $message = new Auth_OpenID_Message(Auth_OpenID_OPENID1_NS);
  817. $request = Auth_OpenID_AssociateRequest::fromMessage($message,
  818. $this->server);
  819. $response = new Auth_OpenID_ServerResponse($request);
  820. $response->fields = Auth_OpenID_Message::fromOpenIDArgs(
  821. array('assoc_handle' => "every-zig"));
  822. $webresponse = $this->encoder->encode($response);
  823. $body = "assoc_handle:every-zig\n";
  824. $this->assertEquals($webresponse->code, AUTH_OPENID_HTTP_OK);
  825. $this->assertEquals($webresponse->headers, array());
  826. $this->assertEquals($webresponse->body, $body);
  827. }
  828. }
  829. function test_alreadySigned()
  830. {
  831. $this->response->fields->setArg(Auth_OpenID_OPENID_NS, 'sig', 'priorSig==');
  832. $result = $this->encoder->encode($this->response);
  833. if (!is_a($result, 'Auth_OpenID_AlreadySigned')) {
  834. $this->fail(sprintf("Expected Auth_OpenID_AlreadySigned " .
  835. "instance, got %s", gettype($result)));
  836. }
  837. }
  838. }
  839. class Tests_Auth_OpenID_CheckID extends PHPUnit_TestCase {
  840. function setUp()
  841. {
  842. $this->store = new Tests_Auth_OpenID_MemStore();
  843. $this->op_endpoint = 'http://endpoint.unittest/encode';
  844. $this->server = new Auth_OpenID_Server($this->store,
  845. $this->op_endpoint);
  846. $this->request = new Auth_OpenID_CheckIDRequest(
  847. 'http://bambam.unittest/',
  848. 'http://bar.unittest/999',
  849. 'http://bar.unittest/',
  850. false, null,
  851. $this->server);
  852. $this->request->message = new Auth_OpenID_Message(
  853. Auth_OpenID_OPENID2_NS);
  854. }
  855. function test_fromMessageClaimedIDWithoutIdentityOpenID2()
  856. {
  857. $name = 'https://example.myopenid.com';
  858. $msg = new Auth_OpenID_Message(Auth_OpenID_OPENID2_NS);
  859. $msg->setArg(Auth_OpenID_OPENID_NS, 'mode', 'checkid_setup');
  860. $msg->setArg(Auth_OpenID_OPENID_NS, 'return_to',
  861. 'http://invalid:8000/rt');
  862. $msg->setArg(Auth_OpenID_OPENID_NS, 'claimed_id', $name);
  863. $result = Auth_OpenID_CheckIDRequest::fromMessage(
  864. $msg, $this->server);
  865. $this->assertTrue(is_a($result, 'Auth_OpenID_ServerError'));
  866. }
  867. function test_fromMessageIdentityWithoutClaimedIDOpenID2()
  868. {
  869. $name = 'https://example.myopenid.com';
  870. $msg = new Auth_OpenID_Message(Auth_OpenID_OPENID2_NS);
  871. $msg->setArg(Auth_OpenID_OPENID_NS, 'mode', 'checkid_setup');
  872. $msg->setArg(Auth_OpenID_OPENID_NS, 'return_to',
  873. 'http://invalid:8000/rt');
  874. $msg->setArg(Auth_OpenID_OPENID_NS, 'identity', $name);
  875. $result = Auth_OpenID_CheckIDRequest::fromMessage(
  876. $msg, $this->server);
  877. $this->assertTrue(is_a($result, 'Auth_OpenID_ServerError'));
  878. }
  879. function test_fromMessageWithEmptyTrustRoot()
  880. {
  881. $return_to = 'http://does.not.matter/';
  882. $msg = Auth_OpenID_Message::fromPostArgs(array(
  883. 'openid.assoc_handle' => '{blah}{blah}{OZivdQ==}',
  884. 'openid.claimed_id' => 'http://delegated.invalid/',
  885. 'openid.identity' => 'http://op-local.example.com/',
  886. 'openid.mode' => 'checkid_setup',
  887. 'openid.ns' => 'http://openid.net/signon/1.0',
  888. 'openid.return_to' => $return_to,
  889. 'openid.trust_root' => ''
  890. ));
  891. $result = Auth_OpenID_CheckIDRequest::fromMessage(
  892. $msg, $this->server);
  893. $this->assertEquals($return_to, $result->trust_root);
  894. }
  895. function test_trustRootInvalid()
  896. {
  897. $this->request->trust_root = "http://foo.unittest/17";
  898. $this->request->return_to = "http://foo.unittest/39";
  899. $this->assertFalse($this->request->trustRootValid());
  900. }
  901. function test_trustRootValid()
  902. {
  903. $this->request->trust_root = "http://foo.unittest/";
  904. $this->request->return_to = "http://foo.unittest/39";
  905. $this->assertTrue($this->request->trustRootValid());
  906. }
  907. function test_malformedTrustRoot()
  908. {
  909. $this->request->trust_root = "invalid://trust*root/";
  910. $this->request->return_to = "http://foo.unittest/39";
  911. $sentinel = 'Sentinel';
  912. $this->request->message = $sentinel;
  913. $result = $this->request->trustRootValid();
  914. $this->assertTrue(Auth_OpenID_isError($result));
  915. $this->assertEquals($result->message, $sentinel);
  916. }
  917. function _verify($trust_root, $return_to, $value)
  918. {
  919. $this->assertEquals($this->request->trust_root, $trust_root);
  920. $this->assertEquals($this->request->return_to, $return_to);
  921. return $value;
  922. }
  923. function _verifyTrue($trust_root, $return_to)
  924. {
  925. return $this->_verify($trust_root, $return_to, true);
  926. }
  927. function _verifyFalse($trust_root, $return_to)
  928. {
  929. return $this->_verify($trust_root, $return_to, false);
  930. }
  931. /*
  932. * Make sure that verifyReturnTo is calling
  933. * Auth_OpenID_verifyReturnTo
  934. */
  935. function test_returnToVerified_callsVerify()
  936. {
  937. // Ensure that True and False are passed through unchanged
  938. $this->request->verifyReturnTo = array(&$this, '_verifyTrue');
  939. $this->assertEquals(true, $this->request->returnToVerified());
  940. $this->request->verifyReturnTo = array(&$this, '_verifyFalse');
  941. $this->assertEquals(false, $this->request->returnToVerified());
  942. }
  943. function test_answerToInvalidRoot()
  944. {
  945. $this->request->trust_root = "http://foo.unittest/17";
  946. $this->request->return_to = "http://foo.unittest/39";
  947. $result = $this->request->answer(true);
  948. if (!is_a($result, 'Auth_OpenID_UntrustedReturnURL')) {
  949. $this->fail(sprintf("Expected Auth_OpenID_UntrustedReturnURL, " .
  950. "got %s", gettype($result)));
  951. }
  952. $this->assertTrue($this->request->answer(false));
  953. }
  954. function _expectAnswer($answer, $identity=null, $claimed_id=null)
  955. {
  956. if (is_a($answer, 'Auth_OpenID_ServerError')) {
  957. $this->fail("Got ServerError, expected valid response in ".$this->getName());
  958. return;
  959. }
  960. $expected_list = array(
  961. array('mode', 'id_res'),
  962. array('return_to', $this->request->return_to),
  963. array('op_endpoint', $this->op_endpoint));
  964. if ($identity) {
  965. $expected_list[] = array('identity', $identity);
  966. if ($claimed_id) {
  967. $expected_list[] = array('claimed_id', $claimed_id);
  968. } else {
  969. $expected_list[] = array('claimed_id', $identity);
  970. }
  971. }
  972. foreach ($expected_list as $pair) {
  973. list($k, $expected) = $pair;
  974. $actual = $answer->fields->getArg(Auth_OpenID_OPENID_NS, $k);
  975. $this->assertEquals($expected, $actual,
  976. "Got wrong value for field '".$k."'");
  977. }
  978. $this->assertTrue($answer->fields->hasKey(Auth_OpenID_OPENID_NS, 'response_nonce'));
  979. $this->assertTrue($answer->fields->getOpenIDNamespace() == Auth_OpenID_OPENID2_NS);
  980. # One for nonce, one for ns
  981. $this->assertEquals(count($answer->fields->toPostArgs()),
  982. count($expected_list) + 2);
  983. }
  984. function test_answerAllow()
  985. {
  986. $answer = $this->request->answer(true);
  987. if (Auth_OpenID_isError($answer)) {
  988. $this->fail($answer->toString());
  989. return;
  990. }
  991. $this->assertEquals($answer->request, $this->request);
  992. $this->_expectAnswer($answer, $this->request->identity);
  993. }
  994. function test_answerAllowDelegatedIdentity()
  995. {
  996. $this->request->claimed_id = 'http://delegating.unittest/';
  997. $answer = $this->request->answer(true);
  998. $this->_expectAnswer($answer, $this->request->identity,
  999. $this->request->claimed_id);
  1000. }
  1001. function test_answerAllowWithoutIdentityReally()
  1002. {
  1003. $this->request->identity = null;
  1004. $answer = $this->request->answer(true);
  1005. $this->assertEquals($answer->request, $this->request);
  1006. $this->_expectAnswer($answer);
  1007. }
  1008. function test_answerAllowAnonymousFail()
  1009. {
  1010. $this->request->identity = null;
  1011. // XXX - Check on this, I think this behavior is legal in
  1012. // OpenID 2.0?
  1013. // $this->failUnlessRaises(
  1014. // ValueError, $this->request->answer, true, identity="=V");
  1015. $this->assertTrue(is_a($this->request->answer(true, null, "=V"),
  1016. 'Auth_OpenID_ServerError'));
  1017. }
  1018. function test_answerAllowWithIdentity()
  1019. {
  1020. $this->request->identity = Auth_OpenID_IDENTIFIER_SELECT;
  1021. $selected_id = 'http://anon.unittest/9861';
  1022. $answer = $this->request->answer(true, null, $selected_id);
  1023. $this->_expectAnswer($answer, $selected_id);
  1024. }
  1025. function test_fromMessageWithoutTrustRoot()
  1026. {
  1027. $msg = new Auth_OpenID_Message(Auth_OpenID_OPENID2_NS);;
  1028. $msg->setArg(Auth_OpenID_OPENID_NS, 'mode', 'checkid_setup');
  1029. $msg->setArg(Auth_OpenID_OPENID_NS, 'return_to',
  1030. 'http://real_trust_root/foo');
  1031. $msg->setArg(Auth_OpenID_OPENID_NS, 'assoc_handle', 'bogus');
  1032. $msg->setArg(Auth_OpenID_OPENID_NS, 'identity', 'george');
  1033. $msg->setArg(Auth_OpenID_OPENID_NS, 'claimed_id', 'george');
  1034. $result = Auth_OpenID_CheckIDRequest::fromMessage(
  1035. $msg, $this->server->op_endpoint);
  1036. $this->assertEquals($result->trust_root,
  1037. 'http://real_trust_root/foo');
  1038. }
  1039. function test_fromMessageWithoutTrustRootOrReturnTo()
  1040. {
  1041. $msg = new Auth_OpenID_Message(Auth_OpenID_OPENID2_NS);
  1042. $msg->setArg(Auth_OpenID_OPENID_NS, 'mode', 'checkid_setup');
  1043. $msg->setArg(Auth_OpenID_OPENID_NS, 'assoc_handle', 'bogus');
  1044. $msg->setArg(Auth_OpenID_OPENID_NS, 'identity', 'george');
  1045. $msg->setArg(Auth_OpenID_OPENID_NS, 'claimed_id', 'george');
  1046. $result = Auth_OpenID_CheckIDRequest::fromMessage(
  1047. $msg, $this->server);
  1048. $this->assertTrue(is_a($result, 'Auth_OpenID_ServerError'));
  1049. }
  1050. function test_answerAllowNoEndpointOpenID1()
  1051. {
  1052. $identity = 'http://bambam.unittest/';
  1053. $reqmessage = Auth_OpenID_Message::fromOpenIDArgs(array(
  1054. 'identity' => $identity,
  1055. 'trust_root' => 'http://bar.unittest/',
  1056. 'return_to' => 'http://bar.unittest/999',
  1057. ));
  1058. $this->server->op_endpoint = null;
  1059. $this->request = Auth_OpenID_CheckIDRequest::fromMessage($reqmessage, $this->server);
  1060. $answer = $this->request->answer(true);
  1061. $expected_list = array('mode' => 'id_res',
  1062. 'return_to' => $this->request->return_to,
  1063. 'identity' => $identity,
  1064. );
  1065. foreach ($expected_list as $k => $expected) {
  1066. $actual = $answer->fields->getArg(Auth_OpenID_OPENID_NS, $k);
  1067. $this->assertEquals($expected, $actual);
  1068. }
  1069. $this->assertTrue($answer->fields->hasKey(Auth_OpenID_OPENID_NS,
  1070. 'response_nonce'));
  1071. $this->assertTrue($answer->fields->getOpenIDNamespace(),
  1072. Auth_OpenID_OPENID1_NS);
  1073. $this->assertTrue(
  1074. $answer->fields->namespaces->isImplicit(Auth_OpenID_OPENID1_NS));
  1075. // One for nonce (OpenID v1 namespace is implicit)
  1076. $this->assertEquals(count($answer->fields->toPostArgs()),
  1077. count($expected_list) + 1,
  1078. var_export($answer->fields->toPostArgs(), true));
  1079. }
  1080. function test_answerAllowWithDelegatedIdentityOpenID2()
  1081. {
  1082. // Answer an IDENTIFIER_SELECT case with a delegated
  1083. // identifier. claimed_id delegates to selected_id here.
  1084. $this->request->identity = Auth_OpenID_IDENTIFIER_SELECT;
  1085. $selected_id = 'http://anon.unittest/9861';
  1086. $claimed_id = 'http://monkeyhat.unittest/';
  1087. $answer = $this->request->answer(true, null, $selected_id,
  1088. $claimed_id);
  1089. $this->_expectAnswer($answer, $selected_id, $claimed_id);
  1090. }
  1091. function test_answerAllowWithDelegatedIdentityOpenID1()
  1092. {
  1093. // claimed_id parameter doesn't exist in OpenID 1.
  1094. $msg = new Auth_OpenID_Message(Auth_OpenID_OPENID1_NS);
  1095. $this->request->message = $msg;
  1096. // claimed_id delegates to selected_id here.
  1097. $this->request->identity = Auth_OpenID_IDENTIFIER_SELECT;
  1098. $selected_id = 'http://anon.unittest/9861';
  1099. $claimed_id = 'http://monkeyhat.unittest/';
  1100. $result = $this->request->answer(true,
  1101. null,
  1102. $selected_id,
  1103. $claimed_id);
  1104. $this->assertTrue(is_a($result, "Auth_OpenID_ServerError"),
  1105. var_export($result, true));
  1106. }
  1107. function test_answerAllowWithAnotherIdentity()
  1108. {
  1109. // XXX - Check on this, I think this behavior is legal is
  1110. // OpenID 2.0?
  1111. // $this->failUnlessRaises(ValueError, $this->request->answer, true,
  1112. // identity="http://pebbles.unittest/");
  1113. $result = $this->request->answer(true, null, "http://pebbles.unittest/");
  1114. $this->assertTrue(is_a($result, "Auth_OpenID_ServerError"));
  1115. }
  1116. function test_answerAllowNoIdentityOpenID1()
  1117. {
  1118. $msg = new Auth_OpenID_Message(Auth_OpenID_OPENID1_NS);
  1119. $this->request->message = $msg;
  1120. $this->request->identity = null;
  1121. // $this->failUnlessRaises(ValueError, $this->request->answer, true,
  1122. // identity=null);
  1123. $result = $this->request->answer(true);
  1124. $this->assertTrue(is_a($result, "Auth_OpenID_ServerError"));
  1125. }
  1126. function test_answerAllowForgotEndpoint()
  1127. {
  1128. $this->request->server->op_endpoint = null;
  1129. $result = $this->request->answer(true);
  1130. $this->assertTrue(is_a($result, "Auth_OpenID_ServerError"));
  1131. }
  1132. function test_checkIDWithNoIdentityOpenID1()
  1133. {
  1134. $msg = new Auth_OpenID_Message(Auth_OpenID_OPENID1_NS);
  1135. $msg->setArg(Auth_OpenID_OPENID_NS, 'return_to', 'bogus');
  1136. $msg->setArg(Auth_OpenID_OPENID_NS, 'trust_root', 'bogus');
  1137. $msg->setArg(Auth_OpenID_OPENID_NS, 'mode', 'checkid_setup');
  1138. $msg->setArg(Auth_OpenID_OPENID_NS, 'assoc_handle', 'bogus');
  1139. // $this->failUnlessRaises(server->ProtocolError,
  1140. // server->CheckIDRequest->fromMessage,
  1141. // msg, $this->server);
  1142. $result = Auth_OpenID_CheckIDRequest::fromMessage($msg, $this->server);
  1143. $this->assertTrue(is_a($result, 'Auth_OpenID_ServerError'));
  1144. }
  1145. function test_trustRootOpenID1()
  1146. {
  1147. // Ignore openid.realm in OpenID 1
  1148. $msg = new Auth_OpenID_Message(Auth_OpenID_OPENID1_NS);
  1149. $msg->setArg(Auth_OpenID_OPENID_NS, 'mode', 'checkid_setup');
  1150. $msg->setArg(Auth_OpenID_OPENID_NS, 'trust_root', 'http://real_trust_root/');
  1151. $msg->setArg(Auth_OpenID_OPENID_NS, 'realm', 'http://fake_trust_root/');
  1152. $msg->setArg(Auth_OpenID_OPENID_NS, 'return_to', 'http://real_trust_root/foo');
  1153. $msg->setArg(Auth_OpenID_OPENID_NS, 'assoc_handle', 'bogus');
  1154. $msg->setArg(Auth_OpenID_OPENID_NS, 'identity', 'george');
  1155. $result = Auth_OpenID_CheckIDRequest::fromMessage($msg, $this->server);
  1156. $this->assertTrue($result->trust_root == 'http://real_trust_root/');
  1157. }
  1158. function test_trustRootOpenID2()
  1159. {
  1160. // Ignore openid.trust_root in OpenID 2
  1161. $msg = new Auth_OpenID_Message(Auth_OpenID_OPENID2_NS);
  1162. $msg->setArg(Auth_OpenID_OPENID_NS, 'mode', 'checkid_setup');
  1163. $msg->setArg(Auth_OpenID_OPENID_NS, 'realm', 'http://real_trust_root/');
  1164. $msg->setArg(Auth_OpenID_OPENID_NS, 'trust_root', 'http://fake_trust_root/');
  1165. $msg->setArg(Auth_OpenID_OPENID_NS, 'return_to', 'http://real_trust_root/foo');
  1166. $msg->setArg(Auth_OpenID_OPENID_NS, 'assoc_handle', 'bogus');
  1167. $msg->setArg(Auth_OpenID_OPENID_NS, 'identity', 'george');
  1168. $msg->setArg(Auth_OpenID_OPENID_NS, 'claimed_id', 'george');
  1169. $result = Auth_OpenID_CheckIDRequest::fromMessage($msg, $this->server);
  1170. $this->assertTrue($result->trust_root == 'http://real_trust_root/');
  1171. }
  1172. function test_encodeToURL()
  1173. {
  1174. $server_url = 'http://openid-server.unittest/';
  1175. $result = $this->request->encodeToURL($server_url);
  1176. $this->assertFalse(is_a($result, 'Auth_OpenID_ServerError'));
  1177. // How to check? How about a round-trip test.
  1178. list($base, $result_args) = explode("?", $result, 2);
  1179. $args = Auth_OpenID::getQuery($result_args);
  1180. $message = Auth_OpenID_Message::fromPostArgs($args);
  1181. $rebuilt_request = Auth_OpenID_CheckIDRequest::fromMessage($message,
  1182. $this->server);
  1183. // argh, lousy hack
  1184. $this->assertTrue($rebuilt_request->equals($this->request));
  1185. }
  1186. function test_answerAllowNoTrustRoot()
  1187. {
  1188. $this->request->trust_root = null;
  1189. $answer = $this->request->answer(true);
  1190. $this->assertEquals($answer->request, $this->request);
  1191. $this->_expectAnswer($answer, $this->request->identity);
  1192. }
  1193. function test_answerImmediateDenyOpenID1()
  1194. {
  1195. $msg = new Auth_OpenID_Message(Auth_OpenID_OPENID1_NS);
  1196. $this->request->message = $msg;
  1197. $this->request->namespace = $msg->getOpenIDNamespace();
  1198. $this->request->mode = 'checkid_immediate';
  1199. $this->request->claimed_id = 'http://claimed-id.test/';
  1200. $this->request->immediate = true;
  1201. $server_url = "http://setup-url.unittest/";
  1202. $answer = $this->request->answer(false, $server_url);
  1203. $this->assertEquals($answer->request, $this->request);
  1204. $this->assertEquals(count($answer->fields->toPostArgs()), 2);
  1205. $this->assertEquals($answer->fields->getOpenIDNamespace(),
  1206. Auth_OpenID_OPENID1_NS);
  1207. $this->assertTrue(
  1208. $answer->fields->namespaces->isImplicit(Auth_OpenID_OPENID1_NS));
  1209. $this->assertEquals($answer->fields->getArg(Auth_OpenID_OPENID_NS, 'mode'),
  1210. 'id_res');
  1211. $usu = $answer->fields->getArg(Auth_OpenID_OPENID_NS,'user_setup_url');
  1212. $this->assertTrue(strpos($usu, $server_url) == 0);
  1213. $expected_substr = 'openid.claimed_id=http%3A%2F%2Fclaimed-id.test%2F';
  1214. $this->assertTrue(strpos($usu, $expected_substr), $usu);
  1215. }
  1216. function test_answerImmediateDenyOpenID2()
  1217. {
  1218. $this->request->mode = 'checkid_immediate';
  1219. $this->request->immediate = true;
  1220. $server_url = "http://setup-url.unittest/";
  1221. $answer = $this->request->answer(false, $server_url);
  1222. $this->assertEquals($answer->request, $this->request);
  1223. $this->assertEquals(count($answer->fields->toPostArgs()), 3);
  1224. $this->assertEquals($answer->fields->getOpenIDNamespace(),
  1225. Auth_OpenID_OPENID2_NS);
  1226. $this->assertEquals($answer->fields->getArg(Auth_OpenID_OPENID_NS, 'mode'),
  1227. 'setup_needed');
  1228. }
  1229. function test_answerSetupDeny()
  1230. {
  1231. $answer = $this->request->answer(false);
  1232. $this->assertEquals($answer->fields->getArgs(Auth_OpenID_OPENID_NS),
  1233. array('mode' => 'cancel'));
  1234. }
  1235. function test_getCancelURL()
  1236. {
  1237. $url = $this->request->getCancelURL();
  1238. $parsed = parse_url($url);
  1239. $query = Auth_OpenID::getQuery($parsed['query']);
  1240. $this->assertEquals(array('openid.mode' => 'cancel',
  1241. 'openid.ns' => Auth_OpenID_OPENID2_NS),
  1242. $query);
  1243. }
  1244. function test_getCancelURLimmed()
  1245. {
  1246. $this->request->mode = 'checkid_immediate';
  1247. $this->request->immediate = true;
  1248. $result = $this->request->getCancelURL();
  1249. if (!is_a($result, 'Auth_OpenID_ServerError')) {
  1250. $this->fail(sprintf("Expected Auth_OpenID_ServerError, got %s",
  1251. gettype($result)));
  1252. }
  1253. }
  1254. }
  1255. class Tests_Auth_OpenID_CheckIDExtension extends PHPUnit_TestCase {
  1256. function setUp()
  1257. {
  1258. $this->op_endpoint = 'http://endpoint.unittest/ext';
  1259. $this->store = new Tests_Auth_OpenID_MemStore();
  1260. $this->server = new Auth_OpenID_Server($this->store, $this->op_endpoint);
  1261. $this->request = new Auth_OpenID_CheckIDRequest(
  1262. 'http://bambam.unittest/',
  1263. 'http://bar.unittest/',
  1264. 'http://bar.unittest/999',
  1265. false,
  1266. null,
  1267. $this->server);
  1268. $this->response = new Auth_OpenID_ServerResponse($this->request);
  1269. $this->response->fields->setArg(Auth_OpenID_OPENID_NS, 'mode', 'id_res');
  1270. $this->response->fields->setArg(Auth_OpenID_OPENID_NS, 'blue', 'star');
  1271. }
  1272. function test_addField()
  1273. {
  1274. $namespace = 'something:';
  1275. $this->response->fields->setArg($namespace, 'bright', 'potato');
  1276. $this->assertEquals($this->response->fields->getArgs(Auth_OpenID_OPENID_NS),
  1277. array('blue' => 'star',
  1278. 'mode' => 'id_res'));
  1279. $this->assertEquals($this->response->fields->getArgs($namespace),
  1280. array('bright' => 'potato'));
  1281. }
  1282. function test_addFields()
  1283. {
  1284. $namespace = 'mi5:';
  1285. $args = array('tangy' => 'suspenders',
  1286. 'bravo' => 'inclusion');
  1287. $this->response->fields->updateArgs($namespace, $args);
  1288. $this->assertEquals($this->response->fields->getArgs(Auth_OpenID_OPENID_NS),
  1289. array('blue' => 'star',
  1290. 'mode' => 'id_res'));
  1291. $this->assertEquals($this->response->fields->getArgs($namespace), $args);
  1292. }
  1293. }
  1294. class _MockSignatory {
  1295. var $isValid = true;
  1296. function _MockSignatory($assoc)
  1297. {
  1298. $this->assocs = array($assoc);
  1299. }
  1300. function verify($assoc_handle, $message)
  1301. {
  1302. if (!$message->hasKey(Auth_OpenID_OPENID_NS, 'sig')) {
  1303. return false;
  1304. }
  1305. if (in_array(array(true, $assoc_handle), $this->assocs)) {
  1306. return $this->isValid;
  1307. } else {
  1308. return false;
  1309. }
  1310. }
  1311. function getAssociation($assoc_handle, $dumb)
  1312. {
  1313. if (in_array(array($dumb, $assoc_handle), $this->assocs)) {
  1314. // This isn't a valid implementation for many uses of this
  1315. // function, mind you.
  1316. return true;
  1317. } else {
  1318. return null;
  1319. }
  1320. }
  1321. function invalidate($assoc_handle, $dumb)
  1322. {
  1323. if (in_array(array($dumb, $assoc_handle), $this->assocs)) {
  1324. $i = 0;
  1325. foreach ($this->assocs as $pair) {
  1326. if ($pair == array($dumb, $assoc_handle)) {
  1327. unset($this->assocs[$i]);
  1328. break;
  1329. }
  1330. $i++;
  1331. }
  1332. }
  1333. }
  1334. }
  1335. class Tests_Auth_OpenID_CheckAuth extends PHPUnit_TestCase {
  1336. function setUp()
  1337. {
  1338. $this->assoc_handle = 'mooooooooo';
  1339. $this->message = Auth_OpenID_Message::fromPostArgs(
  1340. array('openid.sig' => 'signarture',
  1341. 'one' => 'alpha',
  1342. 'two' => 'beta'));
  1343. $this->request = new Auth_OpenID_CheckAuthRequest(
  1344. $this->assoc_handle, $this->message);
  1345. $this->signatory = new _MockSignatory(array(true, $this->assoc_handle));
  1346. }
  1347. function test_valid()
  1348. {
  1349. $this->request->namespace = Auth_OpenID_OPENID1_NS;
  1350. $r = $this->request->answer($this->signatory);
  1351. $this->assertEquals($r->fields->getArgs(Auth_OpenID_OPENID1_NS),
  1352. array('is_valid' => 'true'));
  1353. $this->assertEquals($r->request, $this->request);
  1354. }
  1355. function test_invalid()
  1356. {
  1357. $this->request->namespace = Auth_OpenID_OPENID1_NS;
  1358. $this->signatory->isValid = false;
  1359. $r = $this->request->answer($this->signatory);
  1360. $this->assertEquals($r->fields->getArgs(Auth_OpenID_OPENID1_NS),
  1361. array('is_valid' => 'false'));
  1362. }
  1363. function test_replay()
  1364. {
  1365. $this->request->namespace = Auth_OpenID_OPENID1_NS;
  1366. $r = $this->request->answer($this->signatory);
  1367. $r = $this->request->answer($this->signatory);
  1368. $this->assertEquals($r->fields->getArgs(Auth_OpenID_OPENID1_NS),
  1369. array('is_valid' => 'false'));
  1370. }
  1371. function test_invalidatehandle()
  1372. {
  1373. $this->request->namespace = Auth_OpenID_OPENID1_NS;
  1374. $this->request->invalidate_handle = "bogusHandle";
  1375. $r = $this->request->answer($this->signatory);
  1376. $this->assertEquals($r->fields->getArgs(Auth_OpenID_OPENID1_NS),
  1377. array('is_valid' => 'true',
  1378. 'invalidate_handle' => "bogusHandle"));
  1379. $this->assertEquals($r->request, $this->request);
  1380. }
  1381. function test_invalidatehandleNo()
  1382. {
  1383. $this->request->namespace = Auth_OpenID_OPENID1_NS;
  1384. $assoc_handle = 'goodhandle';
  1385. $this->signatory->assocs[] = array(false, 'goodhandle');
  1386. $this->request->invalidate_handle = $assoc_handle;
  1387. $r = $this->request->answer($this->signatory);
  1388. $this->assertEquals($r->fields->getArgs(Auth_OpenID_OPENID1_NS),
  1389. array('is_valid' => 'true'));
  1390. }
  1391. }
  1392. class Tests_Auth_OpenID_Associate extends PHPUnit_TestCase {
  1393. // TODO: test DH with non-default values for modulus and gen.
  1394. // (important to do because we actually had it broken for a
  1395. // while.)
  1396. function setUp()
  1397. {
  1398. $message = new Auth_OpenID_Message(Auth_OpenID_OPENID1_NS);
  1399. $this->request = Auth_OpenID_AssociateRequest::fromMessage($message);
  1400. $this->store = new Tests_Auth_OpenID_MemStore();
  1401. $this->signatory = new Auth_OpenID_Signatory($this->store);
  1402. }
  1403. function test_dhSHA1()
  1404. {
  1405. if (!defined('Auth_OpenID_NO_MATH_SUPPORT')) {
  1406. $this->assoc = $this->signatory->createAssociation(false,
  1407. 'HMAC-SHA1');
  1408. $dh = new Auth_OpenID_DiffieHellman();
  1409. $ml =& Auth_OpenID_getMathLib();
  1410. $cpub = $dh->public;
  1411. $session = new Auth_OpenID_DiffieHellmanSHA1ServerSession(
  1412. new Auth_OpenID_DiffieHellman(),
  1413. $cpub);
  1414. $this->request = new Auth_OpenID_AssociateRequest($session,
  1415. 'HMAC-SHA1');
  1416. $response = $this->request->answer($this->assoc);
  1417. $this->assertEquals(
  1418. $response->fields->getArg(Auth_OpenID_OPENID_NS, "assoc_type"),
  1419. "HMAC-SHA1");
  1420. $this->assertEquals(
  1421. $response->fields->getArg(Auth_OpenID_OPENID_NS, "assoc_handle"),
  1422. $this->assoc->handle);
  1423. $this->assertFalse(
  1424. $response->fields->getArg(Auth_OpenID_OPENID_NS, "mac_key"));
  1425. $this->assertEquals(
  1426. $response->fields->getArg(Auth_OpenID_OPENID_NS, "session_type"),
  1427. "DH-SHA1");
  1428. $this->assertTrue(
  1429. $response->fields->getArg(Auth_OpenID_OPENID_NS, "enc_mac_key"));
  1430. $this->assertTrue(
  1431. $response->fields->getArg(Auth_OpenID_OPENID_NS,
  1432. "dh_server_public"));
  1433. $enc_key = base64_decode(
  1434. $response->fields->getArg(Auth_OpenID_OPENID_NS, "enc_mac_key"));
  1435. $spub = $ml->base64ToLong(
  1436. $response->fields->getArg(Auth_OpenID_OPENID_NS,
  1437. "dh_server_public"));
  1438. $secret = $dh->xorSecret($spub, $enc_key, $session->hash_func);
  1439. $this->assertEquals($secret, $this->assoc->secret);
  1440. }
  1441. }
  1442. function test_dhSHA256()
  1443. {
  1444. if (defined('Auth_OpenID_NO_MATH_SUPPORT') ||
  1445. !Auth_OpenID_SHA256_SUPPORTED) {
  1446. print "(Skipping test_dhSHA256)";
  1447. return;
  1448. }
  1449. $this->assoc = $this->signatory->createAssociation(false,
  1450. 'HMAC-SHA256');
  1451. $consumer_dh = new Auth_OpenID_DiffieHellman();
  1452. $cpub = $consumer_dh->public;
  1453. $server_dh = new Auth_OpenID_DiffieHellman();
  1454. $session = new Auth_OpenID_DiffieHellmanSHA256ServerSession($server_dh, $cpub);
  1455. $this->request = new Auth_OpenID_AssociateRequest($session, 'HMAC-SHA256');
  1456. $response = $this->request->answer($this->assoc);
  1457. $this->assertFalse($response->fields->getArg(Auth_OpenID_OPENID_NS, "mac_key"));
  1458. $this->assertTrue($response->fields->getArg(Auth_OpenID_OPENID_NS, "enc_mac_key"));
  1459. $this->assertTrue($response->fields->getArg(Auth_OpenID_OPENID_NS, "dh_server_public"));
  1460. $fields = array(
  1461. 'assoc_type' => 'HMAC-SHA256',
  1462. 'assoc_handle' => $this->assoc->handle,
  1463. 'session_type' => 'DH-SHA256',
  1464. );
  1465. foreach ($fields as $k => $v) {
  1466. $this->assertEquals(
  1467. $response->fields->getArg(Auth_OpenID_OPENID_NS, $k), $v);
  1468. }
  1469. $enc_key = base64_decode(
  1470. $response->fields->getArg(Auth_OpenID_OPENID_NS, "enc_mac_key"));
  1471. $lib =& Auth_OpenID_getMathLib();
  1472. $spub = $lib->base64ToLong($response->fields->getArg(Auth_OpenID_OPENID_NS,
  1473. "dh_server_public"));
  1474. $secret = $consumer_dh->xorSecret($spub, $enc_key, 'Auth_OpenID_SHA256');
  1475. $s = base64_encode($secret);
  1476. $assoc_s = base64_encode($this->assoc->secret);
  1477. $this->assertEquals($s, $assoc_s);
  1478. }
  1479. function test_protoError256()
  1480. {
  1481. if (defined('Auth_OpenID_NO_MATH_SUPPORT') ||
  1482. !Auth_OpenID_HMACSHA256_SUPPORTED) {
  1483. print "(Skipping test_protoError256)";
  1484. return;
  1485. }
  1486. $s256_session = new Auth_OpenID_DiffieHellmanSHA256ConsumerSession();
  1487. $invalid_s256 = array('openid.assoc_type' => 'HMAC-SHA1',
  1488. 'openid.session_type' => 'DH-SHA256');
  1489. $invalid_s256 = array_merge($invalid_s256, $s256_session->getRequest());
  1490. $invalid_s256_2 = array('openid.assoc_type' => 'MONKEY-PIRATE',
  1491. 'openid.session_type' => 'DH-SHA256');
  1492. $invalid_s256_2 = array_merge($invalid_s256_2, $s256_session->getRequest());
  1493. $bad_request_argss = array(
  1494. $invalid_s256,
  1495. $invalid_s256_2);
  1496. foreach ($bad_request_argss as $request_args) {
  1497. $message = Auth_OpenID_Message::fromPostArgs($request_args);
  1498. $result = Auth_OpenID_Associaterequest::fromMessage($message);
  1499. $this->assertTrue(is_a($result, 'Auth_OpenID_ServerError'));
  1500. }
  1501. }
  1502. function test_plaintext()
  1503. {
  1504. $this->assoc = $this->signatory->createAssociation(false,
  1505. 'HMAC-SHA1');
  1506. $response = $this->request->answer($this->assoc);
  1507. $this->assertEquals(
  1508. $response->fields->getArg(Auth_OpenID_OPENID_NS, "assoc_type"),
  1509. "HMAC-SHA1");
  1510. $this->assertEquals(
  1511. $response->fields->getArg(Auth_OpenID_OPENID_NS, "assoc_handle"),
  1512. $this->assoc->handle);
  1513. $this->assertEquals(
  1514. $response->fields->getArg(Auth_OpenID_OPENID_NS, "expires_in"),
  1515. sprintf("%d", $this->signatory->SECRET_LIFETIME));
  1516. $this->assertEquals(
  1517. $response->fields->getArg(Auth_OpenID_OPENID_NS, "mac_key"),
  1518. base64_encode($this->assoc->secret));
  1519. $this->assertFalse($response->fields->getArg(Auth_OpenID_OPENID_NS,
  1520. "session_type"));
  1521. $this->assertFalse($response->fields->getArg(Auth_OpenID_OPENID_NS,
  1522. "enc_mac_key"));
  1523. $this->assertFalse($response->fields->getArg(Auth_OpenID_OPENID_NS,
  1524. "dh_server_public"));
  1525. }
  1526. function test_plaintextV2()
  1527. {
  1528. // The main difference between this and the v1 test is that
  1529. // the session_typ is always returned in v2.
  1530. $args = array('openid.mode' => 'associate',
  1531. 'openid.ns' => Auth_OpenID_OPENID2_NS,
  1532. 'openid.assoc_type' => 'HMAC-SHA1',
  1533. 'openid.session_type' => 'no-encryption');
  1534. $this->request = Auth_OpenID_AssociateRequest::fromMessage(
  1535. Auth_OpenID_Message::fromPostArgs($args));
  1536. $this->assertFalse($this->request->message->isOpenID1());
  1537. $this->assoc = $this->signatory->createAssociation(false,
  1538. 'HMAC-SHA1');
  1539. $response = $this->request->answer($this->assoc);
  1540. $this->assertEquals(
  1541. $response->fields->getArg(Auth_OpenID_OPENID_NS, "assoc_type"),
  1542. "HMAC-SHA1");
  1543. $this->assertEquals(
  1544. $response->fields->getArg(Auth_OpenID_OPENID_NS, "assoc_handle"),
  1545. $this->assoc->handle);
  1546. $this->assertEquals(
  1547. $response->fields->getArg(Auth_OpenID_OPENID_NS, "expires_in"),
  1548. sprintf("%d", $this->signatory->SECRET_LIFETIME));
  1549. $this->assertEquals(
  1550. $response->fields->getArg(Auth_OpenID_OPENID_NS, "mac_key"),
  1551. base64_encode($this->assoc->secret));
  1552. $session_type = $response->fields->getArg(Auth_OpenID_OPENID_NS,
  1553. "session_type");
  1554. $this->assertEquals('no-encryption', $session_type);
  1555. $this->assertFalse($response->fields->getArg(Auth_OpenID_OPENID_NS,
  1556. "enc_mac_key"));
  1557. $this->assertFalse($response->fields->getArg(Auth_OpenID_OPENID_NS,
  1558. "dh_server_public"));
  1559. }
  1560. function test_protoError()
  1561. {
  1562. $s1_session = new Auth_OpenID_DiffieHellmanSHA1ConsumerSession();
  1563. $invalid_s1 = array('openid.assoc_type' => 'HMAC-SHA256',
  1564. 'openid.session_type' => 'DH-SHA1');
  1565. $invalid_s1 = array_merge($invalid_s1, $s1_session->getRequest());
  1566. $invalid_s1_2 = array('openid.assoc_type' => 'ROBOT-NINJA',
  1567. 'openid.session_type' => 'DH-SHA1');
  1568. $invalid_s1_2 = array_merge($invalid_s1_2, $s1_session->getRequest());
  1569. $bad_request_argss = array(array('openid.assoc_type' => 'Wha?'),
  1570. $invalid_s1,
  1571. $invalid_s1_2);
  1572. foreach ($bad_request_argss as $request_args) {
  1573. $message = Auth_OpenID_Message::fromPostArgs($request_args);
  1574. $result = Auth_OpenID_AssociateRequest::fromMessage($message);
  1575. $this->assertTrue(is_a($result, 'Auth_OpenID_ServerError'));
  1576. }
  1577. }
  1578. function test_protoErrorFields()
  1579. {
  1580. $contact = 'user@example.invalid';
  1581. $reference = 'Trac ticket number MAX_INT';
  1582. $error = 'poltergeist';
  1583. $openid1_args = array(
  1584. 'openid.identitiy' => 'invalid',
  1585. 'openid.mode' => 'checkid_setup');
  1586. $openid2_args = $openid1_args;
  1587. $openid2_args = array_merge($openid2_args,
  1588. array('openid.ns' => Auth_OpenID_OPENID2_NS));
  1589. // Check presence of optional fields in both protocol versions
  1590. $openid1_msg = Auth_OpenID_Message::fromPostArgs($openid1_args);
  1591. $p = new Auth_OpenID_ServerError($openid1_msg, $error,
  1592. $reference, $contact);
  1593. $reply = $p->toMessage();
  1594. $this->assertEquals($reply->getArg(Auth_OpenID_OPENID_NS, 'reference'),
  1595. $reference);
  1596. $this->assertEquals($reply->getArg(Auth_OpenID_OPENID_NS, 'contact'),
  1597. $contact);
  1598. $openid2_msg = Auth_OpenID_Message::fromPostArgs($openid2_args);
  1599. $p = new Auth_OpenID_ServerError($openid2_msg, $error,
  1600. $reference, $contact);
  1601. $reply = $p->toMessage();
  1602. $this->assertEquals($reply->getArg(Auth_OpenID_OPENID_NS, 'reference'),
  1603. $reference);
  1604. $this->assertEquals($reply->getArg(Auth_OpenID_OPENID_NS, 'contact'),
  1605. $contact);
  1606. }
  1607. function failUnlessExpiresInMatches($msg, $expected_expires_in)
  1608. {
  1609. $expires_in_str = $msg->getArg(Auth_OpenID_OPENID_NS, 'expires_in');
  1610. if ($expires_in_str === null) {
  1611. $this->fail("Expected expires_in value.");
  1612. return;
  1613. }
  1614. $expires_in = intval($expires_in_str);
  1615. // Slop is necessary because the tests can sometimes get run
  1616. // right on a second boundary
  1617. $slop = 1; // second
  1618. $difference = $expected_expires_in - $expires_in;
  1619. $error_message = sprintf('"expires_in" value not within %s of expected: '.
  1620. 'expected=%s, actual=%s',
  1621. $slop, $expected_expires_in, $expires_in);
  1622. $this->assertTrue((0 <= $difference &&
  1623. $difference <= $slop), $error_message);
  1624. }
  1625. function test_plaintext256()
  1626. {
  1627. if (defined('Auth_OpenID_NO_MATH_SUPPORT') ||
  1628. !Auth_OpenID_SHA256_SUPPORTED) {
  1629. print "(Skipping test_plaintext256)";
  1630. return;
  1631. }
  1632. $this->assoc = $this->signatory->createAssociation(false,
  1633. 'HMAC-SHA256');
  1634. $response = $this->request->answer($this->assoc);
  1635. $f = $response->fields;
  1636. $this->assertEquals($f->getArg(Auth_OpenID_OPENID_NS, "assoc_type"),
  1637. "HMAC-SHA1");
  1638. $this->assertEquals($f->getArg(Auth_OpenID_OPENID_NS, "assoc_handle"),
  1639. $this->assoc->handle);
  1640. $this->failUnlessExpiresInMatches(
  1641. $f,
  1642. $this->signatory->SECRET_LIFETIME);
  1643. $this->assertEquals(
  1644. $f->getArg(Auth_OpenID_OPENID_NS, "mac_key"),
  1645. base64_encode($this->assoc->secret));
  1646. $this->assertFalse($f->hasKey(Auth_OpenID_OPENID_NS, "session_type"));
  1647. $this->assertFalse($f->hasKey(Auth_OpenID_OPENID_NS, "enc_mac_key"));
  1648. $this->assertFalse($f->hasKey(Auth_OpenID_OPENID_NS, "dh_server_public"));
  1649. }
  1650. function test_unsupportedPrefer()
  1651. {
  1652. $allowed_assoc = 'COLD-PET-RAT';
  1653. $allowed_sess = 'FROG-BONES';
  1654. $message = 'This is a unit test';
  1655. // Set an OpenID 2 message so answerUnsupported doesn't raise
  1656. // ProtocolError.
  1657. $this->request->message = new Auth_OpenID_Message(Auth_OpenID_OPENID2_NS);
  1658. $response = $this->request->answerUnsupported(
  1659. $message,
  1660. $allowed_assoc,
  1661. $allowed_sess);
  1662. $f = $response->fields;
  1663. $this->assertEquals($f->getArg(Auth_OpenID_OPENID_NS, 'error_code'),
  1664. 'unsupported-type');
  1665. $this->assertEquals($f->getArg(Auth_OpenID_OPENID_NS, 'assoc_type'),
  1666. $allowed_assoc);
  1667. $this->assertEquals($f->getArg(Auth_OpenID_OPENID_NS, 'error'),
  1668. $message);
  1669. $this->assertEquals($f->getArg(Auth_OpenID_OPENID_NS, 'session_type'),
  1670. $allowed_sess);
  1671. }
  1672. function test_unsupported()
  1673. {
  1674. $message = 'This is a unit test';
  1675. $this->request->message = new Auth_OpenID_Message(Auth_OpenID_OPENID2_NS);
  1676. $response = $this->request->answerUnsupported($message);
  1677. $f = $response->fields;
  1678. $this->assertEquals($f->getArg(Auth_OpenID_OPENID_NS, 'error_code'),
  1679. 'unsupported-type');
  1680. $this->assertEquals($f->getArg(Auth_OpenID_OPENID_NS, 'assoc_type'), null);
  1681. $this->assertEquals($f->getArg(Auth_OpenID_OPENID_NS, 'error'), $message);
  1682. $this->assertEquals($f->getArg(Auth_OpenID_OPENID_NS, 'session_type'), null);
  1683. }
  1684. }
  1685. class Counter {
  1686. function Counter()
  1687. {
  1688. $this->count = 0;
  1689. }
  1690. function inc()
  1691. {
  1692. $this->count += 1;
  1693. }
  1694. }
  1695. class Tests_Auth_OpenID_ServerTest extends PHPUnit_TestCase {
  1696. function setUp()
  1697. {
  1698. $this->store = new Tests_Auth_OpenID_MemStore();
  1699. $this->server = new Auth_OpenID_Server($this->store);
  1700. }
  1701. function test_associate()
  1702. {
  1703. if (!defined('Auth_OpenID_NO_MATH_SUPPORT')) {
  1704. $message = new Auth_OpenID_Message(Auth_OpenID_OPENID1_NS);
  1705. $request = Auth_OpenID_AssociateRequest::fromMessage($message);
  1706. $response = $this->server->openid_associate($request);
  1707. $this->assertTrue($response->fields->hasKey(Auth_OpenID_OPENID_NS,
  1708. 'assoc_handle'));
  1709. }
  1710. }
  1711. function test_associate2()
  1712. {
  1713. // Associate when the server has no allowed association types
  1714. //
  1715. // Gives back an error with error_code and no fallback session
  1716. // or assoc types.
  1717. $this->server->negotiator->setAllowedTypes(array());
  1718. $msg = Auth_OpenID_Message::fromPostArgs(array(
  1719. 'openid.ns' => Auth_OpenID_OPENID2_NS,
  1720. 'openid.session_type' => 'no-encryption'));
  1721. $request = Auth_OpenID_AssociateRequest::fromMessage($msg);
  1722. $response = $this->server->openid_associate($request);
  1723. $this->assertTrue($response->fields->hasKey(Auth_OpenID_OPENID_NS, "error"));
  1724. $this->assertTrue($response->fields->hasKey(Auth_OpenID_OPENID_NS, "error_code"));
  1725. $this->assertFalse($response->fields->hasKey(Auth_OpenID_OPENID_NS, "assoc_handle"));
  1726. $this->assertFalse($response->fields->hasKey(Auth_OpenID_OPENID_NS, "assoc_type"));
  1727. $this->assertFalse($response->fields->hasKey(Auth_OpenID_OPENID_NS, "session_type"));
  1728. }
  1729. function test_associate3()
  1730. {
  1731. if (defined('Auth_OpenID_NO_MATH_SUPPORT') ||
  1732. !Auth_OpenID_HMACSHA256_SUPPORTED) {
  1733. print "(Skipping test_associate3)";
  1734. return;
  1735. }
  1736. // Request an assoc type that is not supported when there are
  1737. // supported types.
  1738. //
  1739. // Should give back an error message with a fallback type.
  1740. $this->server->negotiator->setAllowedTypes(array(array('HMAC-SHA256', 'DH-SHA256')));
  1741. $msg = Auth_OpenID_Message::fromPostArgs(array(
  1742. 'openid.ns' => Auth_OpenID_OPENID2_NS,
  1743. 'openid.session_type' => 'no-encryption'));
  1744. $request = Auth_OpenID_AssociateRequest::fromMessage($msg);
  1745. $response = $this->server->openid_associate($request);
  1746. $this->assertTrue($response->fields->hasKey(Auth_OpenID_OPENID_NS, "error"));
  1747. $this->assertTrue($response->fields->hasKey(Auth_OpenID_OPENID_NS, "error_code"));
  1748. $this->assertFalse($response->fields->hasKey(Auth_OpenID_OPENID_NS, "assoc_handle"));
  1749. $this->assertEquals($response->fields->getArg(Auth_OpenID_OPENID_NS, "assoc_type"),
  1750. 'HMAC-SHA256');
  1751. $this->assertEquals($response->fields->getArg(Auth_OpenID_OPENID_NS, "session_type"),
  1752. 'DH-SHA256');
  1753. }
  1754. function test_associate4()
  1755. {
  1756. if (defined('Auth_OpenID_NO_MATH_SUPPORT') ||
  1757. !Auth_OpenID_HMACSHA256_SUPPORTED) {
  1758. print "(Skipping test_associate4)";
  1759. return;
  1760. }
  1761. $this->assertTrue($this->server->negotiator->setAllowedTypes(
  1762. array(array('HMAC-SHA256', 'DH-SHA256'))));
  1763. $query = array(
  1764. 'openid.dh_consumer_public' =>
  1765. 'ALZgnx8N5Lgd7pCj8K86T/DDMFjJXSss1SKoLmxE72kJTzOtG6I2PaYrHX'.
  1766. 'xku4jMQWSsGfLJxwCZ6280uYjUST/9NWmuAfcrBfmDHIBc3H8xh6RBnlXJ'.
  1767. '1WxJY3jHd5k1/ZReyRZOxZTKdF/dnIqwF8ZXUwI6peV0TyS/K1fOfF/s',
  1768. 'openid.assoc_type' => 'HMAC-SHA256',
  1769. 'openid.session_type' => 'DH-SHA256');
  1770. $message = Auth_OpenID_Message::fromPostArgs($query);
  1771. $request = Auth_OpenID_AssociateRequest::fromMessage($message);
  1772. $response = $this->server->openid_associate($request);
  1773. $this->assertTrue($response->fields->hasKey(Auth_OpenID_OPENID_NS, "assoc_handle"));
  1774. }
  1775. function test_missingSessionTypeOpenID2()
  1776. {
  1777. // Make sure session_type is required in OpenID 2
  1778. $msg = Auth_OpenID_Message::fromPostArgs(array('openid.ns' => Auth_OpenID_OPENID2_NS));
  1779. $result = Auth_OpenID_AssociateRequest::fromMessage($msg);
  1780. $this->assertTrue(is_a($result, 'Auth_OpenID_ServerError'));
  1781. }
  1782. function test_checkAuth()
  1783. {
  1784. $request = new Auth_OpenID_CheckAuthRequest('arrrrrf',
  1785. '0x3999', array());
  1786. $response = $this->server->openid_check_authentication($request);
  1787. $this->assertTrue($response->fields->hasKey(Auth_OpenID_OPENID_NS, 'is_valid'));
  1788. }
  1789. }
  1790. class Tests_Auth_OpenID_Signatory extends PHPUnit_TestCase {
  1791. function setUp()
  1792. {
  1793. $this->store =& new Tests_Auth_OpenID_MemStore();
  1794. $this->signatory =& new Auth_OpenID_Signatory($this->store);
  1795. $this->dumb_key = $this->signatory->dumb_key;
  1796. $this->normal_key = $this->signatory->normal_key;
  1797. }
  1798. function test_sign()
  1799. {
  1800. $request = new Auth_OpenID_ServerRequest();
  1801. $request->namespace = Auth_OpenID_OPENID1_NS;
  1802. $assoc_handle = '{assoc}{lookatme}';
  1803. $assoc = Auth_OpenID_Association::fromExpiresIn(60, $assoc_handle,
  1804. 'sekrit', 'HMAC-SHA1');
  1805. $this->store->storeAssociation($this->normal_key, $assoc);
  1806. $request->assoc_handle = $assoc_handle;
  1807. $request->namespace = Auth_OpenID_OPENID1_NS;
  1808. $response = new Auth_OpenID_ServerResponse($request);
  1809. $response->fields = Auth_OpenID_Message::fromOpenIDArgs(array(
  1810. 'foo' => 'amsigned',
  1811. 'bar' => 'notsigned',
  1812. 'azu' => 'alsosigned'));
  1813. $sresponse = $this->signatory->sign($response);
  1814. $this->assertEquals($sresponse->fields->getArg(Auth_OpenID_OPENID_NS,
  1815. 'assoc_handle'),
  1816. $assoc_handle);
  1817. $this->assertEquals($sresponse->fields->getArg(Auth_OpenID_OPENID_NS, 'signed'),
  1818. 'assoc_handle,azu,bar,foo,signed');
  1819. $this->assertTrue($sresponse->fields->hasKey(Auth_OpenID_OPENID_NS, 'sig'));
  1820. }
  1821. function test_signDumb()
  1822. {
  1823. $request = new Auth_OpenID_ServerRequest();
  1824. $request->assoc_handle = null;
  1825. $request->namespace = Auth_OpenID_OPENID1_NS;
  1826. $response = new Auth_OpenID_ServerResponse($request);
  1827. $response->fields = Auth_OpenID_Message::fromOpenIDArgs(array(
  1828. 'foo' => 'amsigned',
  1829. 'bar' => 'notsigned',
  1830. 'azu' => 'alsosigned'));
  1831. $sresponse = $this->signatory->sign($response);
  1832. $assoc_handle = $sresponse->fields->getArg(Auth_OpenID_OPENID_NS,
  1833. 'assoc_handle');
  1834. $this->assertTrue($assoc_handle);
  1835. $assoc = $this->signatory->getAssociation($assoc_handle, true);
  1836. $this->assertTrue($assoc);
  1837. $this->assertEquals($sresponse->fields->getArg(Auth_OpenID_OPENID_NS, 'signed'),
  1838. 'assoc_handle,azu,bar,foo,signed');
  1839. $this->assertTrue($sresponse->fields->hasKey(Auth_OpenID_OPENID_NS, 'sig'));
  1840. }
  1841. function test_signExpired()
  1842. {
  1843. $request = new Auth_OpenID_ServerRequest();
  1844. $assoc_handle = '{assoc}{lookatme}';
  1845. $assoc = Auth_OpenID_Association::fromExpiresIn(-10, $assoc_handle,
  1846. 'sekrit', 'HMAC-SHA1');
  1847. $this->store->storeAssociation($this->normal_key, $assoc);
  1848. $this->assertTrue($this->store->getAssociation($this->normal_key,
  1849. $assoc_handle));
  1850. $request->assoc_handle = $assoc_handle;
  1851. $request->namespace = Auth_OpenID_OPENID1_NS;
  1852. $response = new Auth_OpenID_ServerResponse($request);
  1853. $response->fields = Auth_OpenID_Message::fromOpenIDArgs(array(
  1854. 'foo' => 'amsigned',
  1855. 'bar' => 'notsigned',
  1856. 'azu' => 'alsosigned'));
  1857. $sresponse = $this->signatory->sign($response);
  1858. $new_assoc_handle = $sresponse->fields->getArg(Auth_OpenID_OPENID_NS,
  1859. 'assoc_handle');
  1860. $this->assertTrue($new_assoc_handle);
  1861. $this->assertFalse($new_assoc_handle == $assoc_handle);
  1862. $this->assertEquals($sresponse->fields->getArg(Auth_OpenID_OPENID_NS,
  1863. 'invalidate_handle'),
  1864. $assoc_handle);
  1865. $this->assertEquals($sresponse->fields->getArg(Auth_OpenID_OPENID_NS,
  1866. 'signed'),
  1867. 'assoc_handle,azu,bar,foo,invalidate_handle,signed');
  1868. $this->assertTrue($sresponse->fields->hasKey(Auth_OpenID_OPENID_NS,
  1869. 'sig'));
  1870. // make sure the expired association is gone
  1871. $this->assertFalse($this->store->getAssociation($this->normal_key,
  1872. $assoc_handle));
  1873. // make sure the new key is a dumb mode association
  1874. $this->assertTrue($this->store->getAssociation($this->dumb_key,
  1875. $new_assoc_handle));
  1876. $this->assertFalse($this->store->getAssociation($this->normal_key,
  1877. $new_assoc_handle));
  1878. }
  1879. function test_signInvalidHandle()
  1880. {
  1881. $request = new Auth_OpenID_ServerRequest();
  1882. $assoc_handle = '{bogus-assoc}{notvalid}';
  1883. $request->assoc_handle = $assoc_handle;
  1884. $request->namespace = Auth_OpenID_OPENID1_NS;
  1885. $response = new Auth_OpenID_ServerResponse($request);
  1886. $response->fields = Auth_OpenID_Message::fromOpenIDArgs(array(
  1887. 'foo' => 'amsigned',
  1888. 'bar' => 'notsigned',
  1889. 'azu' => 'alsosigned'));
  1890. $response->signed = array('foo', 'azu');
  1891. $sresponse = $this->signatory->sign($response);
  1892. $new_assoc_handle = $sresponse->fields->getArg(Auth_OpenID_OPENID_NS,
  1893. 'assoc_handle');
  1894. $this->assertTrue($new_assoc_handle);
  1895. $this->assertFalse($new_assoc_handle == $assoc_handle);
  1896. $this->assertEquals($sresponse->fields->getArg(Auth_OpenID_OPENID_NS,
  1897. 'invalidate_handle'),
  1898. $assoc_handle);
  1899. $this->assertEquals($sresponse->fields->getArg(Auth_OpenID_OPENID_NS,
  1900. 'signed'),
  1901. 'assoc_handle,azu,bar,foo,invalidate_handle,signed');
  1902. $this->assertTrue($sresponse->fields->hasKey(Auth_OpenID_OPENID_NS,
  1903. 'sig'));
  1904. // make sure the new key is a dumb mode association
  1905. $this->assertTrue($this->store->getAssociation($this->dumb_key,
  1906. $new_assoc_handle));
  1907. $this->assertFalse($this->store->getAssociation($this->normal_key,
  1908. $new_assoc_handle));
  1909. }
  1910. function test_verify()
  1911. {
  1912. $assoc_handle = '{vroom}{zoom}';
  1913. $assoc = Auth_OpenID_Association::fromExpiresIn(60, $assoc_handle,
  1914. 'sekrit', 'HMAC-SHA1');
  1915. $this->store->storeAssociation($this->dumb_key, $assoc);
  1916. $signed = Auth_OpenID_Message::fromPostArgs(array(
  1917. 'openid.foo' => 'bar',
  1918. 'openid.apple' => 'orange',
  1919. 'openid.assoc_handle' => $assoc_handle,
  1920. 'openid.signed' => 'apple,assoc_handle,foo,signed',
  1921. 'openid.sig' => 'uXoT1qm62/BB09Xbj98TQ8mlBco='));
  1922. $verified = $this->signatory->verify($assoc_handle, $signed);
  1923. $this->assertTrue($verified);
  1924. }
  1925. function test_verifyBadSig()
  1926. {
  1927. $assoc_handle = '{vroom}{zoom}';
  1928. $assoc = Auth_OpenID_Association::fromExpiresIn(60, $assoc_handle,
  1929. 'sekrit', 'HMAC-SHA1');
  1930. $this->store->storeAssociation($this->dumb_key, $assoc);
  1931. $signed = Auth_OpenID_Message::fromPostArgs(array(
  1932. 'openid.foo' => 'bar',
  1933. 'openid.apple' => 'orange',
  1934. 'openid.assoc_handle' => $assoc_handle,
  1935. 'openid.signed' => 'apple,assoc_handle,foo,signed',
  1936. 'openid.sig' => str_rot13('uXoT1qm62/BB09Xbj98TQ8mlBco=')));
  1937. $verified = $this->signatory->verify($assoc_handle, $signed);
  1938. $this->assertFalse($verified);
  1939. }
  1940. function test_verifyBadHandle()
  1941. {
  1942. $assoc_handle = '{vroom}{zoom}';
  1943. $signed = Auth_OpenID_Message::fromPostArgs(
  1944. array('foo' => 'bar',
  1945. 'apple' => 'orange',
  1946. 'openid.sig' => "Ylu0KcIR7PvNegB/K41KpnRgJl0="));
  1947. $verified = $this->signatory->verify($assoc_handle, $signed);
  1948. $this->assertFalse($verified);
  1949. }
  1950. function test_verifyAssocMismatch()
  1951. {
  1952. // Attempt to validate sign-all message with a signed-list
  1953. // assoc.
  1954. $assoc_handle = '{vroom}{zoom}';
  1955. $assoc = Auth_OpenID_Association::fromExpiresIn(
  1956. 60, $assoc_handle, 'sekrit', 'HMAC-SHA1');
  1957. $this->store->storeAssociation($this->dumb_key, $assoc);
  1958. $signed = Auth_OpenID_Message::fromPostArgs(array(
  1959. 'foo' => 'bar',
  1960. 'apple' => 'orange',
  1961. 'openid.sig' => "d71xlHtqnq98DonoSgoK/nD+QRM="
  1962. ));
  1963. $verified = $this->signatory->verify($assoc_handle, $signed);
  1964. $this->assertFalse($verified);
  1965. }
  1966. function test_getAssoc()
  1967. {
  1968. $assoc_handle = $this->makeAssoc(true);
  1969. $assoc = $this->signatory->getAssociation($assoc_handle, true);
  1970. $this->assertTrue($assoc);
  1971. $this->assertEquals($assoc->handle, $assoc_handle);
  1972. }
  1973. function test_getAssocExpired()
  1974. {
  1975. $assoc_handle = $this->makeAssoc(true, -10);
  1976. $assoc = $this->signatory->getAssociation($assoc_handle, true);
  1977. $this->assertFalse($assoc);
  1978. }
  1979. function test_getAssocInvalid()
  1980. {
  1981. $ah = 'no-such-handle';
  1982. $this->assertEquals(
  1983. $this->signatory->getAssociation($ah, false), null);
  1984. }
  1985. function test_getAssocDumbVsNormal()
  1986. {
  1987. $assoc_handle = $this->makeAssoc(true);
  1988. $this->assertEquals(
  1989. $this->signatory->getAssociation($assoc_handle, false), null);
  1990. }
  1991. function test_createAssociation()
  1992. {
  1993. $assoc = $this->signatory->createAssociation(false);
  1994. $this->assertTrue($this->signatory->getAssociation($assoc->handle,
  1995. false));
  1996. }
  1997. function makeAssoc($dumb, $lifetime = 60)
  1998. {
  1999. $assoc_handle = '{bling}';
  2000. $assoc = Auth_OpenID_Association::fromExpiresIn(
  2001. $lifetime, $assoc_handle,
  2002. 'sekrit', 'HMAC-SHA1');
  2003. $this->store->storeAssociation((($dumb) ? $this->dumb_key :
  2004. $this->normal_key), $assoc);
  2005. return $assoc_handle;
  2006. }
  2007. function test_invalidate()
  2008. {
  2009. $assoc_handle = '-squash-';
  2010. $assoc = Auth_OpenID_Association::fromExpiresIn(60, $assoc_handle,
  2011. 'sekrit', 'HMAC-SHA1');
  2012. $this->store->storeAssociation($this->dumb_key, $assoc);
  2013. $assoc = $this->signatory->getAssociation($assoc_handle, true);
  2014. $this->assertTrue($assoc);
  2015. $assoc = $this->signatory->getAssociation($assoc_handle, true);
  2016. $this->assertTrue($assoc);
  2017. $this->signatory->invalidate($assoc_handle, true);
  2018. $assoc = $this->signatory->getAssociation($assoc_handle, true);
  2019. $this->assertFalse($assoc);
  2020. }
  2021. }
  2022. class Tests_Auth_OpenID_Server extends PHPUnit_TestSuite {
  2023. function getName()
  2024. {
  2025. return "Tests_Auth_OpenID_Server";
  2026. }
  2027. function Tests_Auth_OpenID_Server()
  2028. {
  2029. $this->addTestSuite('Tests_Auth_OpenID_Signatory');
  2030. $this->addTestSuite('Tests_Auth_OpenID_ServerTest');
  2031. if (!defined('Auth_OpenID_NO_MATH_SUPPORT')) {
  2032. $this->addTestSuite('Tests_Auth_OpenID_Associate');
  2033. }
  2034. $this->addTestSuite('Tests_Auth_OpenID_CheckAuth');
  2035. $this->addTestSuite('Tests_Auth_OpenID_CheckIDExtension');
  2036. $this->addTestSuite('Tests_Auth_OpenID_CheckAuth');
  2037. $this->addTestSuite('Tests_Auth_OpenID_SigningEncode');
  2038. $this->addTestSuite('Tests_Auth_OpenID_Test_Encode');
  2039. $this->addTestSuite('Tests_Auth_OpenID_Test_Decode');
  2040. $this->addTestSuite('Tests_Auth_OpenID_Test_ServerError');
  2041. $this->addTestSuite('Tests_Auth_OpenID_CheckID');
  2042. }
  2043. }
  2044. ?>