/** * Verifies a given assertion bundle for validity and against the audience * using the local server and without requesting Mozilla's fallback verifier. * * !!! THIS IS THE CURRENTLY __NOT__ ADVISED METHOD WHEN USED IN PRODUCTION MODE !!! * * @access private * @static * @param String $assertion The serialized assertion bundle * @param String $audience The audience as valid URL * @return array An array containing status okay on success or failure on error */ private static function verifyLocally($assertion, $audience) { /** * Include CertAssertion */ try { $certassertion = new CertAssertion($assertion, $audience); $result = $certassertion->verify(); $certChain =& $result["certChain"]; // TODO: Contains the additional payload of the assertion, may be added later! //$payload = &$result["payload"]; $assertion =& $result["assertion"]; // principal and issuer are in the last cert $lastCert =& $certChain[sizeof($certChain) - 1]; $principal = $lastCert->getCertParams()->getPrincipal(); $principal = $principal["email"]; $issuer = $lastCert->getAssertion()->getIssuer(); $result = array("status" => "okay", "email" => $principal, "audience" => $assertion->getAudience(), "expires" => $assertion->getExpiresAt(), "issuer" => $issuer); return json_encode($result); } catch (Exception $e) { //console.log($e->getTraceAsString()); return json_encode(array("status" => "failure", "reason" => $e->getMessage())); } }
<pre> <?php // Comment the following line out to test the script! die; error_reporting(0); require_once "../lib/browserid.php"; $publicKeyIdentity = AbstractPublicKey::deserialize('{"algorithm":"DS","p":"ff600483db6abfc5b45eab78594b3533d550d9f1bf2a992a7a8daa6dc34f8045ad4e6e0c429d334eeeaaefd7e23d4810be00e4cc1492cba325ba81ff2d5a5b305a8d17eb3bf4a06a349d392e00d329744a5179380344e82a18c47933438f891e22aeef812d69c8f75e326cb70ea000c3f776dfdbd604638c2ef717fc26d02e17","q":"e21e04f911d1ed7991008ecaab3bf775984309c3","g":"c52a4a0ff3b7e61fdf1867ce84138369a6154f4afa92966e3c827e25cfa6cf508b90e5de419e1337e07a2e9e2a3cd5dea704d175f8ebf6af397d69e110b96afb17c7a03259329e4829b0d03bbc7896b15b4ade53e130858cc34d96269aa89041f409136c7242a38895c9d5bccad4f389af1d7a4bd1398bd072dffa896233397a","y":"80942e74d41162e7ab30bb4a7a1e0fb0417aad0a1b55b12e0232618502a2552510d631a02a679e60787b12799215b9c35865efb4c86b56584bf85c31f886b25413dc7ef028917e9afbe35726849cfe28a43fba6cdd8e24f4575d5d582317183599c23399e90f10b7e5c0f2bcf7a37e0559dbe492a17a74a49597b0996a2b616d"}'); $secretKeyIdentity = AbstractSecretKey::deserialize('{"algorithm":"DS","p":"ff600483db6abfc5b45eab78594b3533d550d9f1bf2a992a7a8daa6dc34f8045ad4e6e0c429d334eeeaaefd7e23d4810be00e4cc1492cba325ba81ff2d5a5b305a8d17eb3bf4a06a349d392e00d329744a5179380344e82a18c47933438f891e22aeef812d69c8f75e326cb70ea000c3f776dfdbd604638c2ef717fc26d02e17","q":"e21e04f911d1ed7991008ecaab3bf775984309c3","g":"c52a4a0ff3b7e61fdf1867ce84138369a6154f4afa92966e3c827e25cfa6cf508b90e5de419e1337e07a2e9e2a3cd5dea704d175f8ebf6af397d69e110b96afb17c7a03259329e4829b0d03bbc7896b15b4ade53e130858cc34d96269aa89041f409136c7242a38895c9d5bccad4f389af1d7a4bd1398bd072dffa896233397a","x":"a8e62a39c007ab3b7fbaad2e51398c15ec4a720c"}'); $principal = $_REQUEST['principal']; $audience = $_REQUEST['audience']; echo "Usage: createBundle.php?principal=<principal>&audience=<audience>\r\n"; echo "Allowed keysizes: 64, 128, 256!\r\n"; $assertion = CertAssertion::createAssertion($audience, $secretKeyIdentity); echo "Assertion: "; var_dump(WebToken::parse($assertion)->getPayload()); echo "\r\n"; $identityCert = CertAssertion::createIdentityCert($principal, $publicKeyIdentity); echo "Identity Cert: "; var_dump(WebToken::parse($identityCert)->getPayload()); echo "\r\n"; $bundle = new CertBundle($assertion, array($identityCert)); $assertion = $bundle->bundle(); echo "Bundle: "; var_dump($assertion); echo "\r\n"; $certAssertion = new CertAssertion($assertion, $audience); echo "isValid: "; var_dump($certAssertion->isValid()); ?> </pre>
/** * Compare audiences * * Checks if the given assertion is valid for the audience. * * @access private * @param string $want The expected audience * @return string The error message if it fails or null on success */ private function compareAudiences($want) { try { // We allow the RP to provide audience in multiple forms (see issue #82). // The RP SHOULD provide full origin, but we allow these alternate forms for // some dude named Postel doesn't go postal. // 1. full origin 'http://rp.tld' // 1a. full origin with port 'http://rp.tld:8080' // 2. domain and port 'rp.tld:8080' // 3. domain only 'rp.tld' // case 1 & 1a if (preg_match("/^https?:\\/\\//", $this->audience)) { $gu = CertAssertion::normalizeParsedURL(parse_url($this->audience)); $this->audience_scheme = $gu['scheme']; $this->audience_domain = $gu['host']; $this->audience_port = $gu['port']; } else { if (strpos($this->audience, ':') !== false) { $p = explode(':', $this->audience); if (count($p) !== 2) { throw new \Exception("malformed domain"); } $this->audience_domain = $p[0]; $this->audience_port = $p[1]; } else { $this->audience_domain = $this->audience; } } if (!isset($this->audience_domain)) { throw new \Exception("domain mismatch"); } // now parse "want" url $want = CertAssertion::normalizeParsedURL(parse_url($want)); // compare the parts explicitly provided by the client if (isset($this->audience_scheme) && $this->audience_scheme != $want['scheme']) { throw new \Exception("scheme mismatch : " . $want['scheme']); } if (isset($this->audience_port) && $this->audience_port != $want['port']) { throw new \Exception("port mismatch : " . $want['port'] . '/' . $this->audience_port); } if (isset($this->audience_domain) && $this->audience_domain != $want['host']) { throw new \Exception("domain mismatch " . $want['host'] . ' et ' . $this->audience_domain); } return null; } catch (Exception $e) { return $e->getMessage(); } }