def registration_endpoint(self, request, environ, **kwargs): """ :param request: The request :param authn: Client authentication information :param kwargs: extra keyword arguments :return: A Response instance """ _request = RegistrationRequest().deserialize(request, "json") try: _request.verify() except InvalidRedirectUri as err: msg = ClientRegistrationError(error="invalid_redirect_uri", error_description="%s" % err) return BadRequest(msg.to_json(), content="application/json") except (MissingPage, VerificationError) as err: msg = ClientRegistrationError(error="invalid_client_metadata", error_description="%s" % err) return BadRequest(msg.to_json(), content="application/json") # authenticated client if self.authn_at_registration: try: _ = self.verify_client(environ, _request, self.authn_at_registration) except (AuthnFailure, UnknownAssertionType): return Unauthorized() client_id = self.create_new_client(_request) return self.client_info(client_id)
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 client_info_endpoint(self, method="GET", **kwargs): """ Operations on this endpoint are switched through the use of different HTTP methods. :param method: HTTP method used for the request :param kwargs: keyword arguments :return: A Response instance """ _query = compact(parse_qs(kwargs["query"])) try: _id = _query["client_id"] except KeyError: return BadRequest("Missing query component") if _id not in self.cdb: return Unauthorized() # authenticated client try: self.verify_client( kwargs["environ"], kwargs["request"], "bearer_header", client_id=_id ) except (AuthnFailure, UnknownAssertionType): return Unauthorized() if method == "GET": return self.client_info(_id) elif method == "PUT": try: _request = self.server.message_factory.get_request_type( "update_endpoint" )().from_json(kwargs["request"]) except ValueError as err: return BadRequest(str(err)) try: _request.verify() except InvalidRedirectUri as err: msg = ClientRegistrationError( error="invalid_redirect_uri", error_description="%s" % err ) return BadRequest(msg.to_json(), content="application/json") except (MissingPage, VerificationError) as err: msg = ClientRegistrationError( error="invalid_client_metadata", error_description="%s" % err ) return BadRequest(msg.to_json(), content="application/json") try: self.client_info_update(_id, _request) return self.client_info(_id) except ModificationForbidden: return Forbidden() elif method == "DELETE": try: del self.cdb[_id] except KeyError: return Unauthorized() else: return NoContent()
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 client_info_endpoint(self, request, environ, method="GET", query="", **kwargs): """ Operations on this endpoint are switched through the use of different HTTP methods :param request: The request :param authn: Client authentication information :param method: HTTP method used for the request :param query: The query part of the URL used, this is where the client_id is supposed to reside. :param kwargs: extra keyword arguments :return: A Response instance """ _query = urlparse.parse_qs(query) try: _id = _query["client_id"][0] except KeyError: return BadRequest("Missing query component") try: assert _id in self.cdb except AssertionError: return Unauthorized() # authenticated client try: _ = self.verify_client(environ, request, "bearer_header", client_id=_id) except (AuthnFailure, UnknownAssertionType): return Unauthorized() if method == "GET": return self.client_info(_id) elif method == "PUT": try: _request = ClientUpdateRequest().from_json(request) except ValueError: return BadRequest() try: _request.verify() except InvalidRedirectUri, err: msg = ClientRegistrationError(error="invalid_redirect_uri", error_description="%s" % err) return BadRequest(msg.to_json(), content="application/json") except (MissingPage, VerificationError), err: msg = ClientRegistrationError(error="invalid_client_metadata", error_description="%s" % err) return BadRequest(msg.to_json(), content="application/json")
def registration_endpoint(self, **kwargs): """ Perform dynamic client registration. :param request: The request :param authn: Client authentication information :param kwargs: extra keyword arguments :return: A Response instance """ _request = self.server.message_factory.get_request_type( "registration_endpoint" )().deserialize(kwargs["request"], "json") try: _request.verify(keyjar=self.keyjar) except InvalidRedirectUri as err: msg = ClientRegistrationError( error="invalid_redirect_uri", error_description="%s" % err ) return BadRequest(msg.to_json(), content="application/json") except (MissingPage, VerificationError) as err: msg = ClientRegistrationError( error="invalid_client_metadata", error_description="%s" % err ) return BadRequest(msg.to_json(), content="application/json") # If authentication is necessary at registration if self.authn_at_registration: try: self.verify_client( kwargs["environ"], _request, self.authn_at_registration ) except (AuthnFailure, UnknownAssertionType): return Unauthorized() client_restrictions = {} # type: ignore if "parsed_software_statement" in _request: for ss in _request["parsed_software_statement"]: client_restrictions.update(self.consume_software_statement(ss)) del _request["software_statement"] del _request["parsed_software_statement"] try: client_id = self.create_new_client(_request, client_restrictions) except CapabilitiesMisMatch as err: msg = ClientRegistrationError( error="invalid_client_metadata", error_description="%s" % err ) return BadRequest(msg.to_json(), content="application/json") except RestrictionError as err: msg = ClientRegistrationError( error="invalid_client_metadata", error_description="%s" % err ) return BadRequest(msg.to_json(), content="application/json") return self.client_info(client_id)
def exception_to_error_mesg(excep): if isinstance(excep, PyoidcError): if excep.content_type: if isinstance(excep.args, tuple): resp = BadRequest(excep.args[0], content=excep.content_type) else: resp = BadRequest(excep.args, content=excep.content_type) else: resp = BadRequest() else: err = ErrorResponse(error='service_error', error_description='{}:{}'.format( excep.__class__.__name__, excep.args)) resp = BadRequest(err.to_json(), content='application/json') return resp
def _complete_authz(self, user, areq, sid, **kwargs): _log_debug = logger.debug _log_debug("- in authenticated() -") # Do the authorization try: permission = self.authz(user, client_id=areq['client_id']) self.sdb.update(sid, "permission", permission) except Exception: raise _log_debug("response type: %s" % areq["response_type"]) if self.sdb.is_revoked(sid): return self._error(error="access_denied", descr="Token is revoked") info = self.create_authn_response(areq, sid) if isinstance(info, Response): return info else: aresp, fragment_enc = info try: redirect_uri = self.get_redirect_uri(areq) except (RedirectURIError, ParameterError) as err: return BadRequest("%s" % err) # Must not use HTTP unless implicit grant type and native application info = self.aresp_check(aresp, areq) if isinstance(info, Response): return info headers = [] try: _kaka = kwargs["cookie"] except KeyError: pass else: if _kaka and self.cookie_name not in _kaka: # Don't overwrite cookie headers.append( self.cookie_func(user, typ="sso", ttl=self.sso_ttl)) # Now about the response_mode. Should not be set if it's obvious # from the response_type. Knows about 'query', 'fragment' and # 'form_post'. if "response_mode" in areq: try: resp = self.response_mode(areq, fragment_enc, aresp=aresp, redirect_uri=redirect_uri, headers=headers) except InvalidRequest as err: return self._error("invalid_request", err) else: if resp is not None: return resp return aresp, headers, redirect_uri, fragment_enc
def _complete_authz(self, user, areq, sid, **kwargs): _log_debug = logger.debug _log_debug("- in authenticated() -") # Do the authorization try: permission = self.authz(user, client_id=areq['client_id']) self.sdb.update(sid, "permission", permission) except Exception: raise _log_debug("response type: %s" % areq["response_type"]) if self.sdb.is_revoked(sid): return self._error(error="access_denied", descr="Token is revoked") info = self.create_authn_response(areq, sid) if isinstance(info, Response): return info else: aresp, fragment_enc = info try: redirect_uri = self.get_redirect_uri(areq) except (RedirectURIError, ParameterError), err: return BadRequest("%s" % err)
def safe(environ, start_response): _op = environ["oic.oas"] _srv = _op.server _log_info = _op.logger.info _log_info("- safe -") # _log_info("env: %s" % environ) # _log_info("handle: %s" % (handle,)) try: _authz = environ["HTTP_AUTHORIZATION"] (_typ, code) = _authz.split(" ") assert _typ == "Bearer" except KeyError: resp = BadRequest("Missing authorization information") return resp(environ, start_response) try: _sinfo = _srv.sdb[code] except KeyError: resp = Unauthorized("Not authorized") return resp(environ, start_response) _info = "'%s' secrets" % _sinfo["sub"] resp = Response(_info) return resp(environ, start_response)
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 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(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 verify_endpoint(self, request="", cookie=None, **kwargs): _req = parse_qs(request) try: areq = parse_qs(_req["query"][0]) except KeyError: return BadRequest('Could not verify endpoint') authn, acr = self.pick_auth(areq=areq) kwargs["cookie"] = cookie return authn.verify(_req, **kwargs)
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, 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 replace(self, qiss, qtag, info, path): # read entity configuration and replace if changed try: _js = json.loads(info) except Exception as err: return BadRequest(err) _js0 = self.read_conf(qiss, qtag) if _js == _js0: # don't bother pass else: self.write(qiss, qtag, json.dumps(_js)) return Response('OK')
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)
def client_info(self, client_id): _cinfo = self.cdb[client_id].copy() if not valid_client_info(_cinfo): err = ErrorResponse( error="invalid_client", error_description="Invalid client secret" ) return BadRequest(err.to_json(), content="application/json") try: _cinfo["redirect_uris"] = self._tuples_to_uris(_cinfo["redirect_uris"]) except KeyError: pass msg = self.server.message_factory.get_response_type("update_endpoint")(**_cinfo) return Response(msg.to_json(), content="application/json")
def client_info(self, client_id): _cinfo = self.cdb[client_id].copy() if not valid_client_info(_cinfo): err = ErrorResponse(error="invalid_client", error_description="Invalid client secret") return BadRequest(err.to_json(), content="application/json") try: _cinfo["redirect_uris"] = self._tuples_to_uris( _cinfo["redirect_uris"]) except KeyError: pass msg = ClientInfoResponse(**_cinfo) return Response(msg.to_json(), content="application/json")
def get_token_info(self, authn, req, endpoint): """ Parse token for information. :param authn: :param req: :return: """ try: client_id = self.client_authn(self, req, authn) except FailedAuthentication as err: logger.error(err) error = TokenErrorResponse(error="unauthorized_client", error_description="%s" % err) return Response(error.to_json(), content="application/json", status="401 Unauthorized") logger.debug("{}: {} requesting {}".format(endpoint, client_id, req.to_dict())) try: token_type = req["token_type_hint"] except KeyError: try: _info = self.sdb.token_factory["access_token"].get_info( req["token"]) except Exception: try: _info = self.sdb.token_factory["refresh_token"].get_info( req["token"]) except Exception: return self._return_inactive() else: token_type = "refresh_token" else: token_type = "access_token" else: try: _info = self.sdb.token_factory[token_type].get_info( req["token"]) except Exception: return self._return_inactive() if not self.token_access(endpoint, client_id, _info): return BadRequest() return client_id, token_type, _info
def registration_endpoint(self, request, environ, **kwargs): """ :param request: The request :param authn: Client authentication information :param kwargs: extra keyword arguments :return: A Response instance """ _request = RegistrationRequest().deserialize(request, "json") try: _request.verify() except InvalidRedirectUri, err: msg = ClientRegistrationError(error="invalid_redirect_uri", error_description="%s" % err) return BadRequest(msg.to_json(), content="application/json")
def get_token_info(self, authn, req, endpoint): """ :param authn: :param req: :return: """ try: client_id = self.client_authn(self, req, 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('{}: {} requesting {}'.format(endpoint, client_id, req.to_dict())) try: token_type = req['token_type_hint'] except KeyError: try: _info = self.sdb.token_factory['access_token'].info( req['token']) except KeyError: try: _info = self.sdb.token_factory['refresh_token'].get_info( req['token']) except KeyError: raise else: token_type = 'refresh_token' else: token_type = 'access_token' else: try: _info = self.sdb.token_factory[token_type].get_info( req['token']) except KeyError: raise if not self.token_access(endpoint, client_id, _info): return BadRequest() return client_id, token_type, _info
def test(environ, session, path): _test = path[5:] session["flow_index"] = FLOW_SEQUENCE.index(_test) session["phase_index"] = 0 session["start"] = 0 session["trace"] = Trace() _op = resp = client = link = None try: query = parse_qs(environ["QUERY_STRING"]) except KeyError: pass else: try: session["op"] = query["op"][0] try: assert session["op"] in SERVER_ENV["OP"] _op = session["op_conf"] = SERVER_ENV["OP"][session["op"]] except AssertionError: return BadRequest("OP chosen that is not configured") except KeyError: pass if _op: try: client = SERVER_ENV["OIC_CLIENT"][session["opkey"]] except KeyError: _key = rndstr() try: kwargs = {"deviate": _op["deviate"]} except KeyError: kwargs = {} client = create_client(_key, **kwargs) session["opkey"] = _key SERVER_ENV["OIC_CLIENT"][session["opkey"]] = client if _op["features"]["discovery"]: link = _op["provider"]["dynamic"] session["srv_discovery_url"] = link else: client.handle_provider_config(_op["provider"], session["op"]) else: resp = Redirect("/") if resp: return resp else: return {"client": client, "link": link}
def uid(environ, session, path): query = parse_qs(environ["QUERY_STRING"]) if "uid" in query: try: link = RP.find_srv_discovery_url(resource=query["uid"][0]) except requests.ConnectionError: return ServiceError("Webfinger lookup failed, connection error") session["srv_discovery_url"] = link md5 = hashlib.md5() md5.update(link) opkey = base64.b16encode(md5.digest()) client = create_client(opkey) SERVER_ENV["OIC_CLIENT"][opkey] = client session["opkey"] = opkey return {"client": client, "link": link} else: return BadRequest()
def discovery_endpoint(self, request, handle=None, **kwargs): if isinstance(request, dict): request = DiscoveryRequest(**request) else: request = DiscoveryRequest().deserialize(request, "urlencoded") try: assert request["service"] == SWD_ISSUER except AssertionError: return BadRequest("Unsupported service") _response = DiscoveryResponse(locations=[self.baseurl]) if self.signed_metadata_statements: _response.update( {'metadata_statements': self.signed_metadata_statements}) headers = [("Cache-Control", "no-store")] return Response(_response.to_json(), content="application/json", headers=headers)
def permission_registration_endpoint_(self, request, **kwargs): """ The endpoint URI at which the resource server registers a client-requested permission with the authorization server. This is a proposed permission waiting for the user to accept it. :param request: The permission registration request :return: HTTP Response """ adb = self.get_adb(kwargs['client_id']) prr = self.to_prr(request, kwargs['client_id']) if prr: _ticket = adb.ticket_factory.pack(aud=[kwargs['client_id']], type='ticket') logging.debug("Registering permission request: %s" % request) adb.permission_requests[_ticket] = prr resp = PermissionRegistrationResponse(ticket=_ticket) return Created(resp.to_json(), content="application/json") else: return BadRequest("Can't register permission for unknown resource")
class Provider(provider.Provider): def __init__(self, name, sdb, cdb, authn_broker, authz, client_authn, symkey="", urlmap=None, iv=0, default_scope="", ca_bundle=None, seed="", client_authn_methods=None, authn_at_registration="", client_info_url="", secret_lifetime=86400): provider.Provider.__init__(self, name, sdb, cdb, authn_broker, authz, client_authn, symkey, urlmap, iv, default_scope, ca_bundle) self.endp.extend([RegistrationEndpoint, ClientInfoEndpoint]) # dictionary of client authentication methods self.client_authn_methods = client_authn_methods if authn_at_registration: assert authn_at_registration in client_authn_methods self.authn_at_registration = authn_at_registration self.seed = seed self.client_info_url = client_info_url self.secret_lifetime = secret_lifetime # @staticmethod # def _uris_to_dict(uris): # ruri = {} # for uri in uris: # base, query = urllib.splitquery(uri) # if query: # try: # ruri[base].append(urlparse.parse_qs(query)) # except KeyError: # ruri[base] = [urlparse.parse_qs(query)] # else: # ruri[base] = [""] # return ruri # # @staticmethod # def _dict_to_uris(spec): # _uri = [] # for url, qlist in spec.items(): # for query in qlist: # if query: # _uri.append("%s?%s" % (url, query)) # else: # _uri.append(url) # return _uri @staticmethod def _uris_to_tuples(uris): tup = [] for uri in uris: base, query = urllib.splitquery(uri) if query: tup.append((base, query)) else: tup.append((base, "")) return tup @staticmethod def _tuples_to_uris(items): _uri = [] for url, query in items: if query: _uri.append("%s?%s" % (url, query)) else: _uri.append(url) return _uri def create_new_client(self, request): """ :param request: The Client registration request :return: The client_id """ _cinfo = request.to_dict() # create new id and secret _id = rndstr(12) while _id in self.cdb: _id = rndstr(12) _cinfo["client_id"] = _id _cinfo["client_secret"] = secret(self.seed, _id) _cinfo["client_id_issued_at"] = utc_time_sans_frac() _cinfo["client_secret_expires_at"] = utc_time_sans_frac() + \ self.secret_lifetime # If I support client info endpoint if ClientInfoEndpoint in self.endp: _cinfo["registration_access_token"] = rndstr(32) _cinfo["registration_client_uri"] = "%s%s?client_id=%s" % ( self.client_info_url, ClientInfoEndpoint.etype, _id) if "redirect_uris" in request: _cinfo["redirect_uris"] = self._uris_to_tuples( request["redirect_uris"]) self.cdb[_id] = _cinfo return _id def client_info(self, client_id): _cinfo = self.cdb[client_id].copy() try: _cinfo["redirect_uris"] = self._tuples_to_uris( _cinfo["redirect_uris"]) except KeyError: pass msg = ClientInfoResponse(**_cinfo) return Response(msg.to_json(), content="application/json") def client_info_update(self, client_id, request): _cinfo = self.cdb[client_id].copy() try: _cinfo["redirect_uris"] = self._tuples_to_uris( _cinfo["redirect_uris"]) except KeyError: pass for key, value in request.items(): if key in ["client_secret", "client_id"]: # assure it's the same try: assert value == _cinfo[key] except AssertionError: raise ModificationForbidden("Not allowed to change") else: _cinfo[key] = value for key in _cinfo.keys(): if key in [ "client_id_issued_at", "client_secret_expires_at", "registration_access_token", "registration_client_uri" ]: continue if key not in request: del _cinfo[key] if "redirect_uris" in request: _cinfo["redirect_uris"] = self._uris_to_tuples( request["redirect_uris"]) self.cdb[client_id] = _cinfo def verify_client(self, environ, areq, authn_method, client_id=""): """ :param environ: WSGI environ :param areq: The request :param authn_method: client authentication method :return: """ if not client_id: client_id = self.get_client_id(areq, environ["HTTP_AUTHORIZATION"]) try: method = self.client_authn_methods[authn_method] except KeyError: raise UnSupported() return method(self).verify(environ, client_id=client_id) def registration_endpoint(self, request, environ, **kwargs): """ :param request: The request :param authn: Client authentication information :param kwargs: extra keyword arguments :return: A Response instance """ _request = RegistrationRequest().deserialize(request, "json") try: _request.verify() except InvalidRedirectUri, err: msg = ClientRegistrationError(error="invalid_redirect_uri", error_description="%s" % err) return BadRequest(msg.to_json(), content="application/json") except (MissingPage, VerificationError), err: msg = ClientRegistrationError(error="invalid_client_metadata", error_description="%s" % err) return BadRequest(msg.to_json(), content="application/json")
def _complete_authz(self, user, areq, sid, **kwargs): _log_debug = logger.debug _log_debug("- in authenticated() -") # Do the authorization try: permission = self.authz(user, client_id=areq['client_id']) self.sdb.update(sid, "permission", permission) except Exception: raise _log_debug("response type: %s" % areq["response_type"]) if self.sdb.is_revoked(sid): return error_response("access_denied", descr="Token is revoked") try: info = self.create_authn_response(areq, sid) except UnSupported as err: return error_response(*err.args) if isinstance(info, Response): return info else: aresp, fragment_enc = info try: redirect_uri = self.get_redirect_uri(areq) except (RedirectURIError, ParameterError) as err: return BadRequest("%s" % err) # Must not use HTTP unless implicit grant type and native application info = self.aresp_check(aresp, areq) if isinstance(info, Response): return info headers = [] try: _kaka = kwargs["cookie"] except KeyError: pass else: if _kaka: if isinstance(_kaka, dict): for name, val in _kaka.items(): _c = SimpleCookie() _c[name] = val _x = _c.output() if PY2: _x = str(_x) headers.append(tuple(_x.split(": ", 1))) else: _c = SimpleCookie() _c.load(_kaka) for x in _c.output().split('\r\n'): if PY2: x = str(x) headers.append(tuple(x.split(": ", 1))) if self.cookie_name not in _kaka: # Don't overwrite header = self.cookie_func(user, typ="sso", ttl=self.sso_ttl) if header: headers.append(header) else: header = self.cookie_func(user, typ="sso", ttl=self.sso_ttl) if header: headers.append(header) # Now about the response_mode. Should not be set if it's obvious # from the response_type. Knows about 'query', 'fragment' and # 'form_post'. if "response_mode" in areq: try: resp = self.response_mode(areq, fragment_enc, aresp=aresp, redirect_uri=redirect_uri, headers=headers) except InvalidRequest as err: return error_response("invalid_request", str(err)) else: if resp is not None: return resp return aresp, headers, redirect_uri, fragment_enc
def auth_init(self, request, request_class=AuthorizationRequest): """ :param request: The AuthorizationRequest :return: """ logger.debug("Request: '%s'" % sanitize(request)) # Same serialization used for GET and POST try: areq = self.server.parse_authorization_request( request=request_class, query=request) except (MissingRequiredValue, MissingRequiredAttribute, AuthzError) as err: logger.debug("%s" % err) areq = request_class() areq.lax = True if isinstance(request, dict): areq.from_dict(request) else: areq.deserialize(request, "urlencoded") try: redirect_uri = self.get_redirect_uri(areq) except (RedirectURIError, ParameterError, UnknownClient) as err: return error_response("invalid_request", "%s" % err) try: _rtype = areq["response_type"] except KeyError: _rtype = ["code"] try: _state = areq["state"] except KeyError: _state = '' return redirect_authz_error("invalid_request", redirect_uri, "%s" % err, _state, _rtype) except KeyError: areq = request_class().deserialize(request, "urlencoded") # verify the redirect_uri try: self.get_redirect_uri(areq) except (RedirectURIError, ParameterError) as err: return error_response("invalid_request", "%s" % err) except Exception as err: message = traceback.format_exception(*sys.exc_info()) logger.error(message) logger.debug("Bad request: %s (%s)" % (err, err.__class__.__name__)) err = ErrorResponse(error='invalid_request', error_description=str(err)) return BadRequest(err.to_json(), content='application/json') if not areq: logger.debug("No AuthzRequest") return error_response("invalid_request", "Can not parse AuthzRequest") areq = self.filter_request(areq) if self.events: self.events.store('Protocol request', areq) try: _cinfo = self.cdb[areq['client_id']] except KeyError: logger.error( 'Client ID ({}) not in client database'.format( areq['client_id'])) return error_response('unauthorized_client', 'unknown client') else: try: _registered = [set(rt.split(' ')) for rt in _cinfo['response_types']] except KeyError: # If no response_type is registered by the client then we'll # code which it the default according to the OIDC spec. _registered = [{'code'}] _wanted = set(areq["response_type"]) if _wanted not in _registered: return error_response("invalid_request", "Trying to use unregistered response_typ") logger.debug("AuthzRequest: %s" % (sanitize(areq.to_dict()),)) try: redirect_uri = self.get_redirect_uri(areq) except (RedirectURIError, ParameterError, UnknownClient) as err: return error_response("invalid_request", "{}:{}".format(err.__class__.__name__, err)) try: keyjar = self.keyjar except AttributeError: keyjar = "" try: # verify that the request message is correct areq.verify(keyjar=keyjar, opponent_id=areq["client_id"]) except (MissingRequiredAttribute, ValueError, MissingRequiredValue) as err: return redirect_authz_error("invalid_request", redirect_uri, "%s" % err) return {"areq": areq, "redirect_uri": redirect_uri}