Exemple #1
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")

        return True
Exemple #2
0
    def handle_response(self, r, csi):
        data = self.conv.events.last_item(EV_REQUEST)
        try:
            state = data['state']
        except KeyError:
            state = ''

        if 300 < r.status_code < 400:
            resp = self.conv.entity.parse_response(self.response,
                                                   info=r.headers['location'],
                                                   sformat="urlencoded",
                                                   state=state)
        elif r.status_code == 200:
            if "response_mode" in csi and csi["response_mode"] == "form_post":
                resp = self.response()
                forms = BeautifulSoup(r.text).findAll('form')
                for inp in forms[0].find_all("input"):
                    resp[inp.attrs["name"]] = inp.attrs["value"]
            else:
                if r.is_redirect or r.is_permanent_redirect:
                    resp = self.conv.entity.parse_response(
                        self.response,
                        info=r.headers['location'],
                        sformat="urlencoded",
                        state=state)
                else:
                    resp = self.conv.entity.parse_response(self.response,
                                                           info=r.text,
                                                           sformat="json",
                                                           state=state)

            _ent = self.conv.entity
            if isinstance(resp, AccessTokenResponse):
                if 'id_token' in resp and isinstance(resp['id_token'],
                                                     IdToken):
                    pass
                else:
                    resp.verify(keyjar=_ent.keyjar,
                                client_id=_ent.client_id,
                                iss=_ent.provider_info['issuer'])
            else:
                resp.verify(keyjar=_ent.keyjar,
                            client_id=_ent.client_id,
                            iss=_ent.provider_info['issuer'])

        elif r.status_code == 400:
            if r.headers['content-type'] == 'application/json':
                resp = ErrorResponse().from_json(r.text)
            else:
                resp = ErrorResponse(error='service_error',
                                     error_description=r.text)
        else:
            resp = r

        if not isinstance(resp, Response):  # Not a HTTP response
            try:
                try:
                    _id_token = resp["id_token"]
                except KeyError:
                    pass
                else:
                    if _id_token.jws_header:
                        self.conv.events.store('JWS header',
                                               _id_token.jws_header)
                    if _id_token.jwe_header:
                        self.conv.events.store('JWE header',
                                               _id_token.jwe_header)
                    if "kid" not in _id_token.jws_header and not \
                            _id_token.jws_header["alg"] == "HS256":
                        keys = self.conv.entity.keyjar.keys_by_alg_and_usage(
                            issuer=_id_token['iss'],
                            alg=_id_token.jws_header["alg"],
                            usage='sig')
                        if len(keys) > 1:
                            raise ParameterError(
                                "No 'kid' in id_token header!")

                    try:
                        if self.req_args['nonce'] != _id_token['nonce']:
                            raise ParameterError(
                                "invalid nonce! {} != {}".format(
                                    self.req_args['nonce'],
                                    _id_token['nonce']))
                    except KeyError:
                        pass

                    if not same_issuer(self.conv.info["issuer"],
                                       _id_token["iss"]):
                        raise IssuerMismatch(" {} != {}".format(
                            self.conv.info["issuer"], _id_token["iss"]))
                    self.conv.entity.id_token = _id_token
            except KeyError:
                pass

        return resp