Esempio n. 1
0
    def verify(self, **kwargs):
        """
        Verifies that an instance of this class adhers to the given 
            restrictions.
        """
        super(MetadataStatement, self).verify(**kwargs)
        if "signing_keys" in self:
            if 'signing_keys_uri' in self:
                raise VerificationError(
                    'You can only have one of "signing_keys" and '
                    '"signing_keys_uri" in a metadata statement')
            else:
                # signing_keys MUST be a JWKS
                kj = KeyJar()
                try:
                    kj.import_jwks(self['signing_keys'], '')
                except Exception:
                    raise VerificationError('"signing_keys" not a proper JWKS')

        if "metadata_statements" in self and "metadata_statement_uris" in self:
            s = set(self['metadata_statements'].keys())
            t = set(self['metadata_statement_uris'].keys())
            if s.intersection(t):
                raise VerificationError(
                    'You should not have the same key in "metadata_statements" '
                    'and in "metadata_statement_uris"')

        return True
Esempio n. 2
0
    def verify(self, **kwargs):
        super(IdToken, self).verify(**kwargs)

        if "aud" in self:
            if "client_id" in kwargs:
                # check that I'm among the recipients
                if kwargs["client_id"] not in self["aud"]:
                    raise NotForMe(
                        "{} not in aud:{}".format(kwargs["client_id"],
                                                  self["aud"]), self)

            # Then azp has to be present and be one of the aud values
            if len(self["aud"]) > 1:
                try:
                    assert "azp" in self
                except AssertionError:
                    raise VerificationError("azp missing", self)
                else:
                    try:
                        assert self["azp"] in self["aud"]
                    except AssertionError:
                        raise VerificationError(
                            "Mismatch between azp and aud claims", self)

        if "azp" in self:
            if "client_id" in kwargs:
                if kwargs["client_id"] != self["azp"]:
                    raise NotForMe(
                        "{} != azp:{}".format(kwargs["client_id"],
                                              self["azp"]), self)

        _now = time_util.utc_time_sans_frac()

        try:
            _skew = kwargs['skew']
        except KeyError:
            _skew = 0

        try:
            _exp = self['exp']
        except KeyError:
            raise MissingRequiredAttribute('exp')
        else:
            if (_now - _skew) > _exp:
                raise EXPError('Invalid expiration time')

        try:
            _storage_time = kwargs['nonce_storage_time']
        except KeyError:
            _storage_time = NONCE_STORAGE_TIME

        try:
            _iat = self['iat']
        except KeyError:
            raise MissingRequiredAttribute('iat')
        else:
            if (_iat + _storage_time) < (_now - _skew):
                raise IATError('Issued too long ago')

        return True
Esempio n. 3
0
    def verify(self, **kwargs):
        if "aud" in self:
            if "client_id" in kwargs:
                # check that I'm among the recipients
                if kwargs["client_id"] not in self["aud"]:
                    raise NotForMe("", self)

            # Then azp has to be present and be one of the aud values
            if len(self["aud"]) > 1:
                try:
                    assert "azp" in self
                except AssertionError:
                    raise VerificationError("azp missing", self)
                else:
                    try:
                        assert self["azp"] in self["aud"]
                    except AssertionError:
                        raise VerificationError(
                            "Mismatch between azp and aud claims", self)

        if "azp" in self:
            if "client_id" in kwargs:
                if kwargs["client_id"] != self["azp"]:
                    raise NotForMe("", self)

        return super(IdToken, self).verify(**kwargs)
Esempio n. 4
0
def verify_id_token(instance, check_hash=False, **kwargs):
    # Try to decode the JWT, checks the signature
    args = {}
    for arg in TOKEN_VERIFY_ARGS:
        try:
            args[arg] = kwargs[arg]
        except KeyError:
            pass

    _jws = str(instance["id_token"])

    # It can be encrypted, so try to decrypt first
    _jwe = JWE_factory(_jws)
    if _jwe is not None:
        try:
            _jws = _jwe.decrypt(keys=kwargs["keyjar"].get_decrypt_key())
        except JWEException as err:
            raise VerificationError("Could not decrypt id_token", err)
    _packer = JWT()
    _body = _packer.unpack(_jws).payload()

    if "keyjar" in kwargs:
        try:
            if _body["iss"] not in kwargs["keyjar"]:
                raise ValueError("Unknown issuer")
        except KeyError:
            raise MissingRequiredAttribute("iss")

    if _jwe is not None:
        # Use the original encrypted token to set correct headers
        idt = IdToken().from_jwt(str(instance["id_token"]), **args)
    else:
        idt = IdToken().from_jwt(_jws, **args)
    if not idt.verify(**kwargs):
        raise VerificationError("Could not verify id_token", idt)

    if check_hash:
        _alg = idt.jws_header["alg"]
        if _alg != "none":
            hfunc = "HS" + _alg[-3:]
        else:
            # This is allowed only for `code` and it needs to be checked by a Client
            hfunc = None

        if "access_token" in instance and hfunc is not None:
            if "at_hash" not in idt:
                raise MissingRequiredAttribute("Missing at_hash property", idt)
            if idt["at_hash"] != jws.left_hash(instance["access_token"],
                                               hfunc):
                raise AtHashError("Failed to verify access_token hash", idt)

        if "code" in instance and hfunc is not None:
            if "c_hash" not in idt:
                raise MissingRequiredAttribute("Missing c_hash property", idt)
            if idt["c_hash"] != jws.left_hash(instance["code"], hfunc):
                raise CHashError("Failed to verify code hash", idt)

    return idt
Esempio n. 5
0
def verify_id_token(instance, check_hash=False, **kwargs):
    # Try to decode the JWT, checks the signature
    args = {}
    for arg in ["key", "keyjar", "algs", "sender"]:
        try:
            args[arg] = kwargs[arg]
        except KeyError:
            pass

    _jws = str(instance["id_token"])

    # It can be encrypted, so try to decrypt first
    _jwe = JWE_factory(_jws)
    if _jwe is not None:
        try:
            _jws = _jwe.decrypt(keys=kwargs['keyjar'].get_decrypt_key())
        except JWEException as err:
            raise VerificationError("Could not decrypt id_token", err)
    _packer = JWT()
    _body = _packer.unpack(_jws).payload()

    if 'keyjar' in kwargs:
        try:
            if _body['iss'] not in kwargs['keyjar']:
                raise ValueError('Unknown issuer')
        except KeyError:
            raise MissingRequiredAttribute('iss')

    if _jwe is not None:
        # Use the original encrypted token to set correct headers
        idt = IdToken().from_jwt(str(instance['id_token']), **args)
    else:
        idt = IdToken().from_jwt(_jws, **args)
    if not idt.verify(**kwargs):
        raise VerificationError("Could not verify id_token", idt)

    if check_hash:
        _alg = idt.jws_header["alg"]
        # What if _alg == 'none'

        hfunc = "HS" + _alg[-3:]

        if "access_token" in instance:
            if "at_hash" not in idt:
                raise MissingRequiredAttribute("Missing at_hash property", idt)
            if idt["at_hash"] != jws.left_hash(instance["access_token"],
                                               hfunc):
                raise AtHashError("Failed to verify access_token hash", idt)

        if "code" in instance:
            if "c_hash" not in idt:
                raise MissingRequiredAttribute("Missing c_hash property", idt)
            if idt["c_hash"] != jws.left_hash(instance["code"], hfunc):
                raise CHashError("Failed to verify code hash", idt)

    return idt
Esempio n. 6
0
    def verify(self, **kwargs):
        super(AuthorizationResponse, self).verify(**kwargs)

        if 'client_id' in self:
            if self['client_id'] != kwargs['client_id']:
                raise VerificationError('client_id mismatch')
        if 'iss' in self:
            try:
                # Issuer URL for the authorization server issuing the response.
                if self['iss'] != kwargs['iss']:
                    raise VerificationError('Issuer mismatch')
            except KeyError:
                logger.info('No issuer set in the Client config')
                pass

        return True
Esempio n. 7
0
    def verify(self, **kwargs):
        """
        Implementations MUST either return both a Client Configuration Endpoint
        and a Registration Access Token or neither of them.
        :param kwargs:
        :return: True if the message is OK otherwise False
        """

        if "registration_client_uri" in self:
            if not "registration_access_token":
                raise VerificationError((
                    "Only one of registration_client_uri"
                    " and registration_access_token present"), self)
        elif "registration_access_token" in self:
            raise VerificationError((
                "Only one of registration_client_uri"
                " and registration_access_token present"), self)

        return super(RegistrationResponse, self).verify(**kwargs)
Esempio n. 8
0
    def verify(self, **kwargs):
        super(AuthorizationResponse, self).verify(**kwargs)

        if "client_id" in self:
            try:
                if self["client_id"] != kwargs["client_id"]:
                    raise VerificationError("client_id mismatch")
            except KeyError:
                logger.info("No client_id to verify against")
                pass
        if "iss" in self:
            try:
                # Issuer URL for the authorization server issuing the response.
                if self["iss"] != kwargs["iss"]:
                    raise VerificationError("Issuer mismatch")
            except KeyError:
                logger.info("No issuer set in the Client config")
                pass

        return True
Esempio n. 9
0
    def verify(self, **kwargs):
        super(AuthorizationResponse, self).verify(**kwargs)

        if "aud" in self:
            if "client_id" in kwargs:
                # check that it's for me
                if kwargs["client_id"] not in self["aud"]:
                    return False

        if "id_token" in self:
            # Try to decode the JWT, checks the signature
            args = {}
            for arg in ["key", "keyjar", "algs", "sender"]:
                try:
                    args[arg] = kwargs[arg]
                except KeyError:
                    pass
            idt = IdToken().from_jwt(str(self["id_token"]), **args)
            if not idt.verify(**kwargs):
                raise VerificationError("Could not verify id_token", idt)

            _alg = idt.jws_header["alg"]
            # What if _alg == 'none'

            hfunc = "HS" + _alg[-3:]

            if "access_token" in self:
                try:
                    assert "at_hash" in idt
                except AssertionError:
                    raise MissingRequiredAttribute("Missing at_hash property",
                                                   idt)
                try:
                    assert idt["at_hash"] == jws.left_hash(
                        self["access_token"], hfunc)
                except AssertionError:
                    raise AtHashError("Failed to verify access_token hash",
                                      idt)

            if "code" in self:
                try:
                    assert "c_hash" in idt
                except AssertionError:
                    raise MissingRequiredAttribute("Missing c_hash property",
                                                   idt)
                try:
                    assert idt["c_hash"] == jws.left_hash(self["code"], hfunc)
                except AssertionError:
                    raise CHashError("Failed to verify code hash", idt)

            self["id_token"] = idt
        return True
Esempio n. 10
0
    def verify(self, **kwargs):
        if "birthdate" in self:
            # Either YYYY-MM-DD or just YYYY or 0000-MM-DD
            try:
                _ = time.strptime(self["birthdate"], "%Y-%m-%d")
            except ValueError:
                try:
                    _ = time.strptime(self["birthdate"], "%Y")
                except ValueError:
                    try:
                        _ = time.strptime(self["birthdate"], "0000-%m-%d")
                    except ValueError:
                        raise VerificationError("Birthdate format error", self)

        return super(OpenIDSchema, self).verify(**kwargs)
Esempio n. 11
0
    def verify(self, **kwargs):
        """
        Verify that the response is valid.

        Implementations MUST either return both a Client Configuration Endpoint
        and a Registration Access Token or neither of them.
        :param kwargs:
        :return: True if the message is OK otherwise False
        """
        super(RegistrationResponse, self).verify(**kwargs)

        has_reg_uri = "registration_client_uri" in self
        has_reg_at = "registration_access_token" in self
        if has_reg_uri != has_reg_at:
            raise VerificationError(("Only one of registration_client_uri"
                                     " and registration_access_token present"),
                                    self)

        return True
Esempio n. 12
0
    def verify(self, **kwargs):
        super(OpenIDSchema, self).verify(**kwargs)

        if "birthdate" in self:
            # Either YYYY-MM-DD or just YYYY or 0000-MM-DD
            try:
                time.strptime(self["birthdate"], "%Y-%m-%d")
            except ValueError:
                try:
                    time.strptime(self["birthdate"], "%Y")
                except ValueError:
                    try:
                        time.strptime(self["birthdate"], "0000-%m-%d")
                    except ValueError:
                        raise VerificationError("Birthdate format error", self)

        if any(val is None for val in self.values()):
            return False

        return True
Esempio n. 13
0
    def verify(self, **kwargs):
        super(IdToken, self).verify(**kwargs)

        try:
            if kwargs["iss"] != self["iss"]:
                raise IssuerMismatch("{} != {}".format(kwargs["iss"],
                                                       self["iss"]))
        except KeyError:
            pass

        if "aud" in self:
            if "client_id" in kwargs:
                # check that I'm among the recipients
                if kwargs["client_id"] not in self["aud"]:
                    raise NotForMe(
                        "{} not in aud:{}".format(kwargs["client_id"],
                                                  self["aud"]),
                        self,
                    )

            # Then azp has to be present and be one of the aud values
            if len(self["aud"]) > 1:
                if "azp" not in self:
                    raise VerificationError("azp missing", self)
                if self["azp"] not in self["aud"]:
                    raise VerificationError(
                        "Mismatch between azp and aud claims", self)

        if "azp" in self:
            if "client_id" in kwargs:
                if kwargs["client_id"] != self["azp"]:
                    raise NotForMe(
                        "{} != azp:{}".format(kwargs["client_id"],
                                              self["azp"]), self)

        _now = time_util.utc_time_sans_frac()

        try:
            _skew = kwargs["skew"]
        except KeyError:
            _skew = 0

        try:
            _exp = self["exp"]
        except KeyError:
            raise MissingRequiredAttribute("exp")
        else:
            if (_now - _skew) > _exp:
                raise EXPError("Invalid expiration time")

        try:
            _storage_time = kwargs["nonce_storage_time"]
        except KeyError:
            _storage_time = NONCE_STORAGE_TIME

        try:
            _iat = self["iat"]
        except KeyError:
            raise MissingRequiredAttribute("iat")
        else:
            if (_iat + _storage_time) < (_now - _skew):
                raise IATError("Issued too long ago")
            if _now < (_iat - _skew):
                raise IATError("Issued in the future")

        if _exp < _iat:
            raise EXPError("Invalid expiration time")

        return True