Пример #1
0
    def response(self, binding, http_args, query):
        cookie = self.create_cookie(
            '{"'
            + self.CONST_QUERY
            + '": "'
            + base64.b64encode(query.encode("ascii")).decode("ascii")
            + '" , "'
            + self.CONST_HASIDP
            + '": "True" }',
            self.CONST_SAML_COOKIE,
            self.CONST_SAML_COOKIE,
        )
        if binding == BINDING_HTTP_ARTIFACT:
            resp = SeeOther()  # type: Response
        elif binding == BINDING_HTTP_REDIRECT:
            for param, value in http_args["headers"]:
                if param == "Location":
                    resp = SeeOther(str(value), headers=[cookie])
                    break
            else:
                raise ServiceErrorException("Parameter error")
        else:
            http_args["headers"].append(cookie)
            resp = Response(http_args["data"], headers=http_args["headers"])

        return resp
Пример #2
0
    def verify(self, request, **kwargs):
        """
        Verifies that the given totp was correct
        :param request: Either the query part of a URL a urlencoded
        body of a HTTP message or a parse such.
        :param kwargs: Catch whatever else is sent.
        :return: redirect back to where ever the base applications
        wants the user after authentication.
        """
        if isinstance(request, six.string_types):
            _dict = parse_qs(request)
        elif isinstance(request, dict):
            _dict = request
        else:
            raise ValueError("Wrong type of input")

        # verify totp
        try:
            # Do verification
            totp_generator = pyotp.TOTP(self.get_totp_secret_key(_dict["username"][0]))
            assert (True == totp_generator.verify(_dict["totp"][0]))
        except (AssertionError, KeyError):
            resp = Unauthorized("Wrong TOTP")
            ##resp = Unauthorized("Unknown user or wrong password")

            kwargs["request"] = request
            kwargs["form_action"] = kwargs["url"]
            argv = self.templ_arg_func(0, **kwargs)
            argv['wrong_value'] = 1
            argv['form_action'] = kwargs["baseurl"] + "/totp_login"
            argv['username'] = _dict['username'][0]
            argv['acr'] = argv['form_action']
            argv['title'] = 'TOTP verification'

            self.nerror = self.nerror + 1
            if (self.nerror>=3):
                self.nerror = 0
                argv['wrong_value'] = 4

            mte = self.template_lookup.get_template('totp_form.mako')
            resp.message = mte.render(**argv).decode("utf-8")
            return resp, False

        else:
            # If I remove this header, authentication enters in a infinite loop.
            headers = [self.create_cookie(_dict["username"][0], "upm")]
            try:
                _qp = _dict["query"][0]
            except KeyError:
                _qp = self.get_multi_auth_cookie(kwargs['cookie'])
            try:
                return_to = self.generate_return_url(kwargs["return_to"], _qp)
            except KeyError:
                try:
                    return_to = self.generate_return_url(self.return_to, _qp,
                                                         kwargs["path"])
                except KeyError:
                    return_to = self.generate_return_url(self.return_to, _qp)

            return SeeOther(return_to, headers=headers), True
Пример #3
0
    def create_redirect(self, query):
        """
        Performs the redirect to the CAS server.

        :rtype : Response
        :param query: All query parameters to be added to the return_to URL
        after successful authentication.
        :return: A redirect response to the CAS server.
        """
        try:
            req = parse_qs(query)
            acr = req['acr_values'][0]
        except KeyError:
            acr = None

        nonce = uuid.uuid4().get_urn()
        service_url = urlencode(
            {self.CONST_SERVICE: self.get_service_url(nonce, acr)})
        cas_url = self.cas_server + self.CONST_CASLOGIN + service_url
        cookie = self.create_cookie(
            '{"' + self.CONST_NONCE + '": "' + base64.b64encode(
                nonce) + '", "' +
            self.CONST_QUERY + '": "' + base64.b64encode(query) + '"}',
            self.CONST_CAS_COOKIE,
            self.CONST_CAS_COOKIE)
        return SeeOther(cas_url, headers=[cookie])
Пример #4
0
 def _wayf_redirect(self, cookie):
     sid_ = sid()
     self.cache_outstanding_queries[sid_] = self.verification_endpoint
     return (
         -1,
         SeeOther(
             headers=[("Location", "%s?%s" % (self.sp_conf.WAYF, sid_)), cookie]
         ),
     )
Пример #5
0
    def verify(self, request, **kwargs):
        """
        Verifies that the given username and password was correct
        :param request: Either the query part of a URL a urlencoded
        body of a HTTP message or a parse such.
        :param kwargs: Catch whatever else is sent.
        :return: redirect back to where ever the base applications
        wants the user after authentication.
        """

        logger.debug("verify(%s)" % sanitize(request))
        if isinstance(request, six.string_types):
            _dict = compact(parse_qs(request))
        elif isinstance(request, dict):
            _dict = request
        else:
            raise ValueError("Wrong type of input")

        logger.debug("dict: %s" % sanitize(_dict))
        # verify username and password
        try:
            self._verify(_dict["password"], _dict["login"])  # dict origin
        except TypeError:
            try:
                self._verify(_dict["password"][0], _dict["login"][0])
            except (AssertionError, KeyError) as err:
                logger.debug("Password verification failed: {}".format(err))
                resp = Unauthorized("Unknown user or wrong password")
                return resp, False
            else:
                try:
                    _qp = _dict["query"]
                except KeyError:
                    _qp = self.get_multi_auth_cookie(kwargs['cookie'])
        except (AssertionError, KeyError) as err:
            logger.debug("Password verification failed: {}".format(err))
            resp = Unauthorized("Unknown user or wrong password")
            return resp, False
        else:
            try:
                _qp = _dict["query"]
            except KeyError:
                _qp = self.get_multi_auth_cookie(kwargs['cookie'])

        logger.debug("Password verification succeeded.")
        # if "cookie" not in kwargs or self.srv.cookie_name not in kwargs["cookie"]:
        headers = [self.create_cookie(_dict["login"], "upm")]
        try:
            return_to = self.generate_return_url(kwargs["return_to"], _qp)
        except KeyError:
            try:
                return_to = self.generate_return_url(self.return_to, _qp,
                                                     kwargs["path"])
            except KeyError:
                return_to = self.generate_return_url(self.return_to, _qp)

        return SeeOther(return_to, headers=headers), True
Пример #6
0
def application(environ, start_response):
    session = environ['beaker.session']

    path = environ.get('PATH_INFO', '').lstrip('/')
    if path == "robots.txt":
        return static(environ, start_response, "static/robots.txt")

    if path.startswith("static/"):
        return static(environ, start_response, path)

    if path == "logout":
        session.invalidate()
        resp = SeeOther("static/log_out_message.html")
        return resp(environ, start_response)

    if path == "as":
        session["callback"] = True
        request = parse_qs(get_or_post(environ))
        _cli = CONSUMER[unquote(request["authzsrv"][0])]
        session["client"] = _cli
        resp = SeeOther(_cli.begin(RP_CONF.BASE, path))
        return resp(environ, start_response)

    if path == "rp":
        session["callback"] = True
        request = parse_qs(get_or_post(environ))
        _cli = CONSUMER[unquote(request["iss"][0])]
        session["client"] = _cli
        resp = SeeOther(_cli.begin(RP_CONF.BASE, path))
        return resp(environ, start_response)

    if path == "authz_cb":
        _cli = session["client"]
        request = get_or_post(environ)
        aresp = _cli.handle_authorization_response(request)
        rargs = {"code": aresp["code"]}
        atresp = _cli.do_access_token_request(request_args=rargs)
        #extra_args=None, http_args=None,)
        # Access token should be stored somewhere for later usage
        Token[atresp["state"]] = atresp
        resp = Response("Got access token: %s" % atresp["access_token"])
        return resp(environ, start_response)

    return as_choice(environ, start_response)
Пример #7
0
def redirect_authz_error(error, redirect_uri, descr=None, state="", return_type=None):
    err = AuthorizationErrorResponse(error=error)
    if descr:
        err["error_description"] = descr
    if state:
        err["state"] = state
    if return_type is None or return_type == ["code"]:
        location = err.request(redirect_uri)
    else:
        location = err.request(redirect_uri, True)
    return SeeOther(location)
Пример #8
0
    def handle_authn_response(self, context, internal_resp):
        """
        See super class method satosa.frontends.base.FrontendModule#handle_authn_response
        :type context: satosa.context.Context
        :type internal_response: satosa.internal_data.InternalResponse
        :rtype oic.utils.http_util.Response
        """
        auth_req = self._get_authn_request_from_state(context.state)

        # filter attributes to return in ID Token as claims
        attributes = self.converter.from_internal(
            "openid", internal_resp.get_attributes())
        satosa_logging(
            LOGGER, logging.DEBUG,
            "Attributes delivered by backend to OIDC frontend: {}".format(
                json.dumps(attributes)), context.state)
        flattened_attributes = {k: v[0] for k, v in attributes.items()}
        requested_id_token_claims = auth_req.get("claims", {}).get("id_token")
        user_claims = self._get_user_info(flattened_attributes,
                                          requested_id_token_claims,
                                          auth_req["scope"])
        satosa_logging(
            LOGGER, logging.DEBUG,
            "Attributes filtered by requested claims/scope: {}".format(
                json.dumps(user_claims)), context.state)

        # construct epoch timestamp of reported authentication time
        auth_time = datetime.datetime.strptime(
            internal_resp.auth_info.timestamp, "%Y-%m-%dT%H:%M:%SZ")
        epoch_timestamp = (auth_time -
                           datetime.datetime(1970, 1, 1)).total_seconds()

        base_claims = {
            "client_id": auth_req["client_id"],
            "sub": internal_resp.get_user_id(),
            "nonce": auth_req["nonce"]
        }
        id_token = self.provider.id_token_as_signed_jwt(
            base_claims,
            user_info=user_claims,
            auth_time=epoch_timestamp,
            loa="",
            alg=self.sign_alg)

        oidc_client_state = auth_req.get("state")
        kwargs = {}
        if oidc_client_state:  # inlcude any optional 'state' sent by the client in the authn req
            kwargs["state"] = oidc_client_state

        auth_resp = AuthorizationResponse(id_token=id_token, **kwargs)
        http_response = auth_resp.request(
            auth_req["redirect_uri"], self._should_fragment_encode(auth_req))
        return SeeOther(http_response)
Пример #9
0
    def verify(self, request, cookie, **kwargs):
        """
        Verify if the authentication was successful.

        :rtype : Response
        :param request: Contains the request parameters.
        :param cookie: Cookies sent with the request.
        :param kwargs: Any other parameters.
        :return: If the authentication was successful: a redirect to the
        return_to url. Otherwise a unauthorized response.
        :raise: ValueError
        """
        logger.debug("verify(%s)" % request)
        if isinstance(request, str):
            _dict = parse_qs(request)
        elif isinstance(request, dict):
            _dict = request
        else:
            raise ValueError("Wrong type of input")
        try:
            cas_cookie, _ts, _typ = self.getCookieValue(
                cookie, self.CONST_CAS_COOKIE)
            data = json.loads(cas_cookie)
            nonce = base64.b64decode(data[self.CONST_NONCE])
            if nonce != _dict[self.CONST_NONCE][0]:
                logger.warning(
                    "Someone tried to login without a correct nonce!")
                return Unauthorized("You are not authorized!")
            acr = None
            try:
                acr = _dict["acr_values"][0]
            except KeyError:
                pass
            uid = self.handle_callback(_dict[self.CONST_TICKET],
                                       self.get_service_url(nonce, acr))
            if uid is None or uid == "":
                logger.info("Someone tried to login, but was denied by CAS!")
                return Unauthorized("You are not authorized!")
            cookie = self.create_cookie(uid, "casm")
            return_to = self.generate_return_url(self.return_to, uid)
            if "?" in return_to:
                return_to += "&"
            else:
                return_to += "?"
            return_to += base64.b64decode(data[self.CONST_QUERY])
            return SeeOther(return_to, headers=[cookie])
        except Exception:
            # FIXME: This should catch specific exception thrown from methods in the block
            logger.critical(
                "Metod verify in user_cas.py had a fatal exception.",
                exc_info=True)
            return Unauthorized("You are not authorized!")
Пример #10
0
    def wrapper(environ, start_response):
        data = get_post(environ)
        kwargs = dict(urlparse.parse_qsl(data))
        kwargs["state"] = json.loads(urlparse.unquote(kwargs["state"]))
        val, completed = verifier.verify(**kwargs)
        if not completed:
            return val(environ, start_response)
        if val:
            set_cookie, cookie_value = verifier.create_cookie(val, "auth")
            cookie_value += "; path=/"

            url = "{base_url}?{query_string}".format(
                base_url="/authorization",
                query_string=kwargs["state"]["query"])
            response = SeeOther(url, headers=[(set_cookie, cookie_value)])
            return response(environ, start_response)
        else:  # Unsuccessful authentication
            url = "{base_url}?{query_string}".format(
                base_url="/authorization",
                query_string=kwargs["state"]["query"])
            response = SeeOther(url)
            return response(environ, start_response)
Пример #11
0
 def handle_backend_error(self, exception):
     """
     See super class satosa.frontends.base.FrontendModule
     :type exception: satosa.exception.SATOSAError
     :rtype: oic.utils.http_util.Response
     """
     auth_req = self._get_authn_request_from_state(exception.state)
     error_resp = AuthorizationErrorResponse(
         error="access_denied", error_description=exception.message)
     satosa_logging(LOGGER, logging.DEBUG, exception.message,
                    exception.state)
     return SeeOther(
         error_resp.request(auth_req["redirect_uri"],
                            self._should_fragment_encode(auth_req)))
Пример #12
0
def clear_log(path, environ, start_response, lookup):
    # verify that the path is reasonable
    head, tail = os.path.split(path)
    if head != 'clear':  # don't do anything
        resp = NotFound(environ["PATH_INFO"])
        return resp(environ, start_response)

    wd = os.getcwd()
    _dir = os.path.join(wd, 'log', tail)
    if os.path.isdir(_dir):
        create_rp_tar_archive(tail, True)
        shutil.rmtree(_dir)
    else:
        resp = NotFound('No logfile by the name "{}"'.format(tail))
        return resp(environ, start_response)

    resp = SeeOther('/log')
    return resp(environ, start_response)
Пример #13
0
    def run_test(self, tester, _path, _sid, environ, start_response):
        _op = '{} {}'.format(environ['REQUEST_METHOD'], _path)
        resp = tester.run(_path, sid=_sid, op=_op, **self.kwargs)
        if resp:
            logger.info('Response class: {}'.format(resp.__class__.__name__))

        if isinstance(resp, requests.Response):
            try:
                loc = resp.headers['location']
            except KeyError:
                logger.info('Response type: {}, missing location'.format(
                    type(resp)))
                resp = ServiceError('Wrong response: {}:{}'.format(
                    resp.status_code, resp.text))
                return resp(environ, start_response), 0
            else:
                try:
                    tester.conv.events.store('Cookie',
                                             resp.headers['set-cookie'])
                except KeyError:
                    pass
                # For me !
                if loc.startswith(tester.base_url):
                    _path = loc[len(tester.base_url):]
                    if _path[0] == '/':
                        _path = _path[1:]
                    return 0, _path
                else:
                    if self.internal:
                        _url = absolute_url(
                            loc, tester.sh['test_conf']['start_page'])
                        logging.info('Redirect not to me => {}'.format(_url))
                        res = tester.conv.entity.server.http_request(_url)
                        logging.info('{} response'.format(res.status_code))
                        logging.debug('txt: {}'.format(res.text))
                        res = tester.display_test_list()
                        return res, 0
                    else:
                        res = SeeOther(loc)
                        return res(environ, start_response), 0
        elif resp is True or resp is False or resp is None:
            return tester.display_test_list(), 0
        else:
            return resp(environ, start_response), 0
Пример #14
0
 def run(self, **kwargs):
     self.conv.events.store('start_page', self.start_page)
     if self.internal:
         res = self.conv.entity.server.http_request(self.start_page)
     else:
         res = SeeOther(self.start_page)
         return res
     self.conv.events.store(EV_HTTP_RESPONSE, res)
     if res.status_code in [302, 303]:
         loc = res.headers['location']
         try:
             self.conv.events.store('Cookie', res.headers['set-cookie'])
         except KeyError:
             pass
         logger.info('Redirect to {}'.format(loc))
         logger.debug('msg: {}'.format(res.text))
         self.conv.events.store(EV_REDIRECT_URL, loc, sub='init')
     elif res.status_code >= 400:
         logger.info('Error {}'.format(res.text))
         raise OperationError('Error response on HTTP request')
     return res
Пример #15
0
    def verify(self, request, **kwargs):
        """
        Verifies that the given username and password was correct
        :param request: Either the query part of a URL a urlencoded
        body of a HTTP message or a parse such.
        :param kwargs: Catch whatever else is sent.
        :return: redirect back to where ever the base applications
        wants the user after authentication.
        """

        logger.debug("verify(%s)" % request)
        if isinstance(request, six.string_types):
            _dict = parse_qs(request)
        elif isinstance(request, dict):
            _dict = request
        else:
            raise ValueError("Wrong type of input")

        logger.debug("dict: %s" % _dict)
        logger.debug("passwd: %s" % self.passwd)
        # verify username and password
        try:
            assert _dict['login_parameter'][0] == 'logged_in'
        except (AssertionError, KeyError):
            resp = Unauthorized(
                "You are not authorized. Javascript not executed")
            return resp, False
        else:
            cookie = self.create_cookie("diana", "upm")
            try:
                _qp = _dict["query"][0]
            except KeyError:
                _qp = self.get_multi_auth_cookie(kwargs['cookie'])
            try:
                return_to = self.generate_return_url(kwargs["return_to"], _qp)
            except KeyError:
                return_to = self.generate_return_url(self.return_to, _qp)
            resp = SeeOther(return_to, headers=[cookie])

        return resp, True
Пример #16
0
    def authz_part2(self, user, areq, sid, **kwargs):
        """
        After the authentication this is where you should end up

        :param user:
        :param areq: The Authorization Request
        :param sid: Session key
        :param kwargs: possible other parameters
        :return: A redirect to the redirect_uri of the client
        """
        result = self._complete_authz(user, areq, sid, **kwargs)
        if isinstance(result, Response):
            return result
        else:
            aresp, headers, redirect_uri, fragment_enc = result

        # Mix-Up mitigation
        aresp['iss'] = self.baseurl
        aresp['client_id'] = areq['client_id']

        # Just do whatever is the default
        location = aresp.request(redirect_uri, fragment_enc)
        logger.debug("Redirected to: '%s' (%s)" % (location, type(location)))
        return SeeOther(str(location), headers=headers)
Пример #17
0
def application(environ, start_response):
    session = environ['beaker.session']
    path = environ.get('PATH_INFO', '').lstrip('/')
    if path == "robots.txt":
        return static(environ, start_response, LOGGER, "static/robots.txt")
    elif path.startswith("static/"):
        return static(environ, start_response, LOGGER, path)
    elif '/static/' in path:
        pre, post = path.split('static')
        return static(environ, start_response, LOGGER, 'static' + post)

    query = parse_qs(environ["QUERY_STRING"])
    acr_values = session._params['acrs']
    clients = session._params['clients']
    server_env = session._params['server_env']

    LOGGER.info(50 * "=")
    LOGGER.info("[{}] path: {}".format(session.id, path))
    LOGGER.info(50 * "=")

    if path == '':
        if 'access_token' not in session:
            return opchoice(environ, start_response, clients)
        else:
            client = clients[session["op"]]
            # check_session_iframe_url = None
            try:
                # check_session_iframe_url = client.provider_info[
                #     "check_session_iframe"]

                session["session_management"] = {
                    "session_state": query["session_state"][0],
                    "client_id": client.client_id,
                    "issuer": client.provider_info["issuer"]
                }
            except KeyError:
                pass

            kwargs = dict([(p, session[p])
                           for p in ['id_token', 'userinfo', 'user_id']
                           if p in session])

            return opresult(environ, start_response, **kwargs)
    elif path == "rp":  # After having chosen which OP to authenticate at
        if "uid" in query:
            try:
                client = clients.dynamic_client(userid=query["uid"][0])
            except (ConnectionError, OIDCError) as err:
                return operror(environ, start_response, '{}'.format(err))
        elif 'issuer' in query:
            try:
                client = clients[query["issuer"][0]]
            except (ConnectionError, OIDCError) as err:
                return operror(environ, start_response, '{}'.format(err))
        else:
            client = clients[query["op"][0]]

        client.get_userinfo = session._params['userinfo']
        try:
            client.resource_server = session._params['resource_server']
        except KeyError:
            pass

        try:
            session['response_format'] = query["response_format"][0]
        except KeyError:
            session['response_format'] = 'html'

        session["op"] = client.provider_info["issuer"]

        try:
            resp = client.create_authn_request(session, acr_values)
        except Exception as err:
            logging.error(err)
            raise
        else:
            return resp(environ, start_response)
    elif path.endswith('authz_post'):
        try:
            _iss = session['op']
        except KeyError:
            LOGGER.info('[{}] No active session with {}'.format(
                session.id, environ['REMOTE_ADDR']))
            return opchoice(environ, start_response, clients)
        else:
            client = clients[_iss]

        query = parse_qs(get_post(environ))
        try:
            info = query["fragment"][0]
        except KeyError:
            return sorry_response(environ, start_response, conf.BASE,
                                  "missing fragment ?!")
        if info == ['x']:
            return sorry_response(environ, start_response, conf.BASE,
                                  "Expected fragment didn't get one ?!")

        LOGGER.info('[{}] Fragment part: {}'.format(session.id, info))

        try:
            result = client.callback(info, session, 'urlencoded')
            if isinstance(result, SeeOther):
                return result(environ, start_response)
        except OIDCError as err:
            return operror(environ, start_response, "%s" % err)
        except Exception as err:
            raise
        else:
            session.update(result)
            res = SeeOther(server_env['base_url'])
            return res(environ, start_response)
    elif path in clients.return_paths(
    ):  # After having authenticated at the OP
        try:
            _iss = session['op']
        except KeyError:
            LOGGER.info('[{}]No active session with {}'.format(
                session.id, environ['REMOTE_ADDR']))
            return opchoice(environ, start_response, clients)

        # mismatch between callback and return_uri
        # ignore trailing '/'
        if not url_eq(_iss, clients.path[path]):
            LOGGER.warning('[{}]issuer mismatch: {} != {}'.format(
                session.id, _iss, clients.path[path]))
            return operror(environ, start_response, "%s" % 'Not allowed')

        client = clients[clients.path[path]]

        _response_type = client.behaviour["response_type"]
        try:
            _response_mode = client.authz_req[
                session['state']]['response_mode']
        except KeyError:
            _response_mode = ''

        LOGGER.info("[{}]response_type: {}, response_mode: {}".format(
            session.id, _response_type, _response_mode))
        if _response_type and _response_type != "code":
            # Fall through if it's a query response anyway
            if query:
                pass
            elif _response_mode:
                # form_post encoded
                pass
            else:
                return opresult_fragment(environ, start_response)

        LOGGER.info("[{}]Query part: {}".format(session.id, query))

        try:
            result = client.callback(query, session)
            if isinstance(result, SeeOther):
                return result(environ, start_response)
        except OIDCError as err:
            return operror(environ, start_response, "%s" % err)
        except Exception:
            raise
        else:
            session.update(result)
            res = SeeOther(server_env['base_url'])
            return res(environ, start_response)
    elif path == "logout":  # After the user has pressed the logout button
        try:
            _iss = session['op']
        except KeyError:
            LOGGER.info('[{}]No active session with {}'.format(
                session.id, environ['REMOTE_ADDR']))
            return opchoice(environ, start_response, clients)
        client = clients[_iss]
        try:
            del client.authz_req[session['state']]
        except KeyError:
            pass

        logout_url = client.end_session_endpoint
        try:
            # Specify to which URL the OP should return the user after
            # log out. That URL must be registered with the OP at client
            # registration.
            logout_url += "?" + urlencode({
                "post_logout_redirect_uri":
                client.registration_response["post_logout_redirect_uris"][0]
            })
        except KeyError:
            pass
        else:
            # If there is an ID token send it along as a id_token_hint
            _idtoken = get_id_token(client, session)
            if _idtoken:
                logout_url += "&" + urlencode({
                    "id_token_hint":
                    id_token_as_signed_jwt(client, _idtoken, "HS256")
                })
            # Also append the ACR values
            logout_url += "&" + urlencode({"acr_values": acr_values}, True)

        LOGGER.debug("[{}]Logout URL: {}".format(session.id, logout_url))
        LOGGER.debug("Logging out from session: [{}]".format(session.id))
        session.delete()
        resp = SeeOther(str(logout_url))
        return resp(environ, start_response)
    elif path == "logout_success":  # post_logout_redirect_uri
        return Response("Logout successful!")(environ, start_response)
    elif path == "session_iframe":  # session management
        kwargs = session["session_management"]
        resp = Response(mako_template="rp_session_iframe.mako",
                        template_lookup=LOOKUP)
        return resp(environ,
                    start_response,
                    session_change_url="{}session_change".format(
                        server_env["base_url"]),
                    **kwargs)
    elif path == "session_change":
        try:
            _iss = session['op']
        except KeyError:
            LOGGER.info('[{}]No active session with {}'.format(
                session.id, environ['REMOTE_ADDR']))
            return opchoice(environ, start_response, clients)

        try:
            client = clients[_iss]
        except KeyError:
            return Response("No valid session.")(environ, start_response)

        kwargs = {"prompt": "none"}
        # If there is an ID token send it along as a id_token_hint
        idt = get_id_token(client, session)
        if idt:
            kwargs["id_token_hint"] = id_token_as_signed_jwt(
                client, idt, "HS256")
        resp = client.create_authn_request(session, acr_values, **kwargs)
        return resp(environ, start_response)

    return opchoice(environ, start_response, clients)
Пример #18
0
def application(environ, start_response):
    session = Session(environ['beaker.session'])

    path = environ.get('PATH_INFO', '').lstrip('/')
    if path == "robots.txt":
        return static(environ, start_response, LOGGER, "static/robots.txt")

    if path.startswith("static/"):
        return static(environ, start_response, LOGGER, path)

    query = parse_qs(environ["QUERY_STRING"])

    if path == "logout":
        try:
            logoutUrl = session['client'].end_session_endpoint
            plru = "{}post_logout".format(SERVER_ENV["base_url"])
            logoutUrl += "?" + urlencode({"post_logout_redirect_uri": plru})
            try:
                logoutUrl += "&" + urlencode({
                    "id_token_hint": id_token_as_signed_jwt(
                        session['client'], "HS256")})
            except AttributeError as err:
                pass
            session.clear()
            resp = SeeOther(str(logoutUrl))
            return resp(environ, start_response)
        except Exception as err:
            pass

    if path == "post_logout":
        return post_logout(environ, start_response)

    if session['callback']:
        _uri = "%s%s" % (conf.BASE, path)
        for _cli in SERVER_ENV["OIC_CLIENT"].values():
            if _uri in _cli.redirect_uris:
                session['callback'] = False
                func = getattr(RP, "callback")
                return func(environ, SERVER_ENV, start_response, query, session)

    if path == "rpAcr":
        return choose_acr_value(environ, start_response, session)

    if path == "rpAuth":
    # Only called if multiple arc_values (that is authentications) exists.
        if "acr" in query and query["acr"][0] in session['acr_values']:
            func = getattr(RP, "create_authnrequest")
            return func(environ, SERVER_ENV, start_response, session,
                        query["acr"][0])

    if session["client"] is not None:
        session['callback'] = True
        func = getattr(RP, "begin")
        return func(environ, SERVER_ENV, start_response, session, "")

    if path == "rp":
        if "uid" in query:
            try:
                link = RP.find_srv_discovery_url(resource=query["uid"][0])
            except requests.ConnectionError:
                resp = ServiceError("Webfinger lookup failed, connection error")
                return resp(environ, start_response)

            RP.srv_discovery_url = link
            md5 = hashlib.md5()
            md5.update(link.encode("utf-8"))
            opkey = base64.b16encode(md5.digest()).decode("utf-8")
            session['callback'] = True
            func = getattr(RP, "begin")
            return func(environ, SERVER_ENV, start_response, session, opkey)

    return opbyuid(environ, start_response)
Пример #19
0
    def application(self, environ, start_response):
        session = environ['beaker.session']

        jlog = JLog(logger, session.id)
        path = environ.get('PATH_INFO', '').lstrip('/')
        jlog.info({"remote_addr": environ["REMOTE_ADDR"], "path": path})

        # self.events.store(EV_REQUEST, path)

        try:
            sh = session['session_info']
        except KeyError:
            sh = SessionHandler(**self.kwargs)
            #sh.session_init()
            session['session_info'] = sh

        info = WebIh(session=sh, **self.kwargs)
        info.environ = environ
        info.start_response = start_response

        tester = WebTester(info, sh, **self.kwargs)

        if 'path' in self.kwargs and path.startswith(self.kwargs['path']):
            _path = path[len(kwargs['path']) + 1:]
        else:
            _path = path

        if _path == "robots.txt":
            return static_mime("static/robots.txt", environ, start_response)
        elif _path.startswith("static/"):
            return static_mime(_path, environ, start_response)

        if _path == "list":
            try:
                qs = parse_qs(get_or_post(environ))
            except Exception as err:
                jlog.error({'message': err})
                qs = {}
            else:
                if qs:
                    sh['test_conf'] = dict([(k, v[0]) for k, v in qs.items()])
                    # self.session_conf[sh['sid']] = sh
                else:
                    return self.init_session(tester, sh)

                logger.info('test_conf: {}'.format(sh['test_conf']))

                if 'start_page' not in sh['test_conf']:
                    resp = BadRequest('You MUST provide a start_page')
                    return resp(environ, start_response)

            info.profile = tester.sh.profile = qs['response_type'][0]
            sh.session_init()

            if 'test_id' in qs:
                (res, _path) = self.run_test(tester, qs['test_id'][0],
                                             sh['sid'], environ,
                                             start_response)
                if res:
                    return res
            else:
                res = tester.display_test_list()
                return res
        elif _path == '' or _path == 'config':
            return self.init_session(tester, sh)
        elif _path in self.kwargs['flows'].keys():  # Run flow
            # Will use the same test configuration
            try:
                _ = tester.sh['test_conf']
            except KeyError:
                return self.init_session(tester, sh)

            try:
                _sid = tester.sh['sid']
            except KeyError:
                _sid = self.store_session_handler(sh)

            # First time around this should not be set
            try:
                _ = self.session_conf[_sid]['flow']
            except KeyError:
                pass
            else:
                return self.init_session(tester, sh, _path)

            (res, _path) = self.run_test(tester, _path, _sid, environ,
                                         start_response)
            if res:
                return res
        elif _path == 'display':
            return info.flow_list()
        elif _path == "opresult":
            try:
                _display_path = '/{}/display'.format(self.kwargs['path'])
            except KeyError:
                _display_path = '/display'
            resp = SeeOther("{}#{}".format(_display_path,
                                           self.pick_grp(sh['conv'].test_id)))
            return resp(environ, start_response)
        elif _path.startswith("test_info"):
            p = _path.split("/")
            try:
                return info.test_info(p[1])
            except KeyError:
                return info.not_found()
        elif _path == 'all':
            for test_id in sh['flow_names']:
                resp = tester.run(test_id, **self.kwargs)
                if resp is True or resp is False:
                    continue
                elif resp:
                    return resp(environ, start_response)
                else:
                    resp = ServiceError('Unkown service error')
                    return resp(environ, start_response)
            return tester.display_test_list()

        # Whatever gets here should be of the form <session_id>/<path>
        try:
            sid, _path = _path.split('/', 1)
        except ValueError:
            pass
        else:
            if _path.startswith("static/"):
                return static_mime(_path, environ, start_response)

            try:
                _sh = self.session_conf[sid]
            except KeyError:
                resp = ServiceError("Unknown session")
                return resp(environ, start_response)

            tester.sh = _sh
            if 'HTTP_AUTHORIZATION' in environ:
                _sh['conv'].events.store('HTTP_AUTHORIZATION',
                                         environ['HTTP_AUTHORIZATION'])
            _p = _path.split('?')
            _sh['conv'].events.store(
                'http request', '{} /{}'.format(environ['REQUEST_METHOD'],
                                                _path))
            if _p[0] in _sh['conv'].entity.endpoints():
                resp = self.handle(environ, tester, sid, *_p)
                self.session_conf[sid] = tester.sh
                # The only redirect should be the one to the redirect_uri
                if isinstance(resp, SeeOther):
                    if self.internal:
                        # res = self.see_other_to_get(resp, sh)
                        # res is probably a redirect
                        # send the user back to the test list page
                        return info.flow_list()
                    else:
                        return resp(environ, start_response)
                elif isinstance(resp, Response):
                    return resp(environ, start_response)
                else:
                    return resp

            for endpoint, service in self.endpoints.items():
                if _path == endpoint:
                    jlog.info({"service": service})
                    try:
                        resp = self.handle(environ, tester, sid, service)
                        return resp(environ, start_response)
                    except Exception as err:
                        print("%s" % err)
                        message = traceback.format_exception(*sys.exc_info())
                        print(message)
                        jlog.exception(err)
                        resp = ServiceError("%s" % err)
                        return resp(environ)

        jlog.debug({"unknown side": path})
        resp = NotFound("Couldn't find the side you asked for!")
        return resp(environ, start_response)
Пример #20
0
    def _pick_idp(self, query):
        """
        If more than one idp and if none is selected, I have to do wayf or
        disco
        """
        query_dict = {}
        if isinstance(query, basestring):
            query_dict = dict(parse_qs(query))
        else:
            for key, value in query.iteritems():
                if isinstance(value, list):
                    query_dict[key] = value[0]
                else:
                    query_dict[key] = value
            query = urlencode(query_dict)

        _cli = self.sp
        # Find all IdPs
        idps = self.sp.metadata.with_descriptor("idpsso")

        idp_entity_id = None

        if len(idps) == 1:
            # idps is a dictionary
            idp_entity_id = idps.keys()[0]

        if not idp_entity_id and query:
            try:
                _idp_entity_id = query_dict[self.idp_query_param][0]
                if _idp_entity_id in idps:
                    idp_entity_id = _idp_entity_id
            except KeyError:
                logger.debug("No IdP entity ID in query: %s" % query)
                pass

        if not idp_entity_id:
            cookie = self.create_cookie('{"' + self.CONST_QUERY + '": "' + base64.b64encode(query) +
                                        '" , "' + self.CONST_HASIDP + '": "False" }',
                                        self.CONST_SAML_COOKIE, self.CONST_SAML_COOKIE)
            if self.sp_conf.WAYF:
                if query:
                    try:
                        wayf_selected = query_dict["wayf_selected"][0]
                    except KeyError:
                        return self._wayf_redirect(cookie)
                    idp_entity_id = wayf_selected
                else:
                    return self._wayf_redirect(cookie)
            elif self.sp_conf.DISCOSRV:
                if query:
                    idp_entity_id = _cli.parse_discovery_service_response(query=query)
                if not idp_entity_id:
                    sid_ = sid()
                    self.cache_outstanding_queries[sid_] = self.verification_endpoint
                    eid = _cli.config.entityid
                    ret = _cli.config.getattr("endpoints", "sp")["discovery_response"][0][0]
                    ret += "?sid=%s" % sid_
                    loc = _cli.create_discovery_service_request(self.sp_conf.DISCOSRV, eid, **{"return": ret})
                    return -1, SeeOther(loc, headers=[cookie])
            elif not len(idps):
                raise ServiceErrorException('Misconfiguration for the SAML Service Provider!')
            else:
                return -1, NotImplemented("No WAYF or DS present!")
        return 0, idp_entity_id
Пример #21
0
    def application(self, environ, start_response):
        logger.info("Connection from: %s" % environ["REMOTE_ADDR"])

        path = environ.get('PATH_INFO', '').lstrip('/')
        logger.info("path: %s" % path)

        _io = IO(rest=self.rest,
                 environ=environ,
                 start_response=start_response,
                 lookup=self.lookup)

        if path == "robots.txt":
            return _io.static("static/robots.txt")
        elif path == "favicon.ico":
            return _io.static("static/favicon.ico")
        elif path.startswith("static/"):
            return _io.static(path)
        elif path.startswith("export/"):
            return _io.static(path)

        if path == '':
            return _io.get_iss()
        elif path.startswith('form/'):
            return self.form_handling(path, _io)
        elif path == 'create':
            loc = self.basic_entity_configuration(_io)
            resp = SeeOther(loc)
            return resp(_io.environ, _io.start_response)
        elif path.startswith('run/'):
            _iss, _tag = get_iss_and_tag(path)
            if _iss == '' or _tag == '':
                resp = BadRequest('Path must be of the form /run/<iss>/<tag>')
                return resp(environ, start_response)
            _qiss = quote_plus(_iss)
            _qtag = quote_plus(_tag)
            _info = parse_qs(get_post(environ))
            ent_conf = expand_dict(_info)
            self.rest.write(_qiss, _qtag, ent_conf)
            resp = self.run_test_instance(_qiss, _qtag)
            if not isinstance(resp, Response):
                resp = SeeOther(resp)
            return resp(_io.environ, _io.start_response)
        elif path.startswith('model/'):
            p = path.split('/')
            prof = p[1]
            if verify_profile(prof):
                info = create_model(prof)
                if info:
                    res = Response(json.dumps(info), content='applicaton/json')
                else:
                    res = ServiceError()
            else:
                res = BadRequest('Syntax error in profile specification')
            return res(environ, start_response)
        else:
            # check if this a REST request
            _iss, _tag = get_iss_and_tag(path)
            _qiss = quote_plus(_iss)
            _qtag = quote_plus(_tag)
            _path = '/{}/{}'.format(_qiss, _qtag)
            _met = environ.get('REQUEST_METHOD')
            if _met == 'GET':
                resp = self.rest.read(_qiss, _qtag, _path)
            elif _met == 'POST':
                resp = self.rest.replace(_qiss, _qtag, get_post(environ),
                                         _path)
            elif _met == 'PUT':
                resp = self.rest.store(_qiss, _qtag, get_post(environ))
            elif _met == 'DELETE':
                resp = self.rest.delete(_qiss, _qtag)
            else:
                resp = BadRequest('Unsupported request method')

            return resp(environ, start_response)
Пример #22
0
    def application(self, environ, start_response):
        logger.info("Connection from: %s" % environ["REMOTE_ADDR"])
        session = environ['beaker.session']

        path = environ.get('PATH_INFO', '').lstrip('/')
        logger.info("path: %s" % path)
        self.events.store(EV_REQUEST, path)

        try:
            sh = session['session_info']
        except KeyError:
            sh = SessionHandler(**self.kwargs)
            sh.session_init()
            session['session_info'] = sh

        inut = WebIO(session=sh, **self.kwargs)
        inut.environ = environ
        inut.start_response = start_response

        tester = WebTester(inut, sh, **self.kwargs)

        if path == "robots.txt":
            return static_mime("static/robots.txt", environ, start_response)
        elif path.startswith("static/"):
            return static_mime(path, environ, start_response)
        elif path == "list":
            try:
                qs = parse_qs(get_post(environ))
            except Exception as err:
                pass
            else:
                sh['test_conf'] = dict([(k, v[0]) for k, v in qs.items()])
                self.session_conf[sh['sid']] = sh

            return tester.display_test_list()
        elif path == '' or path == 'config':
            sid = rndstr(24)
            sh['sid'] = sid
            try:
                args = sh['test_conf']
            except:
                args = {}
            return tester.do_config(sid, **args)
        elif path in self.kwargs['flows'].keys():  # Run flow
            try:
                _ = tester.sh['test_conf']
            except KeyError:
                resp = SeeOther('/')
                return resp(environ, start_response)
            try:
                _sid = tester.sh['sid']
            except KeyError:
                _sid = rndstr(24)
                tester.sh['sid'] = _sid
                self.session_conf[_sid] = sh

            resp = tester.run(path, sid=_sid, **self.kwargs)
            if isinstance(resp, requests.Response):
                loc = resp.headers['location']
                #tester.conv.events.store('Cookie', resp.headers['set-cookie'])
                if loc.startswith(tester.base_url):
                    path = loc[len(tester.base_url):]
                else:
                    return resp
            elif resp is True or resp is False or resp is None:
                return tester.display_test_list()
            else:
                return resp(environ, start_response)
        elif path == 'display':
            return inut.flow_list()
        elif path == "opresult":
            resp = SeeOther("/display#{}".format(
                self.pick_grp(sh['conv'].test_id)))
            return resp(environ, start_response)
        elif path.startswith("test_info"):
            p = path.split("/")
            try:
                return inut.test_info(p[1])
            except KeyError:
                return inut.not_found()
        elif path == 'all':
            for test_id in sh['flow_names']:
                resp = tester.run(test_id, **self.kwargs)
                if resp is True or resp is False:
                    continue
                elif resp:
                    return resp(environ, start_response)
                else:
                    resp = ServiceError('Unkown service error')
                    return resp(environ, start_response)
            return tester.display_test_list()

        # Whatever gets here should be of the form <session_id>/<path>
        try:
            sid, _path = path.split('/', 1)
        except ValueError:
            pass
        else:
            if _path.startswith("static/"):
                return static_mime(_path, environ, start_response)

            try:
                _sh = self.session_conf[sid]
            except KeyError:
                resp = ServiceError("Unknown session")
                return resp(environ, start_response)

            tester.sh = _sh
            if 'HTTP_AUTHORIZATION' in environ:
                _sh['conv'].events.store('HTTP_AUTHORIZATION',
                                         environ['HTTP_AUTHORIZATION'])
            _p = _path.split('?')
            if _p[0] in _sh['conv'].entity.endpoints():
                resp = self.handle(environ, tester, sid, *_p)
                self.session_conf[sid] = tester.sh
                return resp(environ, start_response)

            for endpoint, service in self.endpoints.items():
                if _path == endpoint:
                    logger.info("service: {}".format(service))
                    try:
                        resp = self.handle(environ, tester, sid, service)
                        return resp(environ, start_response)
                    except Exception as err:
                        print("%s" % err)
                        message = traceback.format_exception(*sys.exc_info())
                        print(message)
                        logger.exception("%s" % err)
                        resp = ServiceError("%s" % err)
                        return resp(environ)

        logger.debug("unknown side: %s" % path)
        resp = NotFound("Couldn't find the side you asked for!")
        return resp(environ, start_response)
Пример #23
0
    def verify(self,
               request,
               cookie,
               path,
               requrl,
               end_point_index=None,
               **kwargs):
        """
        Verifies if the authentication was successful.

        :rtype : Response
        :param request: Contains the request parameters.
        :param cookie: Cookies sent with the request.
        :param kwargs: Any other parameters.
        :return: If the authentication was successful: a redirect to the
        return_to url. Otherwise a unauthorized response.
        :raise: ValueError
        """
        if isinstance(request, six.string_types):
            request = parse_qs(request)
        elif isinstance(request, dict):
            pass
        else:
            raise ValueError("Wrong type of input")

        acs = self.sp.config.getattr("endpoints",
                                     "sp")["assertion_consumer_service"]
        acs_endpoints = [(ep[0].rsplit("/", 1)[1], ep[1]) for ep in acs]
        binding = None
        path = path[1:]
        for endp in acs_endpoints:
            if path == endp[0]:
                binding = endp[1]
                break

        saml_cookie, _ts, _typ = self.getCookieValue(cookie,
                                                     self.CONST_SAML_COOKIE)
        data = json.loads(saml_cookie)

        rp_query_cookie = self.get_multi_auth_cookie(cookie)

        query = rp_query_cookie

        if not query:
            query = base64.b64decode(data[self.CONST_QUERY]).decode("ascii")

        if data[self.CONST_HASIDP] == 'False':
            (done, response) = self._pick_idp(request, end_point_index)
            if done == 0:
                entity_id = response
                # Do the AuthnRequest
                resp = self._redirect_to_auth(self.sp, entity_id, query,
                                              end_point_index)
                return resp, False
            return response, False

        if not request:
            logger.info("Missing Response")
            return Unauthorized("You are not authorized!"), False

        try:
            response = self.sp.parse_authn_request_response(
                request["SAMLResponse"][0], binding,
                self.cache_outstanding_queries)
        except UnknownPrincipal as excp:
            logger.error("UnknownPrincipal: %s" % (excp, ))
            return Unauthorized(self.not_authorized), False
        except UnsupportedBinding as excp:
            logger.error("UnsupportedBinding: %s" % (excp, ))
            return Unauthorized(self.not_authorized), False
        except VerificationError as err:
            logger.error("Verification error: %s" % (err, ))
            return Unauthorized(self.not_authorized), False
        except Exception as err:
            logger.error("Other error: %s" % (err, ))
            return Unauthorized(self.not_authorized), False

        if self.sp_conf.VALID_ATTRIBUTE_RESPONSE is not None:
            for k, v in six.iteritems(self.sp_conf.VALID_ATTRIBUTE_RESPONSE):
                if k not in response.ava:
                    return Unauthorized(self.not_authorized), False
                else:
                    allowed = False
                    for allowed_attr_value in v:
                        if isinstance(response.ava[k], list):
                            for resp_value in response.ava[k]:
                                if allowed_attr_value in resp_value:
                                    allowed = True
                                    break
                        elif allowed_attr_value in response.ava[k]:
                            allowed = True
                            break
                    if not allowed:
                        return Unauthorized(self.not_authorized), False

        # logger.info("parsed OK")'
        uid = response.assertion.subject.name_id.text
        if self.userinfo == "AA":
            if response.entity_id is not None and self.samlcache is not None:
                self.samlcache["AA_ENTITYID"] = response.entity_id
        self.setup_userdb(uid, response.ava)

        return_to = create_return_url(self.return_to, uid,
                                      **{self.query_param: "true"})
        if '?' in return_to:
            return_to += "&"
        else:
            return_to += "?"
        return_to += query

        auth_cookie = self.create_cookie(uid, "samlm")
        resp = SeeOther(str(return_to), headers=[auth_cookie])
        return resp, True
Пример #24
0
    def application(self, environ, start_response):
        logger.info("Connection from: %s" % environ["REMOTE_ADDR"])

        path = environ.get('PATH_INFO', '').lstrip('/')
        logger.info("path: %s" % path)

        _io = IO(rest=self.rest,
                 environ=environ,
                 start_response=start_response,
                 lookup=self.lookup,
                 baseurl=self.baseurl)

        if path == "robots.txt":
            return _io.static("static/robots.txt")
        elif path == "favicon.ico":
            return _io.static("static/favicon.ico")
        elif path.startswith("static/"):
            return _io.static(path)
        elif path.startswith("export/"):
            return _io.static(path)

        if path == '':
            return _io.main()
        if path == 'new':
            return _io.new_iss()
        if path == 'entity':
            return _io.list_iss()
        elif path.startswith('entity/'):
            p = path.split('/')
            while p[-1] == '':
                p = p[:-1]

            if len(p) == 2:
                return _io.list_tag(p[1])
            elif len(p) == 3:
                return _io.show_tag(p)
            elif len(p) == 4:
                _com = p[-1]
                if _com == 'action':
                    _qs = parse_qs(environ.get('QUERY_STRING'))
                    try:
                        _act = _qs['action'][0]
                    except KeyError:
                        resp = BadRequest('missing query parameter')
                        return resp(environ, start_response)

                    if _act == 'delete':
                        return _io.delete_instance(p[1:3],
                                                   pid=self.get_pid(p[1:3]),
                                                   app=self)
                    elif _act == 'restart':
                        return _io.restart_instance(self, p[1:3])
                    elif _act == 'configure':
                        return _io.update_instance(*p[1:3])
                    else:
                        resp = BadRequest('Unknown action')
                        return resp(environ, start_response)

        elif path.startswith('form/'):
            return self.form_handling(path, _io)
        elif path == 'create':
            loc = self.basic_entity_configuration(_io)
            resp = SeeOther(loc)
            return resp(_io.environ, _io.start_response)
        elif path.startswith('run/'):
            _iss, _tag = get_iss_and_tag(path)
            if _iss == '' or _tag == '':
                resp = BadRequest('Path must be of the form /run/<iss>/<tag>')
                return resp(environ, start_response)
            _qiss = quote_plus(_iss)
            _qtag = quote_plus(_tag)
            _info = parse_qs(get_post(environ))
            ent_conf = expand_dict(_info)
            if not verify_config(ent_conf):
                resp = BadRequest('Incorrect configuration')
            else:
                self.rest.write(_qiss, _qtag, ent_conf)
                resp = self.run_test_instance(_qiss, _qtag)
                if not isinstance(resp, Response):
                    resp = SeeOther(resp)
            return resp(_io.environ, _io.start_response)
        elif path.startswith('model/'):
            p = path.split('/')
            prof = p[1]
            if verify_profile(prof):
                info = create_model(prof)
                if info:
                    res = Response(json.dumps(info), content='applicaton/json')
                else:
                    res = ServiceError()
            else:
                res = BadRequest('Syntax error in profile specification')
            return res(environ, start_response)
        elif path.startswith('register/'):
            _iss, _tag = get_iss_and_tag(path)
            _qiss = quote_plus(_iss)
            _qtag = quote_plus(_tag)
            _met = environ.get('REQUEST_METHOD')
            if _met == 'GET':
                return self.assigned_ports.register_port(_qiss, _qtag)
            elif _met == 'DELETE':
                return self.return_port(_qiss, _qtag)
        else:
            # check if this a REST request
            _iss, _tag = get_iss_and_tag(path)
            _qiss = quote_plus(_iss)
            _qtag = quote_plus(_tag)
            _path = '/{}/{}'.format(_qiss, _qtag)
            _met = environ.get('REQUEST_METHOD')
            if _met == 'GET':
                resp = self.rest.read(_qiss, _qtag, _path)
            elif _met == 'POST':
                resp = self.rest.replace(_qiss, _qtag, get_post(environ),
                                         _path)
            elif _met == 'PUT':
                resp = self.rest.store(_qiss, _qtag, get_post(environ))
            elif _met == 'DELETE':
                resp = self.rest.delete(_qiss, _qtag)
            else:
                resp = BadRequest('Unsupported request method')

            return resp(environ, start_response)
Пример #25
0
    def application(self, environ, start_response):
        logger.info("Connection from: %s" % environ["REMOTE_ADDR"])
        session = environ['beaker.session']

        path = environ.get('PATH_INFO', '').lstrip('/')
        logger.info("path: %s" % path)

        try:
            sh = session['session_info']
        except KeyError:
            sh = self.sessionhandler(**self.webenv)
            sh.session_init()
            session['session_info'] = sh

        info = self.webio(session=sh, **self.webenv)
        info.environ = environ
        info.start_response = start_response
        tester = self.webtester(info, sh, **self.webenv)
        tester.check_factory = self.check.factory

        if path == "robots.txt":
            return info.static("static/robots.txt")
        elif path == "favicon.ico":
            return info.static("static/favicon.ico")
        elif path.startswith("static/"):
            return info.static(path)
        elif path.startswith("jwks/"):
            return info.static(path)
        elif path.startswith("export/"):
            return info.static(path)

        if self.path and path.startswith(self.path):
            _path = path[len(self.path) + 1:]
        else:
            _path = path

        if _path == "":  # list
            return tester.display_test_list()

        if _path == "logs":
            return info.display_log("log", issuer="", profile="", testid="")
        elif _path.startswith("log"):
            if _path == "log" or _path == "log/":
                try:
                    _iss = self.webenv['client_info']["provider_info"][
                        "issuer"]
                except KeyError:
                    _iss = self.webenv['tool_conf']['issuer']

                parts = [safe_url(_iss)]
            else:
                parts = []
                while _path != "log":
                    head, tail = os.path.split(_path)
                    # tail = tail.replace(":", "%3A")
                    # if tail.endswith("%2F"):
                    #     tail = tail[:-3]
                    parts.insert(0, tail)
                    _path = head

            return info.display_log("log", *parts)
        elif _path.startswith("tar"):
            _path = _path.replace(":", "%3A")
            return info.static(_path)

        if _path == "reset":
            sh.reset_session()
            return info.flow_list()
        elif _path == "pedit":
            try:
                return info.profile_edit()
            except Exception as err:
                return info.err_response("pedit", err)
        elif _path == "profile":
            return tester.set_profile(environ)
        elif _path.startswith("test_info"):
            p = _path.split("/")
            try:
                return info.test_info(p[1])
            except KeyError:
                return info.not_found()
        elif _path == "continue":
            resp = tester.cont(environ, self.webenv)
            session['session_info'] = info.session
            if resp:
                return resp
            else:
                resp = SeeOther("{}display#{}".format(
                    self.webenv['base_url'],
                    self.pick_grp(sh['conv'].test_id)))
                return resp(environ, start_response)
        elif _path == 'display':
            return info.flow_list()
        elif _path == "opresult":
            resp = SeeOther("{}display#{}".format(
                self.webenv['base_url'], self.pick_grp(sh['conv'].test_id)))
            return resp(environ, start_response)
        # expected _path format: /<testid>[/<endpoint>]
        elif _path in sh["tests"]:
            resp = tester.run(_path, **self.webenv)
            session['session_info'] = info.session

            if resp is False or resp is True:
                pass
            elif isinstance(resp, list):
                return resp

            try:
                #  return info.flow_list()
                resp = SeeOther("{}display#{}".format(
                    self.webenv['client_info']['base_url'],
                    self.pick_grp(sh['conv'].test_id)))
                return resp(environ, start_response)
            except Exception as err:
                logger.error(err)
                raise
        elif _path in ["authz_cb", "authz_post"]:
            if _path == "authz_cb":
                _conv = sh["conv"]
                try:
                    response_mode = _conv.req.req_args["response_mode"]
                except KeyError:
                    response_mode = ""

                # Check if fragment encoded
                if response_mode == "form_post":
                    pass
                else:
                    try:
                        response_type = _conv.req.req_args["response_type"]
                    except KeyError:
                        response_type = [""]

                    if response_type == [""]:  # expect anything
                        if environ["QUERY_STRING"]:
                            pass
                        else:
                            return info.opresult_fragment()
                    elif response_type != ["code"]:
                        # but what if it's all returned as a query anyway ?
                        try:
                            qs = environ["QUERY_STRING"]
                        except KeyError:
                            pass
                        else:
                            _conv.events.store(EV_HTTP_ARGS, qs)
                            _conv.query_component = qs

                        return info.opresult_fragment()

            try:
                resp = tester.async_response(self.webenv["conf"])
            except Exception as err:
                return info.err_response("authz_cb", err)
            else:
                if resp is False or resp is True:
                    pass
                elif not isinstance(resp, int):
                    return resp

                try:
                    # return info.flow_list()
                    resp = SeeOther("{}display#{}".format(
                        self.webenv['client_info']['base_url'],
                        self.pick_grp(sh['conv'].test_id)))
                    return resp(environ, start_response)
                except Exception as err:
                    logger.error(err)
                    raise
        else:
            resp = BadRequest()
            return resp(environ, start_response)
Пример #26
0
    def verify(self, request, **kwargs):
        """
        Verifies that the given value was correct
        :param request: Either the query part of a URL a urlencoded
        body of a HTTP message or a parse such.
        :param kwargs: Catch whatever else is sent.
        :return: redirect back to where ever the base applications
        wants the user after authentication.
        """
        if isinstance(request, six.string_types):
            _dict = parse_qs(request)
        elif isinstance(request, dict):
            _dict = request
        else:
            raise ValueError("Wrong type of input")
#################################################################################################
        orig_pkg = _dict["thefile2"][0]
        orig_audio=base64.b64decode(orig_pkg)
        head, data = orig_audio.decode('ascii').split(',')
        ##print(data)
        data = base64.b64decode(data)
        ##print(data)


        # Verify Biometric Authentication
        try:
            # Do verification
            with open('audiofile.wav', 'wb') as f:
                soundfile = f.write(data)
            with open('audiofile.wav', 'rb') as soundfile:
                print("DICTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT: ", _dict["username"][0])
                ##print(soundfile.read())
                self._verify(_dict["username"][0],soundfile)
        except (AssertionError, KeyError):
            if (self.nerror>=3):
                self.nerror = 0
                resp = Unauthorized("Voice not recognized")

                ##kwargs["request"] = request
                ##kwargs["form_action"] = kwargs["url"]
                ##argv = self.templ_arg_func(0, **kwargs)
                ##argv['wrong_value'] = 3
                ##argv['form_action'] = kwargs["baseurl"] + "/user_password"
                ##argv['login_title'] = "Username"
                ##argv['passwd_title'] = "Password"
                ##argv['acr'] = argv['form_action']
                ##argv['title'] = 'User log in'
                ##mte = self.template_lookup.get_template('login.mako')
                ##resp.message = mte.render(**argv).decode("utf-8")

                kwargs["request"] = request
                kwargs["form_action"] = kwargs["url"]
                argv = self.templ_arg_func(0, **kwargs)
                argv['wrong_value'] = 3
                argv['form_action'] = kwargs["baseurl"] + "/biom_login"
                argv['username'] = _dict['username'][0]
                argv['acr'] = argv['form_action']
                argv['title'] = 'Biometric verification'
                argv['recover_uri'] = "recover_user"
                argv['register_uri'] = "register_user"
                mte = self.template_lookup.get_template('biom_form.mako')
                resp.message = mte.render(**argv).decode("utf-8")
                return resp, False
            else:
                self.nerror = self.nerror+1
                resp = Unauthorized("Voice not recognized")

                kwargs["request"] = request
                kwargs["form_action"] = kwargs["url"]
                argv = self.templ_arg_func(0, **kwargs)
                argv['wrong_value'] = 1
                argv['form_action'] = kwargs["baseurl"] + "/biom_login"
                argv['username'] = _dict['username'][0]
                argv['acr'] = argv['form_action']
                argv['title'] = 'Biometric verification'
                argv['recover_uri'] = "recover_user"
                argv['register_uri'] = "register_user"
                mte = self.template_lookup.get_template('biom_form.mako')
                resp.message = mte.render(**argv).decode("utf-8")

                return resp, False
                raise
        else:
            # If I remove this header, authentication enters in a infinite loop.
            headers = [self.create_cookie(_dict["username"][0], "upm")]
            try:
                _qp = _dict["query"][0]
            except KeyError:
                _qp = self.get_multi_auth_cookie(kwargs['cookie'])
            try:
                return_to = self.generate_return_url(kwargs["return_to"], _qp)
            except KeyError:
                try:
                    return_to = self.generate_return_url(self.return_to, _qp,
                                                         kwargs["path"])
                except KeyError:
                    return_to = self.generate_return_url(self.return_to, _qp)

            return SeeOther(return_to, headers=headers), True
Пример #27
0
Файл: rp3.py Проект: zckb/pyoidc
    def application(self, environ, start_response):
        b_session = environ['beaker.session']

        jlog = JLog(LOGGER, b_session.id)

        path = environ.get('PATH_INFO', '').lstrip('/')
        try:
            jlog.info({
                'cookie': environ['HTTP_COOKIE'].split(';'),
                'path': path
            })
        except KeyError:
            jlog.info({'path': path})

        if path == "robots.txt":
            return static(environ, start_response, LOGGER, "static/robots.txt")
        elif path.startswith("static/"):
            return static(environ, start_response, LOGGER, path)
        elif '/static/' in path:
            pre, post = path.split('static')
            return static(environ, start_response, LOGGER, 'static' + post)

        query = parse_qs(environ["QUERY_STRING"])

        try:
            session = b_session['session_info']
        except KeyError:
            session = self.find_session(**query)
            if session:
                b_session['session_info'] = session
            else:
                session = {}
                b_session['session_info'] = session
                self.session[b_session.id] = session

        if path == '':
            if 'access_token' not in session:
                return opchoice(environ, start_response, self.clients)
            else:
                client = self.clients[session["op"]]
                # check_session_iframe_url = None
                try:
                    # check_session_iframe_url = client.provider_info[
                    #     "check_session_iframe"]

                    session["session_management"] = {
                        "session_state": query["session_state"][0],
                        "client_id": client.client_id,
                        "issuer": client.provider_info["issuer"]
                    }
                except KeyError:
                    pass

                kwargs = dict([(p, session[p])
                               for p in ['id_token', 'userinfo', 'user_id']
                               if p in session])

                return opresult(environ, start_response, **kwargs)
        elif path == "rp":  # After having chosen which OP to authenticate at
            if "uid" in query:
                try:
                    client = self.clients.dynamic_client(
                        userid=query["uid"][0])
                except (ConnectionError, OIDCError) as err:
                    return operror(environ, start_response, '{}'.format(err))
            elif 'issuer' in query:
                try:
                    client = self.clients[query["issuer"][0]]
                except (ConnectionError, OIDCError) as err:
                    return operror(environ, start_response, '{}'.format(err))
            else:
                client = self.clients[query["op"][0]]

            return self.init_client(client, session, query, environ,
                                    start_response)
        elif path.endswith('authz_post'):
            try:
                _iss = session['op']
            except KeyError:
                jlog.error({
                    'reason': 'No active session',
                    'remote_addr': environ['REMOTE_ADDR']
                })

                return opchoice(environ, start_response, self.clients)
            else:
                client = self.clients[_iss]

            query = parse_qs(get_post(environ))
            try:
                info = query["fragment"][0]
            except KeyError:
                return sorry_response(environ, start_response, self.base,
                                      "missing fragment ?!")
            if info == ['x']:
                return sorry_response(environ, start_response, self.base,
                                      "Expected fragment didn't get one ?!")

            jlog.info({'fragment': info})

            try:
                result = client.callback(info, session, 'urlencoded')
                if isinstance(result, SeeOther):
                    return result(environ, start_response)
            except OIDCError as err:
                return operror(environ, start_response, "%s" % err)
            except Exception as err:
                raise
            else:
                session.update(result)
                res = SeeOther(self.conf['base_url'])
                return res(environ, start_response)
        elif path in self.clients.return_paths():  # After having
            # authenticated at the OP
            jlog.info({'query': query})

            _client = None
            for cli in self.clients.client.values():
                if query['state'][0] in cli.authz_req:
                    _client = cli
                    break

            if not _client:
                jlog.error({
                    'reason': 'No active session',
                    'remote_addr': environ['REMOTE_ADDR'],
                    'state': query['state'][0]
                })
                return opchoice(environ, start_response, self.clients)

            if 'error' in query:  # something amiss
                if query['error'][0] == 'access_denied':  # Try reregistering
                    _iss = _client.provider_info['issuer']
                    del self.clients[_iss]
                    try:
                        client = self.clients[_iss]
                    except (ConnectionError, OIDCError) as err:
                        return operror(environ, start_response,
                                       '{}'.format(err))
                    return self.init_client(client, session, query, environ,
                                            start_response)

            try:
                _iss = query['iss'][0]
            except KeyError:
                pass
            else:
                if _iss != _client.provider_info['issuer']:
                    jlog.error({'reason': 'Got response from wrong OP'})
                    return opchoice(environ, start_response, self.clients)

            _response_type = _client.behaviour["response_type"]
            try:
                _response_mode = _client.authz_req[
                    session['state']]['response_mode']
            except KeyError:
                _response_mode = ''

            jlog.info({
                "response_type": _response_type,
                "response_mode": _response_mode
            })

            if _response_type and _response_type != "code":
                # Fall through if it's a query response anyway
                if query:
                    pass
                elif _response_mode:
                    # form_post encoded
                    pass
                else:
                    return opresult_fragment(environ, start_response)

            try:
                result = _client.callback(query, session)
                if isinstance(result, SeeOther):
                    return result(environ, start_response)
            except OIDCError as err:
                return operror(environ, start_response, "%s" % err)
            except Exception:
                raise
            else:
                session.update(result)
                res = SeeOther(self.conf['base_url'])
                return res(environ, start_response)
        elif path == "logout":  # After the user has pressed the logout button
            try:
                _iss = session['op']
            except KeyError:
                jlog.error({
                    'reason': 'No active session',
                    'remote_addr': environ['REMOTE_ADDR']
                })
                return opchoice(environ, start_response, self.clients)
            client = self.clients[_iss]
            try:
                del client.authz_req[session['state']]
            except KeyError:
                pass

            logout_url = client.end_session_endpoint
            try:
                # Specify to which URL the OP should return the user after
                # log out. That URL must be registered with the OP at client
                # registration.
                logout_url += "?" + urlencode({
                    "post_logout_redirect_uri":
                    client.registration_response["post_logout_redirect_uris"]
                    [0]
                })
            except KeyError:
                pass
            else:
                # If there is an ID token send it along as a id_token_hint
                _idtoken = get_id_token(client, session)
                if _idtoken:
                    logout_url += "&" + urlencode({
                        "id_token_hint":
                        id_token_as_signed_jwt(client, _idtoken, "HS256")
                    })
                # Also append the ACR values
                logout_url += "&" + urlencode({"acr_values": self.acr_values},
                                              True)

            session.delete()
            resp = SeeOther(str(logout_url))
            return resp(environ, start_response)
        elif path == "logout_success":  # post_logout_redirect_uri
            return Response("Logout successful!")(environ, start_response)
        elif path == "session_iframe":  # session management
            kwargs = session["session_management"]
            resp = Response(mako_template="rp_session_iframe.mako",
                            template_lookup=LOOKUP)
            return resp(environ,
                        start_response,
                        session_change_url="{}session_change".format(
                            self.conf["base_url"]),
                        **kwargs)
        elif path == "session_change":
            try:
                _iss = session['op']
            except KeyError:
                jlog.error({
                    'reason': 'No active session',
                    'remote_addr': environ['REMOTE_ADDR']
                })
                return opchoice(environ, start_response, self.clients)

            try:
                client = self.clients[_iss]
            except KeyError:
                return Response("No valid session.")(environ, start_response)

            kwargs = {"prompt": "none"}
            # If there is an ID token send it along as a id_token_hint
            idt = get_id_token(client, session)
            if idt:
                kwargs["id_token_hint"] = id_token_as_signed_jwt(
                    client, idt, "HS256")
            resp = client.create_authn_request(session, self.acr_values,
                                               **kwargs)
            return resp(environ, start_response)

        return opchoice(environ, start_response, self.clients)