Ejemplo n.º 1
0
 def parse(cls, jwt):
     """Parse a JWT from a string."""
     algorithm, payload, signature = jwt.split(".")
     signed_data = algorithm + "." + payload
     algorithm = json.loads(decode_bytes(algorithm))["alg"]
     payload = json.loads(decode_bytes(payload))
     signature = decode_bytes(signature)
     return cls(algorithm, payload, signature, signed_data)
Ejemplo n.º 2
0
 def parse(cls, jwt):
     """Parse a JWT from a string."""
     algorithm, payload, signature = jwt.split(".")
     signed_data = algorithm + "." + payload
     try:
         algorithm = decode_json_bytes(algorithm)["alg"]
     except KeyError:
         raise ValueError("badly formed JWT")
     payload = decode_json_bytes(payload)
     signature = decode_bytes(signature)
     return cls(algorithm, payload, signature, signed_data)
Ejemplo n.º 3
0
 def parse(cls, jwt):
     """Parse a JWT from a string."""
     algorithm, payload, signature = jwt.split(".")
     signed_data = algorithm + "." + payload
     try:
         algorithm = decode_json_bytes(algorithm)["alg"]
     except KeyError:
         raise ValueError("badly formed JWT")
     payload = decode_json_bytes(payload)
     signature = decode_bytes(signature)
     return cls(algorithm, payload, signature, signed_data)
Ejemplo n.º 4
0
    def verify(self, assertion, audience=None):
        """Verify the given VEP assertion.

        This method posts the given VEP assertion to the remove verifier
        service.  If it is successfully verified then a dict giving the
        email and audience is returned.  If it is not valid then an error
        is raised.

        If the 'audience' argument is given, it first verifies that the
        audience of the assertion matches the one given.  This can help
        avoid doing lots of crypto for assertions that can't be valid.
        If you don't specify an audience, you *MUST* validate the audience
        value returned by this method.
        """
        # Read audience from assertion if not specified.
        if audience is None:
            token = json.loads(decode_bytes(assertion))["assertion"]
            audience = json.loads(decode_bytes(token.split(".")[1]))["aud"]
        # Encode the data into x-www-form-urlencoded.
        post_data = {"assertion": assertion, "audience": audience}
        post_data = "&".join("%s=%s" % item for item in post_data.items())
        # Post it to the verifier.
        resp = self.urlopen(self.verifier_url, post_data)
        try:
            info = resp.info()
        except AttributeError:
            info = {}
        content_length = info.get("Content-Length")
        if content_length is None:
            data = resp.read()
        else:
            data = resp.read(int(content_length))
        data = json.loads(data)
        # Did it come back clean?
        if data.get('status') != "okay":
            raise ValueError(str(data))
        assert data.get('audience') == audience
        return data
Ejemplo n.º 5
0
    def verify(self, assertion, audience=None, now=None):
        """Verify the given VEP assertion.

        This method parses a VEP identity assertion, verifies the bundled
        chain of certificates and signatures, and returns the extracted
        email address and audience.

        If the 'audience' argument is given, it first verifies that the
        audience of the assertion matches the one given.  This can help
        avoid doing lots of crypto for assertions that can't be valid.
        If you don't specify an audience, you *MUST* validate the audience
        value returned by this method.

        If the 'now' argument is given, it is used as the current time in
        milliseconds.  This lets you verify expired assertions.
        """
        if now is None:
            now = int(time.time() * 1000)
        data = json.loads(decode_bytes(assertion))
        # Check that the assertion is usable and valid.
        # No point doing all that crypto if we're going to fail out anyway.
        assertion = JWT.parse(data["assertion"])
        if audience is not None:
            if assertion.payload["aud"] != audience:
                raise ValueError("mismatched audience")
        if assertion.payload["exp"] < now:
            raise ValueError("expired assertion")
        # Follow the certificate chain to get to the claiming principal.
        certificates = data["certificates"]
        certificates = [JWT.parse(c) for c in certificates]
        cert = self.verify_certificate_chain(certificates, now=now)
        email = cert.payload["principal"]["email"]
        # Check that the root issuer is trusted.
        root_issuer = certificates[0].payload["iss"]
        if root_issuer not in self.trusted_secondaries:
            if not email.endswith("@" + root_issuer):
                msg = "untrusted root issuer: %s" % (root_issuer,)
                raise ValueError(msg)
        # Check the signature on the assertion.
        if not assertion.check_signature(cert.payload["public-key"]):
            raise ValueError("invalid signature on assertion")
        # Looks good!
        return {"status": "okay",
                "audience": assertion.payload["aud"],
                "email": email}
Ejemplo n.º 6
0
 def test_encode_decode_bytes(self):
     self.assertEquals("HELLO", decode_bytes(encode_bytes("HELLO")))
     self.assertEquals("HELLO", decode_bytes(encode_bytes(u"HELLO")))
     self.assertRaises(ValueError, decode_bytes, u"\N{SNOWMAN}")
     self.assertRaises(ValueError, decode_bytes, "A===")
Ejemplo n.º 7
0
 def test_encode_decode_bytes(self):
     self.assertEquals("HELLO", decode_bytes(encode_bytes("HELLO")))
     self.assertEquals("HELLO", decode_bytes(encode_bytes(u"HELLO")))
     self.assertRaises(ValueError, decode_bytes, u"\N{SNOWMAN}")
     self.assertRaises(ValueError, decode_bytes, "A===")