def webfinger(environ, events): query = parse_qs(environ["QUERY_STRING"]) _op = environ["oic.op"] try: if query["rel"] != [OIC_ISSUER]: events.store( EV_CONDITION, State('webfinger_parameters', ERROR, message='parameter rel wrong value: {}'.format( query['rel']))) return BadRequest('Parameter value error') else: resource = query["resource"][0] except KeyError as err: events.store( EV_CONDITION, State('webfinger_parameters', ERROR, message='parameter {} missing'.format(err))) resp = BadRequest("Missing parameter in request") else: wf = WebFinger() resp = Response(wf.response(subject=resource, base=_op.baseurl)) return resp
def setup_webfinger_endpoint(self): wf = WebFinger() resp = Response(wf.response(subject=self.op_base, base=self.op_base)) responses.add(responses.GET, self.op_base + ".well-known/webfinger", body=resp.message, status=200, content_type='application/json')
def test_extra_member_response(self): wf = WebFinger() resp = wf.response('acct:local@domain', 'https://example.com', dummy='foo') # resp should be a JSON document _resp = json.loads(resp) assert _resp['dummy'] == 'foo'
def _webfinger(provider, request, **kwargs): """Handle webfinger requests.""" params = urlparse.parse_qs(request) if params["rel"][0] == OIC_ISSUER: wf = WebFinger() return Response(wf.response(params["resource"][0], provider.baseurl), headers=[("Content-Type", "application/jrd+json")]) else: return BadRequest("Incorrect webfinger.")
def get(self): params = self.request.query_arguments if params['rel'][0].decode('utf-8') == OIC_ISSUER: wf = WebFinger() self.write( wf.response(params["resource"][0].decode('utf-8'), self.settings['oidc_provider'].baseurl)) else: return self.send_error()
def test_extra_member_response(self): wf = WebFinger() resp = wf.response("acct:local@domain", "https://example.com", dummy="foo") # resp should be a JSON document _resp = json.loads(resp) assert _resp["dummy"] == "foo"
def webfinger(environ, start_response, _): query = parse_qs(environ["QUERY_STRING"]) try: assert query["rel"] == [OIC_ISSUER] resource = query["resource"][0] except KeyError: resp = BadRequest("Missing parameter in request") else: wf = WebFinger() resp = Response(wf.response(subject=resource, base=OAS.baseurl)) return resp(environ, start_response)
def webfinger(environ): query = parse_qs(environ["QUERY_STRING"]) try: assert query["rel"] == [OIC_ISSUER] resource = query["resource"][0] except KeyError: resp = BadRequest("Missing parameter in request") else: wf = WebFinger() resp = Response(wf.response(subject=resource, base=AUTHZSRV.baseurl)) return resp
def _webfinger(self): query = request.args try: assert query["rel"] == OIC_ISSUER resource = query["resource"][0] except KeyError: resp = BadRequest("Missing parameter in request") else: wf = WebFinger() resp = Response(wf.response(subject=resource, base=self.provider.baseurl)) return resp
def webfinger(self, environ, start_response): query = parse_qs(environ["QUERY_STRING"]) try: rel = query["rel"] resource = query["resource"][0] except KeyError: resp = BadRequest("Missing parameter in request") else: if rel != [OIC_ISSUER]: resp = BadRequest("Bad issuer in request") else: wf = WebFinger() resp = Response( wf.response(subject=resource, base=self.oas.baseurl)) return resp(environ, start_response)
def webfinger(environ, start_response, session_info, trace, **kwargs): query = parse_qs(environ["QUERY_STRING"]) # Find the identifier session_info["test_id"] = find_identifier(query["resource"][0]) trace.info(HEADER % "WebFinger") trace.request(environ["QUERY_STRING"]) trace.info("QUERY: %s" % (query,)) try: assert query["rel"] == [OIC_ISSUER] resource = query["resource"][0] except AssertionError: errmsg = "Wrong 'rel' value: %s" % query["rel"][0] trace.error(errmsg) resp = BadRequest(errmsg) except KeyError: errmsg = "Missing 'rel' parameter in request" trace.error(errmsg) resp = BadRequest(errmsg) else: wf = WebFinger() p = urlparse(resource) if p.scheme == "acct": l, _ = p.path.split("@") path = pathmap.IDMAP[l.lower()] else: # scheme == http/-s try: path = pathmap.IDMAP[p.path[1:].lower()] except KeyError: path = None if path: _url = os.path.join(kwargs["op_arg"]["baseurl"], session_info["test_id"], path[1:]) resp = Response(wf.response(subject=resource, base=_url), content="application/jrd+json") else: resp = BadRequest("Incorrect resource specification") trace.reply(resp.message) dump_log(session_info, trace) return resp(environ, start_response)
def webfinger(environ, start_response, session_info, trace, **kwargs): query = parse_qs(environ["QUERY_STRING"]) # Find the identifier session_info["test_id"] = find_identifier(query["resource"][0]) trace.info(HEADER % "WebFinger") trace.request(environ["QUERY_STRING"]) trace.info("QUERY: %s" % (query, )) try: assert query["rel"] == [OIC_ISSUER] resource = query["resource"][0] except AssertionError: errmsg = "Wrong 'rel' value: %s" % query["rel"][0] trace.error(errmsg) resp = BadRequest(errmsg) except KeyError: errmsg = "Missing 'rel' parameter in request" trace.error(errmsg) resp = BadRequest(errmsg) else: wf = WebFinger() p = urlparse(resource) if p.scheme == "acct": l, _ = p.path.split("@") path = pathmap.IDMAP[l.lower()] else: # scheme == http/-s try: path = pathmap.IDMAP[p.path[1:].lower()] except KeyError: path = None if path: _url = os.path.join(kwargs["op_arg"]["baseurl"], session_info["test_id"], path[1:]) resp = Response(wf.response(subject=resource, base=_url), content="application/jrd+json") else: resp = BadRequest("Incorrect resource specification") trace.reply(resp.message) dump_log(session_info, trace) return resp(environ, start_response)
def webfinger(environ, start_response, session_info, events, jlog, **kwargs): _query = session_info['parameters'] events.store(EV_REQUEST, Operation("WebFinger", _query)) try: assert _query["rel"] == [OIC_ISSUER] resource = _query["resource"][0] except AssertionError: errmsg = "Wrong 'rel' value: %s" % _query["rel"][0] events.store(EV_FAULT, errmsg) resp = BadRequest(errmsg) except KeyError: errmsg = "Missing 'rel' parameter in request" events.store(EV_FAULT, errmsg) resp = BadRequest(errmsg) else: wf = WebFinger() _url = os.path.join(kwargs["op_arg"]["baseurl"], session_info['oper_id'], session_info["test_id"]) _mesg = wf.response(subject=resource, base=_url) if session_info['test_id'] == 'rp-discovery-webfinger-http-href': _msg = json.loads(_mesg) _msg['links'][0]['href'] = _msg['links'][0]['href'].replace( 'https', 'http') _mesg = json.dumps(_msg) elif session_info['test_id'] == 'rp-discovery-webfinger-unknown-member': _msg = json.loads(_mesg) _msg['dummy'] = 'foobar' _mesg = json.dumps(_msg) resp = Response(_mesg, content="application/jrd+json") events.store(EV_RESPONSE, resp.message) jlog.info(resp2json(resp)) dump_log(session_info, events) return resp(environ, start_response)
def webfinger(environ, start_response, session_info, events, jlog, **kwargs): _query = session_info['parameters'] events.store(EV_REQUEST, Operation("WebFinger", _query)) try: assert _query["rel"] == [OIC_ISSUER] resource = _query["resource"][0] except AssertionError: errmsg = "Wrong 'rel' value: %s" % _query["rel"][0] events.store(EV_FAULT, errmsg) resp = BadRequest(errmsg) except KeyError: errmsg = "Missing 'rel' parameter in request" events.store(EV_FAULT, errmsg) resp = BadRequest(errmsg) else: wf = WebFinger() _url = os.path.join(kwargs["op_arg"]["baseurl"], session_info['oper_id'], session_info["test_id"]) _mesg = wf.response(subject=resource, base=_url) if session_info['test_id'] == 'rp-discovery-webfinger-http-href': _msg = json.loads(_mesg) _msg['links'][0]['href'] = _msg['links'][0]['href'].replace( 'https', 'http') _mesg = json.dumps(_msg) elif session_info[ 'test_id'] == 'rp-discovery-webfinger-unknown-member': _msg = json.loads(_mesg) _msg['dummy'] = 'foobar' _mesg = json.dumps(_msg) resp = Response(_mesg, content="application/jrd+json") events.store(EV_RESPONSE, resp.message) jlog.info(resp2json(resp)) dump_log(session_info, events) return resp(environ, start_response)
def webfinger(environ, start_response, session, trace): query = parse_qs(environ["QUERY_STRING"]) # Find the identifier session["test_id"] = find_identifier(query["resource"][0]) trace.info(HEADER % "WebFinger") trace.request(environ["QUERY_STRING"]) trace.info("QUERY: %s" % (query,)) try: assert query["rel"] == [OIC_ISSUER] resource = query["resource"][0] except AssertionError: errmsg = "Wrong 'rel' value: %s" % query["rel"][0] trace.error(errmsg) resp = BadRequest(errmsg) except KeyError: errmsg = "Missing 'rel' parameter in request" trace.error(errmsg) resp = BadRequest(errmsg) else: wf = WebFinger() p = urlparse(resource) if p.scheme == "acct": l, _ = p.path.split("@") path = pathmap.IDMAP[l] else: # scheme == http/-s path = pathmap.IDMAP[p.path[1:]] _url = os.path.join(OP_ARG["baseurl"], session["test_id"], path[1:]) resp = Response(wf.response(subject=resource, base=_url)) trace.reply(resp.message) dump_log(session, trace) return resp(environ, start_response)
class MyFakeOICServer(Server): def __init__(self, name=""): Server.__init__(self) self.sdb = SessionDB() self.name = name self.client = {} self.registration_expires_in = 3600 self.host = "" self.webfinger = WebFinger() #noinspection PyUnusedLocal def http_request(self, path, method="GET", **kwargs): part = urlparse(path) path = part[2] query = part[4] self.host = "%s://%s" % (part.scheme, part.netloc) response = Response response.status_code = 500 response.text = "" if path == ENDPOINT["authorization_endpoint"]: assert method == "GET" response = self.authorization_endpoint(query) elif path == ENDPOINT["token_endpoint"]: assert method == "POST" response = self.token_endpoint(kwargs["data"]) elif path == ENDPOINT["user_info_endpoint"]: assert method == "POST" response = self.userinfo_endpoint(kwargs["data"]) elif path == ENDPOINT["refresh_session_endpoint"]: assert method == "GET" response = self.refresh_session_endpoint(query) elif path == ENDPOINT["check_session_endpoint"]: assert method == "GET" response = self.check_session_endpoint(query) elif path == ENDPOINT["end_session_endpoint"]: assert method == "GET" response = self.end_session_endpoint(query) elif path == ENDPOINT["registration_endpoint"]: if method == "POST": response = self.registration_endpoint(kwargs["data"]) elif path == "/.well-known/webfinger": assert method == "GET" qdict = parse_qs(query) response.status_code = 200 response.text = self.webfinger.response(qdict["resource"][0], "%s/" % self.name) elif path == "/.well-known/openid-configuration": assert method == "GET" response = self.openid_conf() return response def authorization_endpoint(self, query): req = self.parse_authorization_request(query=query) sid = self.sdb.create_authz_session(sub="user", areq=req) _info = self.sdb[sid] _info["sub"] = _info["local_sub"] if "code" in req["response_type"]: if "token" in req["response_type"]: grant = _info["code"] _dict = self.sdb.upgrade_to_token(grant) _dict["oauth_state"] = "authz", _dict = by_schema(AuthorizationResponse(), **_dict) resp = AuthorizationResponse(**_dict) #resp.code = grant else: resp = AuthorizationResponse(state=req["state"], code=_info["code"]) else: # "implicit" in req.response_type: grant = _info["code"] params = AccessTokenResponse.c_param.keys() _dict = dict([(k, v) for k, v in self.sdb.upgrade_to_token(grant).items() if k in params]) try: del _dict["refresh_token"] except KeyError: pass if "id_token" in req["response_type"]: _idt = self.make_id_token(_info, issuer=self.name, access_token=_dict["access_token"]) alg = "RS256" ckey = self.keyjar.get_signing_key(alg2keytype(alg), _info["client_id"]) _dict["id_token"] = _idt.to_jwt(key=ckey, algorithm=alg) resp = AccessTokenResponse(**_dict) location = resp.request(req["redirect_uri"]) response = Response() response.headers = {"location": location} response.status_code = 302 response.text = "" return response def token_endpoint(self, data): if "grant_type=refresh_token" in data: req = self.parse_refresh_token_request(body=data) _info = self.sdb.refresh_token(req["refresh_token"]) elif "grant_type=authorization_code": req = self.parse_token_request(body=data) _info = self.sdb.upgrade_to_token(req["code"]) else: response = TokenErrorResponse(error="unsupported_grant_type") return response, "" resp = AccessTokenResponse(**by_schema(AccessTokenResponse, **_info)) response = Response() response.headers = {"content-type": "application/json"} response.text = resp.to_json() return response def userinfo_endpoint(self, data): _ = self.parse_user_info_request(data) _info = { "sub": "melgar", "name": "Melody Gardot", "nickname": "Mel", "email": "*****@*****.**", "verified": True, } resp = OpenIDSchema(**_info) response = Response() response.headers = {"content-type": "application/json"} response.text = resp.to_json() return response def registration_endpoint(self, data): try: req = self.parse_registration_request(data, "json") except ValueError: req = self.parse_registration_request(data) client_secret = rndstr() expires = utc_time_sans_frac() + self.registration_expires_in kwargs = {} if "client_id" not in req: client_id = rndstr(10) registration_access_token = rndstr(20) _client_info = req.to_dict() kwargs.update(_client_info) _client_info.update({ "client_secret": client_secret, "info": req.to_dict(), "expires": expires, "registration_access_token": registration_access_token, "registration_client_uri": "register_endpoint" }) self.client[client_id] = _client_info kwargs["registration_access_token"] = registration_access_token kwargs["registration_client_uri"] = "register_endpoint" try: del kwargs["operation"] except KeyError: pass else: client_id = req.client_id _cinfo = self.client[req.client_id] _cinfo["info"].update(req.to_dict()) _cinfo["client_secret"] = client_secret _cinfo["expires"] = expires resp = RegistrationResponse(client_id=client_id, client_secret=client_secret, client_secret_expires_at=expires, **kwargs) response = Response() response.headers = {"content-type": "application/json"} response.text = resp.to_json() return response def check_session_endpoint(self, query): try: idtoken = self.parse_check_session_request(query=query) except Exception: raise response = Response() response.text = idtoken.to_json() response.headers = {"content-type": "application/json"} return response #noinspection PyUnusedLocal def refresh_session_endpoint(self, query): try: req = self.parse_refresh_session_request(query=query) except Exception: raise resp = RegistrationResponse(client_id="anonymous", client_secret="hemligt") response = Response() response.headers = {"content-type": "application/json"} response.text = resp.to_json() return response def end_session_endpoint(self, query): try: req = self.parse_end_session_request(query=query) except Exception: raise # redirect back resp = EndSessionResponse(state=req["state"]) url = resp.request(req["redirect_url"]) response = Response() response.headers = {"location": url} response.status_code = 302 # redirect response.text = "" return response #noinspection PyUnusedLocal def add_credentials(self, user, passwd): return def openid_conf(self): endpoint = {} for point, path in ENDPOINT.items(): endpoint[point] = "%s%s" % (self.host, path) signing_algs = jws.SIGNER_ALGS.keys() resp = ProviderConfigurationResponse( issuer=self.name, scopes_supported=["openid", "profile", "email", "address"], identifiers_supported=["public", "PPID"], flows_supported=["code", "token", "code token", "id_token", "code id_token", "token id_token"], subject_types_supported=["pairwise", "public"], response_types_supported=["code", "token", "id_token", "code token", "code id_token", "token id_token", "code token id_token"], jwks_uri="http://example.com/oidc/jwks", id_token_signing_alg_values_supported=signing_algs, grant_types_supported=["authorization_code", "implicit"], **endpoint) response = Response() response.headers = {"content-type": "application/json"} response.text = resp.to_json() return response
class MyFakeOICServer(Server): def __init__(self, name=""): Server.__init__(self) self.sdb = SessionDB(name) self.name = name self.client = {} self.registration_expires_in = 3600 self.host = "" self.webfinger = WebFinger() self.userinfo_signed_response_alg = "" def http_request(self, path, method="GET", **kwargs): part = urlparse(path) path = part[2] query = part[4] self.host = "%s://%s" % (part.scheme, part.netloc) response = Response response.status_code = 500 response.text = "" if path == ENDPOINT["authorization_endpoint"]: assert method == "GET" response = self.authorization_endpoint(query) elif path == ENDPOINT["token_endpoint"]: assert method == "POST" response = self.token_endpoint(kwargs["data"]) elif path == ENDPOINT["user_info_endpoint"]: assert method == "POST" response = self.userinfo_endpoint(kwargs["data"]) elif path == ENDPOINT["refresh_session_endpoint"]: assert method == "GET" response = self.refresh_session_endpoint(query) elif path == ENDPOINT["check_session_endpoint"]: assert method == "GET" response = self.check_session_endpoint(query) elif path == ENDPOINT["end_session_endpoint"]: assert method == "GET" response = self.end_session_endpoint(query) elif path == ENDPOINT["registration_endpoint"]: if method == "POST": response = self.registration_endpoint(kwargs["data"]) elif path == "/.well-known/webfinger": assert method == "GET" qdict = parse_qs(query) response.status_code = 200 response.text = self.webfinger.response(qdict["resource"][0], "%s/" % self.name) elif path == "/.well-known/openid-configuration": assert method == "GET" response = self.openid_conf() return response def authorization_endpoint(self, query): req = self.parse_authorization_request(query=query) aevent = AuthnEvent("user", "salt", authn_info="acr") sid = self.sdb.create_authz_session(aevent, areq=req) self.sdb.do_sub(sid, "client_salt") _info = self.sdb[sid] if "code" in req["response_type"]: if "token" in req["response_type"]: grant = _info["code"] if 'offline_access' in _info['scope']: _dict = self.sdb.upgrade_to_token(grant, issue_refresh=True) else: _dict = self.sdb.upgrade_to_token(grant) _dict["oauth_state"] = "authz", _dict = by_schema(AuthorizationResponse(), **_dict) resp = AuthorizationResponse(**_dict) # resp.code = grant else: _state = req["state"] resp = AuthorizationResponse(state=_state, code=_info["code"]) else: # "implicit" in req.response_type: grant = _info["code"] params = AccessTokenResponse.c_param.keys() _dict = dict([(k, v) for k, v in self.sdb.upgrade_to_token(grant).items() if k in params]) try: del _dict["refresh_token"] except KeyError: pass if "id_token" in req["response_type"]: _idt = self.make_id_token(_info, issuer=self.name, access_token=_dict["access_token"]) alg = "RS256" ckey = self.keyjar.get_signing_key(alg2keytype(alg), _info["client_id"]) _dict["id_token"] = _idt.to_jwt(key=ckey, algorithm=alg) resp = AccessTokenResponse(**_dict) location = resp.request(req["redirect_uri"]) response = Response() response.headers = {"location": location} response.status_code = 302 response.text = "" return response def token_endpoint(self, data): if "grant_type=refresh_token" in data: req = self.parse_refresh_token_request(body=data) _info = self.sdb.refresh_token(req["refresh_token"], req['client_id']) elif "grant_type=authorization_code" in data: req = self.parse_token_request(body=data) if 'offline_access' in self.sdb[req['code']]['scope']: _info = self.sdb.upgrade_to_token(req["code"], issue_refresh=True) else: _info = self.sdb.upgrade_to_token(req["code"]) else: response = TokenErrorResponse(error="unsupported_grant_type") return response, "" resp = AccessTokenResponse(**by_schema(AccessTokenResponse, **_info)) response = Response() response.headers = {"content-type": "application/json"} response.text = resp.to_json() return response def userinfo_endpoint(self, data): self.parse_user_info_request(data) _info = { "sub": "melgar", "name": "Melody Gardot", "nickname": "Mel", "email": "*****@*****.**", "verified": True, } resp = OpenIDSchema(**_info) response = Response() if self.userinfo_signed_response_alg: alg = self.userinfo_signed_response_alg response.headers = {"content-type": "application/jwt"} key = self.keyjar.get_signing_key(alg2keytype(alg), "", alg=alg) response.text = resp.to_jwt(key, alg) else: response.headers = {"content-type": "application/json"} response.text = resp.to_json() return response def registration_endpoint(self, data): try: req = self.parse_registration_request(data, "json") except ValueError: req = self.parse_registration_request(data) client_secret = rndstr() expires = utc_time_sans_frac() + self.registration_expires_in kwargs = {} if "client_id" not in req: client_id = rndstr(10) registration_access_token = rndstr(20) _client_info = req.to_dict() kwargs.update(_client_info) _client_info.update({ "client_secret": client_secret, "info": req.to_dict(), "expires": expires, "registration_access_token": registration_access_token, "registration_client_uri": "register_endpoint" }) self.client[client_id] = _client_info kwargs["registration_access_token"] = registration_access_token kwargs["registration_client_uri"] = "register_endpoint" try: del kwargs["operation"] except KeyError: pass else: client_id = req.client_id _cinfo = self.client[req.client_id] _cinfo["info"].update(req.to_dict()) _cinfo["client_secret"] = client_secret _cinfo["expires"] = expires resp = RegistrationResponse(client_id=client_id, client_secret=client_secret, client_secret_expires_at=expires, **kwargs) response = Response() response.headers = {"content-type": "application/json"} response.text = resp.to_json() return response def check_session_endpoint(self, query): try: idtoken = self.parse_check_session_request(query=query) except Exception: raise response = Response() response.text = idtoken.to_json() response.headers = {"content-type": "application/json"} return response def refresh_session_endpoint(self, query): self.parse_refresh_session_request(query=query) resp = RegistrationResponse(client_id="anonymous", client_secret="hemligt") response = Response() response.headers = {"content-type": "application/json"} response.text = resp.to_json() return response def end_session_endpoint(self, query): try: req = self.parse_end_session_request(query=query) except Exception: raise # redirect back resp = EndSessionResponse(state=req["state"]) url = resp.request(req["redirect_url"]) response = Response() response.headers = {"location": url} response.status_code = 302 # redirect response.text = "" return response @staticmethod def add_credentials(user, passwd): pass def openid_conf(self): endpoint = {} for point, path in ENDPOINT.items(): endpoint[point] = "%s%s" % (self.host, path) signing_algs = list(jws.SIGNER_ALGS.keys()) resp = ProviderConfigurationResponse( issuer=self.name, scopes_supported=["openid", "profile", "email", "address"], identifiers_supported=["public", "PPID"], flows_supported=[ "code", "token", "code token", "id_token", "code id_token", "token id_token" ], subject_types_supported=["pairwise", "public"], response_types_supported=[ "code", "token", "id_token", "code token", "code id_token", "token id_token", "code token id_token" ], jwks_uri="http://example.com/oidc/jwks", id_token_signing_alg_values_supported=signing_algs, grant_types_supported=["authorization_code", "implicit"], **endpoint) response = Response() response.headers = {"content-type": "application/json"} response.text = resp.to_json() return response