Ejemplo n.º 1
0
    def test_end_session_endpoint_with_wrong_post_logout_redirect_uri(self):
        self._code_auth("1234567")
        self._code_auth2("abcdefg")

        id_token = self._auth_with_id_token("1234567")

        _sdb = self.session_endpoint.endpoint_context.sdb
        _sid = self._get_sid()
        cookie = self._create_cookie("diana", _sid, "1234567", "client_1")

        post_logout_redirect_uri = "https://demo.example.com/log_out"

        msg = Message(id_token=id_token)
        verify_id_token(msg, keyjar=self.session_endpoint.endpoint_context.keyjar)

        with pytest.raises(RedirectURIError):
            self.session_endpoint.process_request(
                {
                    "post_logout_redirect_uri": post_logout_redirect_uri,
                    "state": "abcde",
                    "id_token_hint": id_token,
                    verified_claim_name("id_token_hint"): msg[
                        verified_claim_name("id_token")
                    ],
                },
                cookie=cookie,
            )
Ejemplo n.º 2
0
    def test_end_session_endpoint_with_wrong_post_logout_redirect_uri(self):
        _resp = self._code_auth("1234567")
        self._code_auth2("abcdefg")

        resp_args, _session_id = self._auth_with_id_token("1234567")
        id_token = resp_args["id_token"]

        cookie = self._create_cookie(_session_id)
        http_info = {"cookie": [cookie]}

        post_logout_redirect_uri = "https://demo.example.com/log_out"

        msg = Message(id_token=id_token)
        verify_id_token(
            msg,
            keyjar=self.session_endpoint.server_get("endpoint_context").keyjar)

        with pytest.raises(RedirectURIError):
            self.session_endpoint.process_request(
                {
                    "post_logout_redirect_uri":
                    post_logout_redirect_uri,
                    "state":
                    "abcde",
                    "id_token_hint":
                    id_token,
                    verified_claim_name("id_token_hint"):
                    msg[verified_claim_name("id_token")],
                },
                http_info=http_info,
            )
Ejemplo n.º 3
0
    def test_end_session_endpoint_with_cookie_wrong_user(self):
        # Need cookie and ID Token to figure this out
        id_token = self._auth_with_id_token("1234567")

        cookie = self._create_cookie("diggins", "_sid_", "1234567", "client_1")

        msg = Message(id_token=id_token)
        verify_id_token(msg, keyjar=self.session_endpoint.endpoint_context.keyjar)

        msg2 = Message(id_token_hint=id_token)
        msg2[verified_claim_name("id_token_hint")] = msg[
            verified_claim_name("id_token")
        ]
        with pytest.raises(ValueError):
            self.session_endpoint.process_request(msg2, cookie=cookie)
Ejemplo n.º 4
0
    def verify(self, request, **kwargs):
        _jwt = JWT(self.endpoint_context.keyjar)
        try:
            ca_jwt = _jwt.unpack(request["client_assertion"])
        except (Invalid, MissingKey, BadSignature) as err:
            logger.info("%s" % sanitize(err))
            raise AuthnFailure("Could not verify client_assertion.")

        try:
            logger.debug("authntoken: %s" % sanitize(ca_jwt.to_dict()))
        except AttributeError:
            logger.debug("authntoken: %s" % sanitize(ca_jwt))

        request[verified_claim_name("client_assertion")] = ca_jwt

        try:
            client_id = kwargs["client_id"]
        except KeyError:
            client_id = ca_jwt["iss"]

        # I should be among the audience
        # could be either my issuer id or the token endpoint
        if self.endpoint_context.issuer in ca_jwt["aud"]:
            pass
        elif self.endpoint_context.endpoint["token"].full_path in ca_jwt[
                "aud"]:
            pass
        else:
            raise NotForMe("Not for me!")

        return {"client_id": client_id, "jwt": ca_jwt}
 def test_id_token_nonce_match(self):
     self.service.store_nonce2state('nonce', 'state')
     resp = AccessTokenResponse()
     resp[verified_claim_name('id_token')] = {'nonce': 'nonce'}
     self.service.store_nonce2state('nonce2', 'state2')
     with pytest.raises(ParameterError):
         self.service.update_service_context(resp, key='state2')
Ejemplo n.º 6
0
def max_age(request):
    try:
        return request[verified_claim_name("request")]["max_age"]
    except KeyError:
        try:
            return request["max_age"]
        except KeyError:
            return 0
Ejemplo n.º 7
0
def backchannel_logout(client, request='', request_args=None):
    """

    :param request: URL encoded logout request
    :return:
    """

    if request:
        req = BackChannelLogoutRequest().from_urlencoded(as_unicode(request))
    else:
        req = BackChannelLogoutRequest(**request_args)

    kwargs = {
        'aud':
        client.service_context.get('client_id'),
        'iss':
        client.service_context.get('issuer'),
        'keyjar':
        client.service_context.keyjar,
        'allowed_sign_alg':
        client.service_context.get('registration_response').get(
            "id_token_signed_response_alg", "RS256")
    }

    try:
        req.verify(**kwargs)
    except (MessageException, ValueError, NotForMe) as err:
        raise MessageException('Bogus logout request: {}'.format(err))

    # Find the subject through 'sid' or 'sub'

    try:
        sub = req[verified_claim_name('logout_token')]['sub']
    except KeyError:
        try:
            sid = req[verified_claim_name('logout_token')]['sid']
        except KeyError:
            raise MessageException('Neither "sid" nor "sub"')
        else:
            _state = client.session_interface.get_state_by_sid(sid)
    else:
        _state = client.session_interface.get_state_by_sub(sub)

    return _state
Ejemplo n.º 8
0
    def _do_request_uri(self, request, client_id, endpoint_context, **kwargs):
        _request_uri = request.get("request_uri")
        if _request_uri:
            # Do I do pushed authorization requests ?
            if "pushed_authorization" in endpoint_context.endpoint:
                # Is it a UUID urn
                if _request_uri.startswith("urn:uuid:"):
                    _req = endpoint_context.par_db.get(_request_uri)
                    if _req:
                        del endpoint_context.par_db[_request_uri]  # One time
                        # usage
                        return _req
                    else:
                        raise ValueError("Got a request_uri I can not resolve")

            # Do I support request_uri ?
            _supported = endpoint_context.provider_info.get(
                "request_uri_parameter_supported", True)
            _registered = endpoint_context.cdb[client_id].get("request_uris")
            # Not registered should be handled else where
            if _registered:
                # Before matching remove a possible fragment
                _p = _request_uri.split("#")
                if _p[0] not in _registered:
                    raise ValueError("A request_uri outside the registered")
            # Fetch the request
            _resp = endpoint_context.httpc.get(_request_uri,
                                               **endpoint_context.httpc_params)
            if _resp.status_code == 200:
                args = {"keyjar": endpoint_context.keyjar}
                request = AuthorizationRequest().from_jwt(_resp.text, **args)
                self.allowed_request_algorithms(
                    client_id,
                    endpoint_context,
                    request.jws_header.get("alg", "RS256"),
                    "sign",
                )
                if request.jwe_header is not None:
                    self.allowed_request_algorithms(
                        client_id,
                        endpoint_context,
                        request.jws_header.get("alg"),
                        "enc_alg",
                    )
                    self.allowed_request_algorithms(
                        client_id,
                        endpoint_context,
                        request.jws_header.get("enc"),
                        "enc_enc",
                    )
                request[verified_claim_name("request")] = request
            else:
                raise ServiceError("Got a %s response", _resp.status)

        return request
Ejemplo n.º 9
0
    def test_end_session_endpoint_with_cookie_id_token_and_unknown_sid(self):
        # Need cookie and ID Token to figure this out
        resp_args, _session_id = self._auth_with_id_token("1234567")
        id_token = resp_args["id_token"]

        _uid, _cid, _gid = self.session_manager.decrypt_session_id(_session_id)
        cookie = self._create_cookie(
            self.session_manager.session_key(_uid, "client_66", _gid))
        http_info = {"cookie": [cookie]}

        msg = Message(id_token=id_token)
        verify_id_token(
            msg,
            keyjar=self.session_endpoint.server_get("endpoint_context").keyjar)

        msg2 = Message(id_token_hint=id_token)
        msg2[verified_claim_name("id_token_hint")] = msg[verified_claim_name(
            "id_token")]
        with pytest.raises(ValueError):
            self.session_endpoint.process_request(msg2, http_info=http_info)
Ejemplo n.º 10
0
def pick_auth(endpoint_context, areq, all=False):
    """
    Pick authentication method

    :param areq: AuthorizationRequest instance
    :return: A dictionary with the authentication method and its authn class ref
    """

    acrs = []
    try:
        if len(endpoint_context.authn_broker) == 1:
            return endpoint_context.authn_broker.default()

        if "acr_values" in areq:
            if not isinstance(areq["acr_values"], list):
                areq["acr_values"] = [areq["acr_values"]]
            acrs = areq["acr_values"]
        else:  # same as any
            try:
                acrs = areq["claims"]["id_token"]["acr"]["values"]
            except KeyError:
                try:
                    _ith = areq[verified_claim_name("id_token_hint")]
                except KeyError:
                    try:
                        _hint = areq["login_hint"]
                    except KeyError:
                        pass
                    else:
                        if endpoint_context.login_hint2acrs:
                            acrs = endpoint_context.login_hint2acrs(_hint)
                else:
                    try:
                        acrs = [_ith["acr"]]
                    except KeyError:
                        pass

                if not acrs:
                    return endpoint_context.authn_broker.default()

        for acr in acrs:
            res = endpoint_context.authn_broker.pick(acr)
            logger.debug("Picked AuthN broker for ACR %s: %s" % (str(acr), str(res)))
            if res:
                if all:
                    return res
                else:
                    # Return the first guess by pick.
                    return res[0]

    except KeyError as exc:
        logger.debug("An error occurred while picking the authN broker: %s" % str(exc))

    return None
Ejemplo n.º 11
0
    def verify(self, request, key_type, **kwargs):
        _context = self.server_get("endpoint_context")
        _jwt = JWT(_context.keyjar, msg_cls=JsonWebToken)
        try:
            ca_jwt = _jwt.unpack(request["client_assertion"])
        except (Invalid, MissingKey, BadSignature) as err:
            logger.info("%s" % sanitize(err))
            raise AuthnFailure("Could not verify client_assertion.")

        _sign_alg = ca_jwt.jws_header.get("alg")
        if _sign_alg and _sign_alg.startswith("HS"):
            if key_type == "private_key":
                raise AttributeError("Wrong key type")
            keys = _context.keyjar.get("sig", "oct", ca_jwt["iss"],
                                       ca_jwt.jws_header.get("kid"))
            _secret = _context.cdb[ca_jwt["iss"]].get("client_secret")
            if _secret and keys[0].key != as_bytes(_secret):
                raise AttributeError(
                    "Oct key used for signing not client_secret")
        else:
            if key_type == "client_secret":
                raise AttributeError("Wrong key type")

        authtoken = sanitize(ca_jwt.to_dict())
        logger.debug("authntoken: {}".format(authtoken))

        _endpoint = kwargs.get("endpoint")
        if _endpoint is None or not _endpoint:
            if _context.issuer in ca_jwt["aud"]:
                pass
            else:
                raise NotForMe("Not for me!")
        else:
            if set(ca_jwt["aud"]).intersection(
                    _endpoint.allowed_target_uris()):
                pass
            else:
                raise NotForMe("Not for me!")

        # If there is a jti use it to make sure one-time usage is true
        _jti = ca_jwt.get("jti")
        if _jti:
            _key = "{}:{}".format(ca_jwt["iss"], _jti)
            if _key in _context.jti_db:
                raise MultipleUsage("Have seen this token once before")
            else:
                _context.jti_db[_key] = utc_time_sans_frac()

        request[verified_claim_name("client_assertion")] = ca_jwt
        client_id = kwargs.get("client_id") or ca_jwt["iss"]

        return {"client_id": client_id, "jwt": ca_jwt}
Ejemplo n.º 12
0
def pick_auth(endpoint_context, areq, pick_all=False):
    """
    Pick authentication method

    :param areq: AuthorizationRequest instance
    :return: A dictionary with the authentication method and its authn class ref
    """
    acrs = []
    if len(endpoint_context.authn_broker) == 1:
        return endpoint_context.authn_broker.default()

    if "acr_values" in areq:
        if not isinstance(areq["acr_values"], list):
            areq["acr_values"] = [areq["acr_values"]]
        acrs = areq["acr_values"]

    else:
        try:
            acrs = areq["claims"]["id_token"]["acr"]["values"]
        except KeyError:
            _ith = verified_claim_name("id_token_hint")
            if areq.get(_ith):
                _ith = areq[verified_claim_name("id_token_hint")]
                if _ith.get("acr"):
                    acrs = [_ith["acr"]]
            else:
                if areq.get("login_hint") and endpoint_context.login_hint2acrs:
                    acrs = endpoint_context.login_hint2acrs(areq["login_hint"])

    if not acrs:
        return endpoint_context.authn_broker.default()

    for acr in acrs:
        res = endpoint_context.authn_broker.pick(acr)
        logger.debug(f"Picked AuthN broker for ACR {str(acr)}: {str(res)}")
        if res:
            return res if pick_all else res[0]

    return None
    def test_example(self):
        _symkey = KC_SYM_S.get(alg2keytype("HS256"))
        esreq = EndSessionRequest(id_token_hint=IDTOKEN.to_jwt(
            key=_symkey, algorithm="HS256", lifetime=300),
                                  redirect_url="http://example.org/jqauthz",
                                  state="state0")

        request = EndSessionRequest().from_urlencoded(esreq.to_urlencoded())
        keyjar = KeyJar()
        for _key in _symkey:
            keyjar.add_symmetric('', _key.key)
            keyjar.add_symmetric(ISS, _key.key)
            keyjar.add_symmetric(CLIENT_ID, _key.key)
        request.verify(keyjar=keyjar)
        assert isinstance(request, EndSessionRequest)
        assert set(request.keys()) == {
            verified_claim_name('id_token_hint'), 'id_token_hint',
            'redirect_url', 'state'
        }
        assert request["state"] == "state0"
        assert request[verified_claim_name("id_token_hint")]["aud"] == [
            "client_1"
        ]
Ejemplo n.º 14
0
 def test_id_token_acr(self):
     _req = AUTH_REQ_DICT.copy()
     _req["claims"] = {
         "id_token": {"acr": {"value": "http://www.swamid.se/policy/assurance/al1"}}
     }
     _req["response_type"] = "code id_token token"
     _req["nonce"] = "rnd_nonce"
     _pr_resp = self.endpoint.parse_request(_req)
     _resp = self.endpoint.process_request(_pr_resp)
     res = verify_id_token(
         _resp["response_args"], keyjar=self.endpoint.endpoint_context.keyjar
     )
     assert res
     res = _resp["response_args"][verified_claim_name("id_token")]
     assert res["acr"] == "http://www.swamid.se/policy/assurance/al1"
    def post_parse_response(self, response, **kwargs):
        response = authorization.Authorization.post_parse_response(
            self, response, **kwargs)

        _idt = response.get(verified_claim_name('id_token'))
        if _idt:
            # If there is a verified ID Token then we have to do nonce
            # verification.
            _request = self.get_request_from_response(response)
            _req_nonce = _request.get('nonce')
            if _req_nonce:
                _id_token_nonce = _idt.get('nonce')
                if not _id_token_nonce:
                    raise MissingRequiredAttribute('nonce')
                elif _req_nonce != _id_token_nonce:
                    raise ValueError('Invalid nonce')
        return response
Ejemplo n.º 16
0
    def extend_request_args(self,
                            args,
                            item_cls,
                            item_type,
                            key,
                            parameters,
                            orig=False):
        """
        Add a set of parameters and their value to a set of request arguments.

        :param args: A dictionary
        :param item_cls: The :py:class:`oidcmsg.message.Message` subclass
            that describes the item
        :param item_type: The type of item, this is one of the parameter
            names in the :py:class:`oidcservice.state_interface.State` class.
        :param key: The key to the information in the database
        :param parameters: A list of parameters who's values this method
            will return.
        :param orig: Where the value of a claim is a signed JWT return
            that.
        :return: A dictionary with keys from the list of parameters and
            values being the values of those parameters in the item.
            If the parameter does not a appear in the item it will not appear
            in the returned dictionary.
        """
        try:
            item = self.get_item(item_cls, item_type, key)
        except KeyError:
            pass
        else:
            for parameter in parameters:
                if orig:
                    try:
                        args[parameter] = item[parameter]
                    except KeyError:
                        pass
                else:
                    try:
                        args[parameter] = item[verified_claim_name(parameter)]
                    except KeyError:
                        try:
                            args[parameter] = item[parameter]
                        except KeyError:
                            pass

        return args
Ejemplo n.º 17
0
    def multiple_extend_request_args(self,
                                     args,
                                     key,
                                     parameters,
                                     item_types,
                                     orig=False):
        """
        Go through a set of items (by their type) and add the attribute-value
        that match the list of parameters to the arguments
        If the same parameter occurs in 2 different items then the value in
        the later one will be the one used.

        :param args: Initial set of arguments
        :param key: Key to the State information in the state database
        :param parameters: A list of parameters that we're looking for
        :param item_types: A list of item_type specifying which items we
            are interested in.
        :param orig: Where the value of a claim is a signed JWT return
            that.
        :return: A possibly augmented set of arguments.
        """
        _state = self.get_state(key)

        for typ in item_types:
            try:
                _item = Message(**_state[typ])
            except KeyError:
                continue

            for parameter in parameters:
                if orig:
                    try:
                        args[parameter] = _item[parameter]
                    except KeyError:
                        pass
                else:
                    try:
                        args[parameter] = _item[verified_claim_name(parameter)]
                    except KeyError:
                        try:
                            args[parameter] = _item[parameter]
                        except KeyError:
                            pass

        return args
Ejemplo n.º 18
0
    def parse_request(self, request, http_info=None, **kwargs):
        """

        :param request:
        :param auth:
        :param kwargs:
        :return:
        """

        if not request:
            request = {}

        # Verify that the client is allowed to do this
        try:
            auth_info = self.client_authentication(request, http_info, **kwargs)
        except UnknownOrNoAuthnMethod:
            pass
        else:
            if not auth_info:
                pass
            elif isinstance(auth_info, ResponseMessage):
                return auth_info
            else:
                request["client_id"] = auth_info["client_id"]
                request["access_token"] = auth_info["token"]

        if isinstance(request, dict):
            _context = self.server_get("endpoint_context")
            request = self.request_cls(**request)
            if not request.verify(keyjar=_context.keyjar, sigalg=""):
                raise InvalidRequest("Request didn't verify")
            # id_token_signing_alg_values_supported
            try:
                _ith = request[verified_claim_name("id_token_hint")]
            except KeyError:
                pass
            else:
                if (
                    _ith.jws_header["alg"]
                    not in _context.provider_info["id_token_signing_alg_values_supported"]
                ):
                    raise JWSException("Unsupported signing algorithm")

        return request
Ejemplo n.º 19
0
    def update_service_context(self, resp, key='', **kwargs):
        try:
            _idt = resp[verified_claim_name('id_token')]
        except KeyError:
            pass
        else:
            try:
                if self.get_state_by_nonce(_idt['nonce']) != key:
                    raise ParameterError('Someone has messed with "nonce"')
            except KeyError:
                raise ValueError('Invalid nonce value')

            self.store_sub2state(_idt['sub'], key)

        if 'expires_in' in resp:
            resp['__expires_at'] = time_sans_frac() + int(
                resp['expires_in'])

        self.store_item(resp, 'token_response', key)
    def update_service_context(self, resp, key='', **kwargs):
        try:
            _idt = resp[verified_claim_name('id_token')]
        except KeyError:
            pass
        else:
            # If there is a verified ID Token then we have to do nonce
            # verification
            try:
                if self.get_state_by_nonce(_idt['nonce']) != key:
                    raise ParameterError('Someone has messed with "nonce"')
            except KeyError:
                raise ValueError('Missing nonce value')

            self.store_sub2state(_idt['sub'], key)

        if 'expires_in' in resp:
            resp['__expires_at'] = time_sans_frac() + int(resp['expires_in'])
        self.store_item(resp.to_json(), 'auth_response', key)
Ejemplo n.º 21
0
    def verify(self, request, **kwargs):
        _jwt = JWT(self.endpoint_context.keyjar)
        try:
            ca_jwt = _jwt.unpack(request["client_assertion"])
        except (Invalid, MissingKey, BadSignature) as err:
            logger.info("%s" % sanitize(err))
            raise AuthnFailure("Could not verify client_assertion.")

        authtoken = sanitize(ca_jwt)
        if hasattr(ca_jwt, "to_dict") and callable(ca_jwt, "to_dict"):
            authtoken = sanitize(ca_jwt.to_dict())
        logger.debug("authntoken: {}".format(authtoken))

        _endpoint = kwargs.get("endpoint")
        if _endpoint is None or not _endpoint:
            if self.endpoint_context.issuer in ca_jwt["aud"]:
                pass
            else:
                raise NotForMe("Not for me!")
        else:
            if set(ca_jwt["aud"]).intersection(
                    self.endpoint_context.endpoint[_endpoint].allowed_target_uris()):
                pass
            else:
                raise NotForMe("Not for me!")

        # If there is a jti use it to make sure one-time usage is true
        _jti = ca_jwt.get('jti')
        if _jti:
            _key = "{}:{}".format(ca_jwt['iss'], _jti)
            if _key in self.endpoint_context.jti_db:
                raise MultipleUsage("Have seen this token once before")
            else:
                self.endpoint_context.jti_db.set(_key, utc_time_sans_frac())

        request[verified_claim_name("client_assertion")] = ca_jwt
        client_id = kwargs.get("client_id") or ca_jwt["iss"]

        return {"client_id": client_id, "jwt": ca_jwt}
Ejemplo n.º 22
0
    def verify(self, request=None, **kwargs):
        _context = self.server_get("endpoint_context")
        _jwt = JWT(_context.keyjar, msg_cls=JsonWebToken)
        try:
            _jwt = _jwt.unpack(request["request"])
        except (Invalid, MissingKey, BadSignature) as err:
            logger.info("%s" % sanitize(err))
            raise AuthnFailure("Could not verify client_assertion.")

        # If there is a jti use it to make sure one-time usage is true
        _jti = _jwt.get("jti")
        if _jti:
            _key = "{}:{}".format(_jwt["iss"], _jti)
            if _key in _context.jti_db:
                raise MultipleUsage("Have seen this token once before")
            else:
                _context.jti_db[_key] = utc_time_sans_frac()

        request[verified_claim_name("client_assertion")] = _jwt
        client_id = kwargs.get("client_id") or _jwt["iss"]

        return {"client_id": client_id, "jwt": _jwt}
Ejemplo n.º 23
0
    def parse_request(self, request, auth=None, **kwargs):
        """

        :param request:
        :param auth:
        :param kwargs:
        :return:
        """

        if not request:
            request = {}

        # Verify that the client is allowed to do this
        try:
            auth_info = self.client_authentication(request, auth, **kwargs)
        except UnknownOrNoAuthnMethod:
            pass
        else:
            if isinstance(auth_info, ResponseMessage):
                return auth_info
            else:
                request['client_id'] = auth_info['client_id']
                request['access_token'] = auth_info['token']

        if isinstance(request, dict):
            request = self.request_cls(**request)
            if not request.verify(keyjar=self.endpoint_context.keyjar,
                                  sigalg=''):
                raise InvalidRequest("Didn't verify")
            # id_token_signing_alg_values_supported
            _ith = request[verified_claim_name("id_token_hint")]
            if _ith.jws_header['alg'] not in \
                    self.endpoint_context.provider_info[
                        'id_token_signing_alg_values_supported']:
                raise JWSException('Unsupported signing algorithm')

        return request
Ejemplo n.º 24
0
def max_age(request):
    verified_request = verified_claim_name("request")
    return request.get(verified_request, {}).get("max_age") or request.get("max_age", 0)
Ejemplo n.º 25
0
    def process_request(self, request=None, cookie=None, **kwargs):
        """
        Perform user logout

        :param request:
        :param cookie:
        :param kwargs:
        :return:
        """
        _sdb = self.endpoint_context.sdb

        try:
            part = self.endpoint_context.cookie_dealer.get_cookie_value(
                cookie, cookie_name='oidc_op')
        except IndexError:
            raise InvalidRequest('Cookie error')

        if part:
            # value is a base64 encoded JSON document
            _cookie_info = json.loads(as_unicode(b64d(as_bytes(part[0]))))
            _sid = _cookie_info['sid']
        else:
            _sid = ''

        if 'id_token_hint' in request:
            _ith_sid = _sdb.sso_db.get_sids_by_sub(
                request[verified_claim_name("id_token_hint")]['sub'])[0]
            if _ith_sid != _sid:  # someone's messing with me
                raise ValueError('Wrong ID Token hint')

        session = _sdb[_sid]

        client_id = session['authn_req']['client_id']

        _cinfo = self.endpoint_context.cdb[client_id]

        # verify that the post_logout_redirect_uri if present are among the ones
        # registered

        try:
            _url_q = splitquery(request['post_logout_redirect_uri'])
        except KeyError:
            pass
        else:
            if not _url_q in _cinfo['post_logout_redirect_uris']:
                raise ValueError('Unregistered post_logout_redirect_uri')

        # Kill the session
        _sdb.revoke_session(sid=_sid)

        if 'post_logout_redirect_uri' in request:
            _ruri = request["post_logout_redirect_uri"]
            if 'state' in request:
                _ruri = '{}?{}'.format(_ruri,
                                       urlencode({'state': request['state']}))
        else:  # To  my own logout-done page
            try:
                _ruri = self.endpoint_context.conf['post_logout_page']
            except KeyError:
                _ruri = self.endpoint_context.issuer

        return {'response_args': _ruri}
Ejemplo n.º 26
0
 def proposed_user(self, request):
     try:
         return request[verified_claim_name('it_token_hint')]['sub']
     except KeyError:
         return ''
Ejemplo n.º 27
0
def proposed_user(request):
    try:
        return request[verified_claim_name("it_token_hint")]["sub"]
    except KeyError:
        return ""
Ejemplo n.º 28
0
def proposed_user(request):
    cn = verified_claim_name("it_token_hint")
    if request.get(cn):
        return request[cn].get("sub", "")
    return ""
Ejemplo n.º 29
0
    def _do_request_uri(self, request, client_id, endpoint_context, **kwargs):
        _request_uri = request.get("request_uri")
        if _request_uri:
            # Do I do pushed authorization requests ?
            _endp = self.server_get("endpoint", "pushed_authorization")
            if _endp:
                # Is it a UUID urn
                if _request_uri.startswith("urn:uuid:"):
                    _req = endpoint_context.par_db.get(_request_uri)
                    if _req:
                        # One time usage
                        del endpoint_context.par_db[_request_uri]
                        return _req
                    else:
                        raise ValueError("Got a request_uri I can not resolve")

            # Do I support request_uri ?
            if endpoint_context.provider_info.get(
                    "request_uri_parameter_supported", True) is False:
                raise ServiceError(
                    "Someone is using request_uri which I'm not supporting")

            _registered = endpoint_context.cdb[client_id].get("request_uris")
            # Not registered should be handled else where
            if _registered:
                # Before matching remove a possible fragment
                _p = _request_uri.split("#")
                # ignore registered fragments for now.
                if _p[0] not in [base for base, qp in _registered]:
                    raise ValueError("A request_uri outside the registered")

            # Fetch the request
            _resp = endpoint_context.httpc.get(_request_uri,
                                               **endpoint_context.httpc_params)
            if _resp.status_code == 200:
                args = {"keyjar": endpoint_context.keyjar, "issuer": client_id}
                _ver_request = self.request_cls().from_jwt(_resp.text, **args)
                self.allowed_request_algorithms(
                    client_id,
                    endpoint_context,
                    _ver_request.jws_header.get("alg", "RS256"),
                    "sign",
                )
                if _ver_request.jwe_header is not None:
                    self.allowed_request_algorithms(
                        client_id,
                        endpoint_context,
                        _ver_request.jws_header.get("alg"),
                        "enc_alg",
                    )
                    self.allowed_request_algorithms(
                        client_id,
                        endpoint_context,
                        _ver_request.jws_header.get("enc"),
                        "enc_enc",
                    )
                # The protected info overwrites the non-protected
                for k, v in _ver_request.items():
                    request[k] = v

                request[verified_claim_name("request")] = _ver_request
            else:
                raise ServiceError("Got a %s response", _resp.status)

        return request
Ejemplo n.º 30
0
    def process_request(self, request=None, cookie=None, **kwargs):
        """
        Perform user logout

        :param request:
        :param cookie:
        :param kwargs:
        :return:
        """
        _cntx = self.endpoint_context
        _sdb = _cntx.sdb

        if "post_logout_redirect_uri" in request:
            if "id_token_hint" not in request:
                raise InvalidRequest(
                    "If post_logout_redirect_uri then id_token_hint is a MUST")
        _cookie_name = self.endpoint_context.cookie_name["session"]
        try:
            part = self.endpoint_context.cookie_dealer.get_cookie_value(
                cookie, cookie_name=_cookie_name)
        except IndexError:
            raise InvalidRequest("Cookie error")
        except KeyError:
            part = None

        if part:
            # value is a base64 encoded JSON document
            _cookie_info = json.loads(as_unicode(b64d(as_bytes(part[0]))))
            logger.debug("Cookie info: {}".format(_cookie_info))
            _sid = _cookie_info["sid"]
        else:
            logger.debug("No relevant cookie")
            _sid = ""
            _cookie_info = {}

        if "id_token_hint" in request:
            logger.debug("ID token hint: {}".format(
                request[verified_claim_name("id_token_hint")]))

            auds = request[verified_claim_name("id_token_hint")]["aud"]
            _ith_sid = ""
            _sids = _sdb.sso_db.get_sids_by_sub(
                request[verified_claim_name("id_token_hint")]["sub"])

            if _sids is None:
                raise ValueError("Unknown subject identifier")

            for _isid in _sids:
                if _sdb[_isid]["authn_req"]["client_id"] in auds:
                    _ith_sid = _isid
                    break

            if not _ith_sid:
                raise ValueError("Unknown subject")

            if _sid:
                if _ith_sid != _sid:  # someone's messing with me
                    raise ValueError("Wrong ID Token hint")
            else:
                _sid = _ith_sid
        else:
            auds = []

        try:
            session = _sdb[_sid]
        except KeyError:
            raise ValueError("Can't find any corresponding session")

        client_id = session["authn_req"]["client_id"]
        # Does this match what's in the cookie ?
        if _cookie_info:
            if client_id != _cookie_info["client_id"]:
                logger.warning(
                    "Client ID in authz request and in cookie does not match")
                raise ValueError("Wrong Client")

        if auds:
            if client_id not in auds:
                raise ValueError("Incorrect ID Token hint")

        _cinfo = _cntx.cdb[client_id]

        # verify that the post_logout_redirect_uri if present are among the ones
        # registered

        try:
            _uri = request["post_logout_redirect_uri"]
        except KeyError:
            if _cntx.issuer.endswith("/"):
                _uri = "{}{}".format(_cntx.issuer,
                                     self.kwargs["post_logout_uri_path"])
            else:
                _uri = "{}/{}".format(_cntx.issuer,
                                      self.kwargs["post_logout_uri_path"])
            plur = False
        else:
            plur = True
            verify_uri(_cntx,
                       request,
                       "post_logout_redirect_uri",
                       client_id=client_id)

        payload = {
            "sid": _sid,
            "client_id": client_id,
            "user": session["authn_event"]["uid"],
        }

        # redirect user to OP logout verification page
        if plur and "state" in request:
            _uri = "{}?{}".format(_uri, urlencode({"state": request["state"]}))
            payload["state"] = request["state"]

        payload["redirect_uri"] = _uri

        logger.debug("JWS payload: {}".format(payload))
        # From me to me
        _jws = JWT(
            _cntx.keyjar,
            iss=_cntx.issuer,
            lifetime=86400,
            sign_alg=self.kwargs["signing_alg"],
        )
        sjwt = _jws.pack(payload=payload, recv=_cntx.issuer)

        location = "{}?{}".format(self.kwargs["logout_verify_url"],
                                  urlencode({"sjwt": sjwt}))
        return {"redirect_location": location}