def verify_id_token(msg, check_hash=False, claim='id_token', **kwargs):
    # Try to decode the JWT, checks the signature
    args = {}
    for arg in ID_TOKEN_VERIFY_ARGS:
        try:
            args[arg] = kwargs[arg]
        except KeyError:
            pass

    _jws = jws_factory(msg[claim])
    if not _jws:
        raise ValueError('{} not a signed JWT'.format(claim))

    if _jws.jwt.headers['alg'] == 'none':
        try:
            _allow_none = kwargs['allow_sign_alg_none']
        except KeyError:
            logger.info('Signing algorithm None not allowed')
            return False
        else:
            if not _allow_none:
                logger.info('Signing algorithm None not allowed')
                return False

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

    idt = IdToken().from_jwt(str(msg[claim]), **args)
    if not idt.verify(**kwargs):
        return False

    if check_hash:
        _alg = idt.jws_header["alg"]
        hfunc = "HS" + _alg[-3:]

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

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

    msg[verified_claim_name(claim)] = idt
    logger.info('Verified {}: {}'.format(claim, idt.to_dict()))

    return True
Exemplo n.º 2
0
def verify_id_token(msg, check_hash=False, claim="id_token", **kwargs):
    # Try to decode the JWT, checks the signature
    args = {}
    for arg in ID_TOKEN_VERIFY_ARGS:
        try:
            args[arg] = kwargs[arg]
        except KeyError:
            pass

    _jws = jws_factory(msg[claim])
    if not _jws:
        raise ValueError("{} not a signed JWT".format(claim))

    if _jws.jwt.headers["alg"] == "none":
        _signed = False
        _sign_alg = kwargs.get("sigalg")
        if _sign_alg == "none":
            _allowed = True
        else:  # There might or might not be a specified signing alg
            if kwargs.get("allow_sign_alg_none", False) is False:
                logger.info("Signing algorithm None not allowed")
                raise UnsupportedAlgorithm("Signing algorithm None not allowed")
    else:
        _signed = True
        if "allowed_sign_alg" in kwargs:
            if _jws.jwt.headers["alg"] != kwargs["allowed_sign_alg"]:
                _msg = "Wrong token signing algorithm, {} != {}".format(
                    _jws.jwt.headers["alg"], kwargs["allowed_sign_alg"]
                )
                logger.error(_msg)
                raise UnsupportedAlgorithm(_msg)

    _body = _jws.jwt.payload()
    if _signed and "keyjar" in kwargs:
        try:
            if _body["iss"] not in kwargs["keyjar"]:
                logger.info("KeyJar issuers: {}".format(kwargs["keyjar"]))
                raise ValueError('Unknown issuer: "{}"'.format(_body["iss"]))
        except KeyError:
            raise MissingRequiredAttribute("iss")

    idt = IdToken().from_jwt(str(msg[claim]), **args)
    if not idt.verify(**kwargs):
        return False

    if _signed and check_hash:
        _alg = idt.jws_header["alg"]
        hfunc = "HS" + _alg[-3:]

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

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

    msg[verified_claim_name(claim)] = idt
    logger.info("Verified {}: {}".format(claim, idt.to_dict()))

    return True
Exemplo n.º 3
0
    def from_jwt(self, txt, keyjar, verify=True, **kwargs):
        """
        Given a signed and/or encrypted JWT, verify its correctness and then
        create a class instance from the content.

        :param txt: The JWT
        :param key: keys that might be used to decrypt and/or verify the
            signature of the JWT
        :param verify: Whether the signature should be verified or not
        :param keyjar: A KeyJar that might contain the necessary key.
        :param kwargs: Extra key word arguments
        :return: A class instance
        """

        algarg = {}
        if 'encalg' in kwargs:
            algarg['alg'] = kwargs['encalg']
        if 'encenc' in kwargs:
            algarg['enc'] = kwargs['encenc']
        _decryptor = jwe_factory(txt, **algarg)

        if _decryptor:
            logger.debug("JWE headers: %s", _decryptor.jwt.headers)

            dkeys = keyjar.get_decrypt_key(owner="")

            logger.debug('Decrypt class: %s', _decryptor.__class__)
            _res = _decryptor.decrypt(txt, dkeys)
            logger.debug('decrypted message: %s', _res)
            if isinstance(_res, tuple):
                txt = as_unicode(_res[0])
            elif isinstance(_res, list) and len(_res) == 2:
                txt = as_unicode(_res[0])
            else:
                txt = as_unicode(_res)
            self.jwe_header = _decryptor.jwt.headers

        if kwargs.get('sigalg'):
            _verifier = jws_factory(txt, alg=kwargs['sigalg'])
        else:
            _verifier = jws_factory(txt)

        if _verifier:
            _jwt = _verifier.jwt
            jso = _jwt.payload()
            _header = _jwt.headers

            key = []
            # if "sender" in kwargs:
            #     key.extend(keyjar.get_verify_key(owner=kwargs["sender"]))

            logger.debug("Raw JSON: %s", jso)
            logger.debug("JWS header: %s", _header)
            if _header["alg"] == "none":
                pass
            elif verify:
                if keyjar:
                    key.extend(keyjar.get_jwt_verify_keys(_jwt, **kwargs))

                if "alg" in _header and _header["alg"] != "none":
                    if not key:
                        raise MissingSigningKey("alg=%s" % _header["alg"])

                logger.debug("Found signing key.")
                try:
                    _verifier.verify_compact(txt, key)
                except NoSuitableSigningKeys:
                    if keyjar:
                        keyjar.update()
                        key = keyjar.get_jwt_verify_keys(_jwt, **kwargs)
                        _verifier.verify_compact(txt, key)

            self.jws_header = _jwt.headers
        else:
            jso = json.loads(txt)

        self.jwt = txt
        return self.from_dict(jso)