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
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
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])
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] ), )
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
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)
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)
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)
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!")
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)
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)))
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)
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
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
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
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)
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)
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)
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)
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
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)
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)
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
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)
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)
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
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)