Server.php 93 KB

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