def verify(self, **kwargs):
        super(LogoutToken, self).verify(**kwargs)

        if 'nonce' in self:
            raise MessageException('"nonce" is prohibited from appearing in '
                                   'a LogoutToken.')

        # Check the 'events' JSON
        _keys = list(self['events'].keys())
        if len(_keys) != 1:
            raise ValueError('Must only be one member in "events"')
        if _keys[0] != "http://schemas.openid.net/event/backchannel-logout":
            raise ValueError('Wrong member in "events"')
        if self['events'][_keys[0]] != {}:
            raise ValueError('Wrong member value in "events"')

        # There must be either a 'sub' or a 'sid', and may contain both
        if not ('sub' in self or 'sid' in self):
            raise ValueError('There MUST be either a "sub" or a "sid"')

        try:
            if kwargs['aud'] not in self['aud']:
                raise NotForMe('Not among intended audience')
        except KeyError:
            pass

        try:
            if kwargs['iss'] != self['iss']:
                raise NotForMe('Wrong issuer')
        except KeyError:
            pass

        _now = utc_time_sans_frac()

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

        try:
            _exp = self['iat']
        except KeyError:
            pass
        else:
            if self['iat'] > (_now + _skew):
                raise ValueError('Invalid issued_at time')

        _allowed = kwargs.get("allowed_sign_alg")
        if _allowed and self.jws_header['alg'] != _allowed:
            _msg = "Wrong token signing algorithm, {} != {}".format(
                self.jws_header['alg'], kwargs["allowed_sign_alg"])
            raise UnsupportedAlgorithm(_msg)

        return True
Example #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