def code_grant_type(self, areq): # assert that the code is valid try: _info = self.sdb[areq["code"]] except KeyError: err = TokenErrorResponse(error="invalid_grant", error_description="Unknown access grant") return Response(err.to_json(), content="application/json", status="401 Unauthorized") authzreq = json.loads(_info['authzreq']) if 'code_verifier' in areq: try: _method = authzreq['code_challenge_method'] except KeyError: _method = 'S256' resp = self.verify_code_challenge(areq['code_verifier'], authzreq['code_challenge'], _method) if resp: return resp if 'state' in areq: if self.sdb[areq['code']]['state'] != areq['state']: err = TokenErrorResponse(error="unauthorized_client") return Unauthorized(err.to_json(), content="application/json") resp = self.token_scope_check(areq, _info) if resp: return resp # If redirect_uri was in the initial authorization request # verify that the one given here is the correct one. if "redirect_uri" in _info: assert areq["redirect_uri"] == _info["redirect_uri"] issue_refresh = False if 'scope' in authzreq and 'offline_access' in authzreq['scope']: if authzreq['response_type'] == 'code': issue_refresh = True try: _tinfo = self.sdb.upgrade_to_token(areq["code"], issue_refresh=issue_refresh) except AccessCodeUsed: err = TokenErrorResponse(error="invalid_grant", error_description="Access grant used") return Response(err.to_json(), content="application/json", status="401 Unauthorized") logger.debug("_tinfo: %s" % _tinfo) atr = AccessTokenResponse(**by_schema(AccessTokenResponse, **_tinfo)) logger.debug("AccessTokenResponse: %s" % atr) return Response(atr.to_json(), content="application/json")
def providerinfo_endpoint(self, **kwargs): _log_info = logger.info _log_info("@providerinfo_endpoint") try: _response = self.create_providerinfo() _log_info("provider_info_response: %s" % (_response.to_dict(), )) headers = [("Cache-Control", "no-store"), ("x-ffo", "bar")] if 'handle' in kwargs: (key, _) = kwargs['handle'] if key.startswith(STR) and key.endswith(STR): cookie = self.cookie_func(key, self.cookie_name, "pinfo", self.sso_ttl) headers.append(cookie) resp = Response(_response.to_json(), content="application/json", headers=headers) except Exception: message = traceback.format_exception(*sys.exc_info()) logger.error(message) resp = Response(message, content="html/text") return resp
def providerinfo_endpoint(self, handle="", **kwargs): _log_debug = logger.debug _log_info = logger.info _log_info("@providerinfo_endpoint") try: _response = self.conf_info #for endp in self.endpoints: # _response[endp(None).name] = "%s%s" % (self.baseurl, # endp.etype) _log_info("provider_info_response: %s" % (_response.to_dict(), )) headers = [("Cache-Control", "no-store"), ("x-ffo", "bar")] if handle: (key, timestamp) = handle if key.startswith(STR) and key.endswith(STR): cookie = self.cookie_func(key, self.cookie_name, "pinfo", self.sso_ttl) headers.append(cookie) resp = Response(_response.to_json(), content="application/json", headers=headers) except Exception as err: message = traceback.format_exception(*sys.exc_info()) logger.error(message) resp = Response(message, content="html/text") return resp
def __call__(self, cookie=None, policy_url=None, logo_url=None, query="", **kwargs): """ Put up the login form """ if cookie: headers = [cookie] else: headers = [] resp = Response(headers=headers) acr = None try: req = urlparse.parse_qs(query) acr = req["acr_values"][0] except: pass argv = {"login": "", "password": "", "action": "verify", "policy_url": policy_url, "logo_url": logo_url, "query": query, "acr" : acr} logger.info("do_authentication argv: %s" % argv) mte = self.template_lookup.get_template(self.mako_template) resp.message = mte.render(**argv) return resp
def introspection_endpoint_(self, user, **kwargs): """ The endpoint URI at which the resource server introspects an RPT presented to it by a client. """ request = kwargs["request"] logger.debug("requestor: %s, request: %s" % (user, request)) ir = IntrospectionRequest().from_json(request) adb = self.get_adb(kwargs["client_id"]) try: try: # requestor = self.rpt[ir["token"]]["requestor"] perms = adb.permit.get_accepted_by_rpt(user, ir["token"]) except KeyError: response = BadRequest() else: if perms: irep = IntrospectionResponse(active=True, exp=perms[0]["exp"], permissions=perms) logger.debug("response: %s" % irep.to_json()) response = Response(irep.to_json(), content="application/json") else: logger.info("No permissions bound to this RPT") response = BadRequest() except ToOld: logger.info("RPT expired") irep = IntrospectionResponse(valid=False) response = Response(irep.to_json(), content="application/json") except KeyError: response = BadRequest() return response
def display_log(environ, start_response): path = environ.get('PATH_INFO', '').lstrip('/') if path == "log": tail = environ["REMOTE_ADDR"] path = os.path.join(path, tail) elif path == "logs": path = "log" if os.path.isfile(path): return static(environ, start_response, path) elif os.path.isdir(path): item = [] for (dirpath, dirnames, filenames) in os.walk(path): if dirnames: item = [(fn, os.path.join(path, fn)) for fn in dirnames] break if filenames: item = [(fn, os.path.join(path, fn)) for fn in filenames] break item.sort() resp = Response(mako_template="logs.mako", template_lookup=LOOKUP, headers=[]) argv = {"logs": item} return resp(environ, start_response, **argv) else: resp = Response("No saved logs") return resp(environ, start_response)
def token_endpoint(self, authn="", **kwargs): """ This is where clients come to get their access tokens """ _sdb = self.sdb logger.debug("- token -") body = kwargs["request"] logger.debug("body: %s" % sanitize(body)) areq = AccessTokenRequest().deserialize(body, "urlencoded") try: self.client_authn(self, areq, authn) except FailedAuthentication as err: logger.error(err) err = TokenErrorResponse(error="unauthorized_client", error_description="%s" % err) return Response(err.to_json(), content="application/json", status="401 Unauthorized") logger.debug("AccessTokenRequest: %s" % sanitize(areq)) try: assert areq["grant_type"] == "authorization_code" except AssertionError: err = TokenErrorResponse(error="invalid_request", error_description="Wrong grant type") return Response(err.to_json(), content="application/json", status="401 Unauthorized") # assert that the code is valid _info = _sdb[areq["code"]] resp = self.token_scope_check(areq, _info) if resp: return resp # If redirect_uri was in the initial authorization request # verify that the one given here is the correct one. if "redirect_uri" in _info: assert areq["redirect_uri"] == _info["redirect_uri"] try: _tinfo = _sdb.upgrade_to_token(areq["code"], issue_refresh=True) except AccessCodeUsed: err = TokenErrorResponse(error="invalid_grant", error_description="Access grant used") return Response(err.to_json(), content="application/json", status="401 Unauthorized") logger.debug("_tinfo: %s" % sanitize(_tinfo)) atr = AccessTokenResponse(**by_schema(AccessTokenResponse, **_tinfo)) logger.debug("AccessTokenResponse: %s" % sanitize(atr)) return Response(atr.to_json(), content="application/json")
def __call__(self, cookie=None, end_point_index=0, **kwargs): """Put up the login form.""" resp = Response() argv = self.templ_arg_func(end_point_index, **kwargs) logger.info("do_authentication argv: %s" % sanitize(argv)) mte = self.template_lookup.get_template(self.mako_template) resp.message = mte.render(**argv).decode("utf-8") return resp
def __call__(self, cookie=None, end_point_index=0, **kwargs): """ Put up the login form """ resp = Response() argv = self.templ_arg_func(end_point_index, **kwargs) logger.info("do_authentication argv: %s" % sanitize(argv)) mte = self.template_lookup.get_template(self.mako_template) resp.message = mte.render(**argv).decode("utf-8") return resp
def __call__(self, cookie=None, end_point_index=0, **kwargs): """ Put up the login form """ resp = Response() self.nerror = 0 template_args = self.templ_arg_func(end_point_index, **kwargs) # mako_template_engine = self.template_lookup.get_template('totp_form.mako') mako_template_engine = self.template_lookup.get_template(self.mako_template) resp.message = mako_template_engine.render(**template_args).decode("utf-8") return resp
def trace(): resp = None for handler in logger.handlers: if isinstance(handler, TraceHandler): msg = [(e["created"], e["msg"]) for e in handler.buffer] resp = Response(json.dumps(msg)) break # Should I flush the buffer ? #handler.flush() if resp: return resp else: return Response([])
def get_iss(self): resp = Response(mako_template="new_iss.mako", template_lookup=self.lookup, headers=[]) args = {'base': ''} return resp(self.environ, self.start_response, **args)
def token_endpoint(self, dtype='urlencoded', **kwargs): atr = AccessTokenRequest().deserialize(kwargs["request"], dtype) resp = super(PoPProvider, self).token_endpoint(**kwargs) if "token_type" not in atr or atr["token_type"] != "pop": return resp client_public_key = base64.urlsafe_b64decode( atr["key"].encode("utf-8")).decode("utf-8") pop_key = json.loads(client_public_key) atr = AccessTokenResponse().deserialize(resp.message, method="json") data = self.sdb.read(atr["access_token"]) jwt = { "iss": self.baseurl, "aud": self.baseurl, "exp": data["token_expires_at"], "nbf": int(time.time()), "cnf": { "jwk": pop_key } } _jws = JWS(jwt, alg="RS256").sign_compact( self.keyjar.get_signing_key(owner="")) self.access_tokens[_jws] = data["access_token"] atr["access_token"] = _jws atr["token_type"] = "pop" return Response(atr.to_json(), content="application/json")
def do_config(self, sid='', start_page='', params='', **args): resp = Response(mako_template="config.mako", template_lookup=self.kwargs['lookup'], headers=[]) if sid: _url = os.path.join(self.base_url, sid) else: _url = self.base_url try: test_id = args['test_id'] except KeyError: test_id = '' kwargs = { 'start_page': start_page, 'params': params, 'issuer': _url, 'profiles': list(self.kwargs['op_profiles'].keys()), 'selected': self.selected, 'sid': sid, 'base': self.base_url, 'test_id': test_id } return resp(self.inut.environ, self.inut.start_response, **kwargs)
def sorry_response(environ, start_response, homepage, err): resp = Response(mako_template="sorry.mako", template_lookup=LOOKUP, headers=[]) argv = {"htmlpage": homepage, "error": str(err)} return resp(environ, start_response, **argv)
def revocation_endpoint(self, authn='', request=None, **kwargs): """ Implements RFC7009 allows a client to invalidate an access or refresh token. :param authn: Client Authentication information :param request: The revocation request :param kwargs: :return: """ trr = TokenRevocationRequest().deserialize(request, "urlencoded") resp = self.get_token_info(authn, trr, 'revocation_endpoint') if isinstance(resp, Response): return resp else: client_id, token_type, _info = resp logger.info('{} token revocation: {}'.format(client_id, trr.to_dict())) try: self.sdb.token_factory[token_type].invalidate(trr['token']) except KeyError: return BadRequest() else: return Response('OK')
def refresh_token_grant_type(self, areq): at = self.token_handler.refresh_access_token(self.baseurl, areq['access_token'], 'refresh_token') atr = AccessTokenResponse(**by_schema(AccessTokenResponse, **at)) return Response(atr.to_json(), content="application/json")
def load_keys(self, request, client_id, client_secret): try: self.keyjar.load_keys(request, client_id) try: n_keys = len(self.keyjar[client_id]) msg = "Found {} keys for client_id={}" logger.debug(msg.format(n_keys, client_id)) except KeyError: pass except Exception as err: msg = "Failed to load client keys: {}" logger.error(msg.format(sanitize(request.to_dict()))) logger.error("%s", err) err = ClientRegistrationError( error="invalid_configuration_parameter", error_description="%s" % err) return Response(err.to_json(), content="application/json", status_code="400 Bad Request") # Add the client_secret as a symmetric key to the keyjar _kc = KeyBundle([{ "kty": "oct", "key": client_secret, "use": "ver" }, { "kty": "oct", "key": client_secret, "use": "sig" }]) try: self.keyjar[client_id].append(_kc) except KeyError: self.keyjar[client_id] = [_kc]
def opbyuid(environ, start_response): resp = Response(mako_template="opbyuid.mako", template_lookup=LOOKUP, headers=[]) argv = { } return resp(environ, start_response, **argv)
def __call__(self, cookie=None, end_point_index=0, **kwargs): """ Put up the login form """ # if cookie: # headers = [cookie] # else: # headers = [] resp = Response() argv = self.templ_arg_func(end_point_index, **kwargs) logger.info("do_authentication argv: %s" % argv) mte = self.template_lookup.get_template(self.mako_template) resp.message = mte.render(**argv) return resp
def password_grant_type(self, areq): """ Token authorization using Resource owner password credentials. RFC6749 section 4.3 """ # `Any` comparison tries a first broker, so we either hit an IndexError or get a method try: authn, authn_class_ref = self.pick_auth(areq, "any") except IndexError: err = TokenErrorResponse(error="invalid_grant") return Unauthorized(err.to_json(), content="application/json") identity, _ts = authn.authenticated_as( username=areq["username"], password=areq["password"] ) if identity is None: err = TokenErrorResponse(error="invalid_grant") return Unauthorized(err.to_json(), content="application/json") # We are returning a token areq["response_type"] = ["token"] authn_event = AuthnEvent( identity["uid"], identity.get("salt", ""), authn_info=authn_class_ref, time_stamp=_ts, ) sid = self.setup_session(areq, authn_event, self.cdb[areq["client_id"]]) _at = self.sdb.upgrade_to_token(self.sdb[sid]["code"], issue_refresh=True) atr_class = self.server.message_factory.get_response_type("token_endpoint") atr = atr_class(**by_schema(atr_class, **_at)) return Response( atr.to_json(), content="application/json", headers=OAUTH2_NOCACHE_HEADERS )
def providerinfo_endpoint(self, handle="", **kwargs): _log_info = logger.info _log_info("@providerinfo_endpoint") try: _response = self.create_providerinfo() msg = "provider_info_response: {}" _log_info(msg.format(sanitize(_response.to_dict()))) if self.events: self.events.store("Protocol response", _response) headers = [("Cache-Control", "no-store")] if handle: (key, timestamp) = handle if key.startswith(STR) and key.endswith(STR): cookie = self.cookie_func(key, self.cookie_name, "pinfo", self.sso_ttl) headers.append(cookie) resp = Response(_response.to_json(), content="application/json", headers=headers) except Exception: message = traceback.format_exception(*sys.exc_info()) logger.error(message) resp = error_response("service_error", message) return resp
def load_keys(self, request, client_id, client_secret): try: self.keyjar.load_keys(request, client_id) try: logger.debug("keys for %s: [%s]" % (client_id, ",".join( ["%s" % x for x in self.keyjar[client_id]]))) except KeyError: pass except Exception as err: logger.error("Failed to load client keys: %s" % request.to_dict()) logger.error("%s", err) err = ClientRegistrationError( error="invalid_configuration_parameter", error_description="%s" % err) return Response(err.to_json(), content="application/json", status="400 Bad Request") # Add the client_secret as a symmetric key to the keyjar _kc = KeyBundle([{ "kty": "oct", "key": client_secret, "use": "ver" }, { "kty": "oct", "key": client_secret, "use": "sig" }]) try: self.keyjar[client_id].append(_kc) except KeyError: self.keyjar[client_id] = [_kc]
def do_put(self, path, info): """ UPDATE: PUT /{collection}/{id} """ _name = self.resource_name(path) try: f = open(_name, "w") except IOError: return ErrorResponse(error="not_allowed") head, tail = os.path.split(_name) try: _ji = json.loads(info) except ValueError: return ErrorResponse(error="not_json") try: assert _ji["_id"] == tail except KeyError: _ji["_id"] = tail except AssertionError: return ErrorResponse(error="not_allowed") f.write(json.dumps(_ji)) f.close() return Response(json.dumps({"_id": tail}), headers=[("Location", "%s/%s" % (self.baseurl, self.url(_name)))])
def delete_instance(self, iss, tag): resp = Response(mako_template="new_instance.mako", template_lookup=self.lookup, headers=[]) arg = {'base': ''} return resp(self.environ, self.start_response, **arg)
def providerinfo_endpoint(self, handle="", **kwargs): """ The Provider info endpoint. A request for provider info should be handled by this method. It will work as well for requests from federation aware RPs as for non-federation aware RPs. :param handle: (key, timestamp) tuple used at cookie construction :param kwargs: Extra key word arguments. :return: Provider Info response """ logger.info("@providerinfo_endpoint") try: _response = self.create_fed_providerinfo() msg = "provider_info_response: {}" logger.info(msg.format(sanitize(_response.to_dict()))) if self.events: self.events.store('Protocol response', _response) headers = [("Cache-Control", "no-store"), ("x-ffo", "bar")] if handle: (key, timestamp) = handle if key.startswith(STR) and key.endswith(STR): cookie = self.cookie_func(key, self.cookie_name, "pinfo", self.sso_ttl) headers.append(cookie) resp = Response(_response.to_json(), content="application/json", headers=headers) except Exception: message = traceback.format_exception(*sys.exc_info()) logger.error(message) resp = error('service_error', message) return resp
def flow_list(environ, start_response, flows, done): resp = Response(mako_template="flowlist.mako", template_lookup=LOOKUP, headers=[]) argv = {"base": KW_ARGS["conf"].BASE, "flows": flows, "done": done} return resp(environ, start_response, **argv)
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 token_endpoint(self, authn="", **kwargs): """ This is where clients come to get their access tokens """ logger.debug("- token -") body = kwargs["request"] logger.debug("body: %s" % body) areq = AccessTokenRequest().deserialize(body, "urlencoded") try: self.client_authn(self, areq, authn) except FailedAuthentication as err: logger.error(err) err = TokenErrorResponse(error="unauthorized_client", error_description="%s" % err) return Response(err.to_json(), content="application/json", status_code=401) logger.debug("AccessTokenRequest: %s" % areq) _grant_type = areq["grant_type"] if _grant_type == "authorization_code": return self.code_grant_type(areq) elif _grant_type == 'client_credentials': return self.client_credentials_grant_type(areq) elif _grant_type == 'password': return self.password_grant_type(areq) elif _grant_type == 'refresh_token': return self.refresh_token_grant_type(areq) else: raise UnSupported('grant_type: {}'.format(_grant_type))
def delete_instance(self, parts, pid=0, app=None): lp = [unquote_plus(p) for p in parts] qp = [quote_plus(p) for p in lp] _key = app.assigned_ports.make_key(*lp) if pid: kill_process(pid) del app.running_processes[_key] os.unlink(os.path.join(self.entpath, *qp)) # Remove issuer if out of tags if not os.listdir(os.path.join(self.entpath, qp[0])): os.rmdir(os.path.join(self.entpath, qp[0])) del app.assigned_ports[_key] resp = Response(mako_template='message.mako', template_lookup=self.lookup, headers=[]) args = { 'title': "Action performed", 'base': self.baseurl, 'note': 'Your test tool instance <em>{} {}</em> has been ' 'removed'.format(*lp) } return resp(self.environ, self.start_response, **args)
def introspection_endpoint(self, authn='', request=None, **kwargs): """ Implements RFC7662 :param authn: Client Authentication information :param request: The introspection request :param kwargs: :return: """ tir = TokenIntrospectionRequest().deserialize(request, "urlencoded") resp = self.get_token_info(authn, tir, 'introspection_endpoint') if isinstance(resp, Response): return resp else: client_id, token_type, _info = resp logger.info('{} token introspection: {}'.format( client_id, tir.to_dict())) ir = TokenIntrospectionResponse( active=self.sdb.token_factory[token_type].is_valid(_info), **_info.to_dict()) ir.weed() return Response(ir.to_json(), content="application/json")
def restart_instance(self, app, part): _iss = unquote_plus(part[0]) _tag = unquote_plus(part[1]) url = app.run_test_instance(quote_plus(_iss), quote_plus(_tag)) if isinstance(url, Response): return url(self.environ, self.start_response) resp = Response(mako_template='message.mako', template_lookup=self.lookup, headers=[]) if url: args = { 'title': "Action performed", 'base': self.baseurl, 'note': 'Your test instance "{iss}:{tag}" has been ' 'restarted as <a href="{url}">{url}</a>'.format(iss=_iss, tag=_tag, url=url) } else: args = { 'title': "Action Failed", 'base': self.baseurl, 'note': 'Could not restart your test instance' } return resp(self.environ, self.start_response, **args)