Exemplo n.º 1
0
    async def basic_auth(request, handler):
        basic_auth = request.headers.get('Authorization')
        if basic_auth:
            auth = BasicAuth.decode(basic_auth)
            if handler.auth_role in check_passwd(pwd_db, auth.login, auth.password):
                return await handler(request)

        headers = {'WWW-Authenticate': 'Basic realm="XXX"'}
        return web.HTTPUnauthorized(headers=headers)
Exemplo n.º 2
0
async def test_auth_legacy_support_api_password_access(app, aiohttp_client):
    """Test access using api_password if auth.support_legacy."""
    setup_auth(app, [], True, support_legacy=True, api_password=API_PASSWORD)
    client = await aiohttp_client(app)

    req = await client.get('/', headers={HTTP_HEADER_HA_AUTH: API_PASSWORD})
    assert req.status == 200

    resp = await client.get('/', params={'api_password': API_PASSWORD})
    assert resp.status == 200

    req = await client.get('/', auth=BasicAuth('homeassistant', API_PASSWORD))
    assert req.status == 200
Exemplo n.º 3
0
    def __init__(self, app=None):
        self.logger = init_logger('test.aiohttp.bitcoin.rpcclient',
                                  log_level=logging.DEBUG,
                                  propagate=False)

        self.app = app
        config = app['config']
        customer_records = config.get('customer_records')[0]
        login = customer_records.get('bitcoin_rpc_username')
        password = customer_records.get('bitcoin_rpc_password')
        self.url = "http://{0}".format(
            customer_records.get('bitcoin_rpc_address'))
        self.auth = BasicAuth(login=login, password=password)
Exemplo n.º 4
0
async def test_basic_auth_works(app, aiohttp_client, hass, legacy_auth):
    """Test access with basic authentication."""
    setup_auth(app, [], api_password=API_PASSWORD)
    client = await aiohttp_client(app)
    user = await legacy_api_password.async_get_user(hass)

    req = await client.get('/', auth=BasicAuth('homeassistant', API_PASSWORD))
    assert req.status == 200
    assert await req.json() == {
        'refresh_token_id': None,
        'user_id': user.id,
    }

    req = await client.get('/', auth=BasicAuth('wrong_username', API_PASSWORD))
    assert req.status == 401

    req = await client.get('/',
                           auth=BasicAuth('homeassistant', 'wrong password'))
    assert req.status == 401

    req = await client.get('/', headers={'authorization': 'NotBasic abcdefg'})
    assert req.status == 401
Exemplo n.º 5
0
 def __init__(self):
     vault = Vault()
     secret = vault.load_secret("snow_service")
     self.auth = BasicAuth(login=secret.get("user"),
                           password=secret.get("pwd"),
                           encoding="utf-8")
     try:
         snow_instance = secret.get("instance")
         self.base_api_url = f"https://{snow_instance}/api/now"
         self._session = None
     except ConnectionError as e:
         logger.error("Unable to connect to ServiceNow.")
         logger.error(e)
Exemplo n.º 6
0
async def test_auth_active_blocked_api_password_access(app, aiohttp_client):
    """Test access using api_password should be blocked when auth.active."""
    setup_auth(app, [], True, api_password=API_PASSWORD)
    client = await aiohttp_client(app)

    req = await client.get('/', headers={HTTP_HEADER_HA_AUTH: API_PASSWORD})
    assert req.status == 401

    resp = await client.get('/', params={'api_password': API_PASSWORD})
    assert resp.status == 401

    req = await client.get('/', auth=BasicAuth('homeassistant', API_PASSWORD))
    assert req.status == 401
async def test_auth_and_restart(reader, ui_server, config: Config, server,
                                restarter, coord: Coordinator):
    update = {
        "config": {
            "require_login": True,
            "expose_extra_server": True
        },
        "snapshot_folder": "unused"
    }
    assert ui_server._starts == 1
    assert not config.get(Setting.REQUIRE_LOGIN)
    assert await reader.postjson("saveconfig", json=update) == {
        'message': 'Settings saved'
    }
    await restarter.waitForRestart()
    assert config.get(Setting.REQUIRE_LOGIN)
    assert server._options['require_login']
    assert ui_server._starts == 2

    await reader.get("getstatus", status=401, ingress=False)
    await reader.get("getstatus",
                     auth=BasicAuth("user", "badpassword"),
                     status=401,
                     ingress=False)
    await reader.get("getstatus",
                     auth=BasicAuth("user", "pass"),
                     ingress=False)
    await coord.waitForSyncToFinish()
    status = await reader.getjson("getstatus",
                                  auth=BasicAuth("user", "pass"),
                                  ingress=False)

    # verify a the sync succeeded (no errors)
    assert status["last_error"] is None

    # The ingress server shouldn't require login, even though its turned on for the extra server
    await reader.get("getstatus")
    # even a bad user/pass should work
    await reader.get("getstatus", auth=BasicAuth("baduser", "badpassword"))
Exemplo n.º 8
0
    async def _async_send_remote_file_message(
        self,
        url: str,
        targets: list[str],
        message: str,
        title: str | None,
        *,
        username: str | None = None,
        password: str | None = None,
    ) -> None:
        """Upload a remote file (with message) to Slack.

        Note that we bypass the python-slackclient WebClient and use aiohttp directly,
        as the former would require us to download the entire remote file into memory
        first before uploading it to Slack.
        """
        if not self._hass.config.is_allowed_external_url(url):
            _LOGGER.error("URL is not allowed: %s", url)
            return

        filename = _async_get_filename_from_url(url)
        session = aiohttp_client.async_get_clientsession(self._hass)

        kwargs: AuthDictT = {}
        if username and password is not None:
            kwargs = {"auth": BasicAuth(username, password=password)}

        resp = await session.request("get", url, **kwargs)

        try:
            resp.raise_for_status()
        except ClientError as err:
            _LOGGER.error("Error while retrieving %s: %r", url, err)
            return

        form_data: FormDataT = {
            "channels": ",".join(targets),
            "filename": filename,
            "initial_comment": message,
            "title": title or filename,
            "token": self._client.token,
        }

        data = FormData(form_data, charset="utf-8")
        data.add_field("file", resp.content, filename=filename)

        try:
            await session.post("https://www.slack.com/api/files.upload",
                               data=data)
        except ClientError as err:
            _LOGGER.error("Error while uploading file message: %r", err)
Exemplo n.º 9
0
def _build_req_args(
    *,
    token: Optional[str],
    http_verb: str,
    files: dict,
    data: Union[dict, FormData],
    params: dict,
    json: dict,  # skipcq: PYL-W0621
    headers: dict,
    auth: dict,
    ssl: Optional[SSLContext],
    proxy: Optional[str],
) -> dict:
    has_json = json is not None
    has_files = files is not None
    if has_json and http_verb != "POST":
        msg = "Json data can only be submitted as POST requests. GET requests should use the 'params' argument."
        raise SlackRequestError(msg)

    if auth:
        auth = BasicAuth(auth["client_id"], auth["client_secret"])

    if data is not None and isinstance(data, dict):
        data = {k: v for k, v in data.items() if v is not None}
    if files is not None and isinstance(files, dict):
        files = {k: v for k, v in files.items() if v is not None}
    if params is not None and isinstance(params, dict):
        params = {k: v for k, v in params.items() if v is not None}

    token: Optional[str] = token
    if params is not None and "token" in params:
        token = params.pop("token")
    if json is not None and "token" in json:
        token = json.pop("token")
    req_args = {
        "headers": _get_headers(
            headers=headers,
            token=token,
            has_json=has_json,
            has_files=has_files,
            request_specific_headers=headers,
        ),
        "data": data,
        "files": files,
        "params": params,
        "json": json,
        "ssl": ssl,
        "proxy": proxy,
        "auth": auth,
    }
    return req_args
Exemplo n.º 10
0
async def test_get_slack_mappings(aiohttp_client: TestClient) -> None:
    config = Configuration()
    auth = BasicAuth(config.username, config.password)
    slack = MockSlackClient()
    slack.add_user("U1", "githubuser")
    slack.add_user("U2", "otheruser")

    app = await create_app(slack=slack)
    client = await aiohttp_client(app)

    response = await client.get("/checkerboard/slack", auth=auth)
    assert response.status == 200
    data = await response.json()
    assert data == {"U1": "githubuser", "U2": "otheruser"}
Exemplo n.º 11
0
async def transfer_json():
    # Load settings file
    settings = None
    with elapsedtime("loading_settings"):
        cfg_file = pathlib.Path.cwd() / "settings" / "settings.json"
        if not cfg_file.is_file():
            raise Exception("No setting file")
        settings = json.loads(cfg_file.read_text())
    # Load JSON
    employee_map = {}
    org_unit_map = {}
    # TODO: Asyncio to write both files at once?
    with elapsedtime("loading_employees"):
        with open("tmp/employees.json", "r") as employees_in:
            employee_map = json.load(employees_in)
    with elapsedtime("loading_org_units"):
        with open("tmp/org_units.json", "r") as org_units_in:
            org_unit_map = json.load(org_units_in)
    print("employees:", len(employee_map))
    print("org units:", len(org_unit_map))
    # Transfer JSON
    base_url = settings.get("exporters.os2phonebook_base_url",
                            "http://localhost:8000/api/")
    username = settings.get("exporters.os2phonebook_basic_auth_user",
                            "dataloader")
    password = settings.get("exporters.os2phonebook_basic_auth_pass",
                            "password1")
    employees_url = settings.get("exporters.os2phonebook_employees_uri",
                                 "load-employees")
    org_units_url = settings.get("exporters.os2phonebook_org_units_uri",
                                 "load-org-units")
    basic_auth = BasicAuth(username, password)

    @retry(stop_max_attempt_number=20,
           wait_exponential_multiplier=1000,
           wait_exponential_max=10000)
    async def push_updates(url, payload):
        async with aiohttp_session.post(base_url + url,
                                        json=payload,
                                        auth=basic_auth) as response:
            if response.status != 200:
                logger.warning("OS2Phonebook returned non-200 status code")
            print(await response.text())

    with elapsedtime("push_x"):
        async with ClientSession() as aiohttp_session:
            await asyncio.gather(
                push_updates(employees_url, employee_map),
                push_updates(org_units_url, org_unit_map),
            )
Exemplo n.º 12
0
async def auth_check(request, handler):
    if 'ADMIN_USER' not in os.environ or 'ADMIN_PASSWORD' not in os.environ:
        raise Exception('Admin login credentials not set')

    if 'Authorization' not in request.headers:
        raise HTTPUnauthorized()

    auth = BasicAuth.decode(request.headers['Authorization'])
    if (auth.login != os.environ['ADMIN_USER'] or
            auth.password != os.environ['ADMIN_PASSWORD']):
        raise HTTPUnauthorized()

    response = await handler(request)
    return response
Exemplo n.º 13
0
async def _basic_auth_registry_request(app: web.Application, path: str,
                                       method: str,
                                       **session_kwargs) -> Tuple[Dict, Dict]:
    if not config.REGISTRY_URL:
        raise exceptions.DirectorException("URL to registry is not defined")

    url = URL(
        f"{'https' if config.REGISTRY_SSL else 'http'}://{config.REGISTRY_URL}{path}"
    )
    logger.debug("Requesting registry using %s", url)
    # try the registry with basic authentication first, spare 1 call
    resp_data: Dict = {}
    resp_headers: Dict = {}
    auth = (BasicAuth(login=config.REGISTRY_USER, password=config.REGISTRY_PW)
            if config.REGISTRY_AUTH and config.REGISTRY_USER
            and config.REGISTRY_PW else None)

    session = app[APP_CLIENT_SESSION_KEY]
    try:
        async with session.request(method.lower(),
                                   url,
                                   auth=auth,
                                   **session_kwargs) as response:
            if response.status == HTTPStatus.UNAUTHORIZED:
                logger.debug("Registry unauthorized request: %s", await
                             response.text())
                # basic mode failed, test with other auth mode
                resp_data, resp_headers = await _auth_registry_request(
                    url, method, response.headers, session, **session_kwargs)

            elif response.status == HTTPStatus.NOT_FOUND:
                logger.exception("Path to registry not found: %s", url)
                raise exceptions.ServiceNotAvailableError(str(path))

            elif response.status > 399:
                logger.exception("Unknown error while accessing registry: %s",
                                 str(response))
                raise exceptions.RegistryConnectionError(str(response))

            else:
                # registry that does not need an auth
                resp_data = await response.json(content_type=None)
                resp_headers = response.headers

            return (resp_data, resp_headers)
    except client_exceptions.ClientError as exc:
        logger.exception("Unknown error while accessing registry: %s",
                         str(exc))
        raise exceptions.DirectorException(
            f"Unknown error while accessing registry: {str(exc)}")
Exemplo n.º 14
0
async def parse_main_page(session, queue, base_path, download_settings):
    links_to_pdf = {
        "Overlays": lambda x: "slides/lecture{}.pdf".format(x + 1),
        "Handout": lambda x: "slides/lecture{}.handout.pdf".format(x + 1),
        "Exercise": "dl/exercises/exercises{:02d}.pdf".format,
    }

    await validate_url(session,
                       queue,
                       links_to_pdf,
                       BASE_URL,
                       base_path,
                       auth=BasicAuth(download_settings.username,
                                      download_settings.password))
Exemplo n.º 15
0
async def task():
    await mongo.admin.command("ismaster")

    session = ClientSession()

    async for user in db.users.find():
        try:
            auth = BasicAuth(REDDIT_CLIENT_ID, REDDIT_CLIENT_SECRET)
            header = {'User-agent': 'ImposterLeaderboard, /u/RenegadeAI'}
            payload = {
                'grant_type': 'refresh_token',
                'refresh_token': user['token']['refresh_token']
            }
            r = await session.post(
                'https://www.reddit.com/api/v1/access_token',
                headers=header,
                auth=auth,
                data=payload)
            reddit_token = await r.json()

            header['Authorization'] = f'Bearer {reddit_token["access_token"]}'

            r = await session.get('https://gremlins-api.reddit.com/status',
                                  headers=header)
            stats = await r.json()

            user = await db.users.find_one_and_update(
                {'id': user['id']},
                {
                    "$set": {
                        'token.access_token': reddit_token['access_token'],
                        'games_played': stats['games_played'],
                        'games_won': stats['games_won'],
                        'user_score': stats['user_score'],
                        'user_score_pretty': stats['user_score_pretty'],
                        'max_lose_streak': stats['max_lose_streak'],
                        'lose_streak': stats['lose_streak'],
                        'max_win_streak': stats['max_win_streak'],
                        'win_streak': stats['win_streak'],
                    }
                },
            )

            print(f'Updated /u/{user["name"]}')

        except Exception as e:
            print(f'Error: {e}')

    await session.close()
    mongo.close()
Exemplo n.º 16
0
async def check_proxy_enable(host: str, port:str, username: str, password: str) -> Dict[str, Union[str, bool]]:
    async with ClientSession() as session:
        if username is None:
            proxy_auth = None
        else:
            proxy_auth = BasicAuth(username, password)
        async with session.get("http://python.org",
                               proxy=f"http://{host}:{port}",
                               proxy_auth=proxy_auth) as resp:
            return {'host': host,
                    'port': port,
                    'username': username,
                    'password': password,
                    'enabled': resp.status == 200}
Exemplo n.º 17
0
async def test_auth_legacy_support_api_password_cannot_access(
        app, aiohttp_client, legacy_auth, opp):
    """Test access using api_password if auth.support_legacy."""
    setup_auth(opp, app)
    client = await aiohttp_client(app)

    req = await client.get("/", headers={HTTP_HEADER_HA_AUTH: API_PASSWORD})
    assert req.status == 401

    resp = await client.get("/", params={"api_password": API_PASSWORD})
    assert resp.status == 401

    req = await client.get("/", auth=BasicAuth("openpeerpower", API_PASSWORD))
    assert req.status == 401
Exemplo n.º 18
0
async def fetch(url, session):
    proxy_auth = BasicAuth('HUIHANHTTTEST1', 'LDJUC95z')
    headers = {'connection': 'closed'}
    async with session.get(url=url,
                           proxy="http://http-proxy-sg1.dobel.cn:9180",
                           proxy_auth=proxy_auth,
                           headers=headers) as resp:
        ss = await resp.read()
        s = ss.decode("utf-8")
        # print(s)
        selector = etree.HTML(s)
        u = selector.xpath(
            "/html/body/div[3]/div[1]/div[5]/div/div[2]/div[3]/a/@href")
        print(u)
Exemplo n.º 19
0
async def test_auth_legacy_support_api_password_cannot_access(
        app, aiohttp_client, legacy_auth, hass):
    """Test access using api_password if auth.support_legacy."""
    setup_auth(hass, app)
    client = await aiohttp_client(app)

    req = await client.get("/", headers={HTTP_HEADER_HA_AUTH: API_PASSWORD})
    assert req.status == HTTPStatus.UNAUTHORIZED

    resp = await client.get("/", params={"api_password": API_PASSWORD})
    assert resp.status == HTTPStatus.UNAUTHORIZED

    req = await client.get("/", auth=BasicAuth("homeassistant", API_PASSWORD))
    assert req.status == HTTPStatus.UNAUTHORIZED
Exemplo n.º 20
0
 async def transfer(
         self,
         params: Union[TransferInput, dict]
 ) -> Union[TransferSuccess, TransferError]:
     params = self._get_validated_transfer_input(params)
     async with request('POST', self.TRANSFER,
                        auth=BasicAuth(self.store_id, self.store_key),
                        json=asdict(params)
                        ) as response:
         try:
             data = await response.json()
             return self._get_formatted_transfer_res(data)
         except Exception as e:
             return TransferError(error=str(e))
Exemplo n.º 21
0
 async def authenticate(self, request):
     session = await get_session(request)
     auth_request = request.headers.get('AUTHORIZATION', None)
     logger.debug('authentication: {}'.format(auth_request))
     if auth_request is not None:
         try:
             creds = BasicAuth.decode(auth_request)
             if creds.password == self.credentials.get(creds.login, ''):
                 logger.debug('Authenticated user: {}'.format(creds.login))
                 session['authenticated'] = 'True:{}'.format(creds.login)
                 return web.Response(body='logged in'.encode('utf-8'))
         except ValueError as e:
             pass
     return web.Response(body='login error'.encode('utf-8'))
Exemplo n.º 22
0
 async def create_order(
         self,
         params: Union[CreateOrderInput, dict]
 ) -> Union[CreateOrderSuccess, CreateOrderError]:
     params = self._get_validated_create_order_input(params)
     async with request('POST', self.CREATE_ORDER,
                        auth=BasicAuth(self.store_id, self.store_key),
                        json=asdict(params)
                        ) as response:
         try:
             data = await response.json()
             return self._get_formatted_create_order_res(data)
         except Exception as e:
             return CreateOrderError(error=str(e))
Exemplo n.º 23
0
 def __init__(self,creds_file='creds.json'):
     with open(creds_file) as cf:
         creds = json.load(cf)
         
     cp_user = creds['cp_user']
     cp_pass = creds['cp_pass']
     vb_user = creds['vb_user']
     vb_pass_md5 = creds['vb_pass_md5']
     self.fourm_loc = creds['forum_loc']
     
     self._basic_auth = BasicAuth(cp_user,cp_pass)
     self._login_data = {'logintype':'cplogin','do':'login',
         'vb_login_md5password':vb_pass_md5,'vb_login_md5password_utf':vb_pass_md5,
         'vb_login_username':vb_user,'vb_login_password':''}
Exemplo n.º 24
0
    async def receive_new_access_token(self):
        """Receive a new acces token vai oauth."""
        data, status = await self._perform_api_post_request(
            'https://eu.battle.net/oauth/token',
            auth=BasicAuth(self._key, self._secret),
            params={'grant_type': 'client_credentials'})

        if status != 200:
            raise InvalidApiResponse(status)

        self._access_token = data.get('access_token')
        self._access_token_checked = True
        self._controller.set_config('access_token', self._access_token)
        logger.info('New access token received.')
Exemplo n.º 25
0
    async def create(self, username: str, password: str, contactemail: str,
                     domain: str, plan: str) -> Any:
        """
        Creates a new vPanel user account.

        :param username: user's internal username, has a limit of 8 characters.
        :param password: user's password on the vPanel.
        :param contactemail: user's email on the vPanel.
        :param domain: user's domain on the vPanel.
        :param plan: user's plan on the vPanel.

        Usage:
            >>> client = AsyncClient(username='******', password='******')
            >>> await client.create(
            >>>     username="******",
            >>>     password="******",
            >>>     contactemail="*****@*****.**",
            >>>     domain="subdomain.example.com",
            >>>     plan="MyAwesomePlan",
            >>> )
        """
        # Get the session, set the params, and make a post request.
        session = await self._ensure_session()

        params = {
            "username": username,
            "password": password,
            "contactemail": contactemail,
            "domain": domain,
            "plan": plan,
        }

        async with session.post(
                f"{self.api_url}/createacct.php",
                params=params,
                auth=BasicAuth(self.username, self.password),
        ) as r:
            response = await r.text()

            # Parse the response and get the root element.
            root = self._parse_xml(response)

            status = root[0][2].text
            if status == "1":
                # Return the vPanel username.
                return root[0][0][1].text
            # Raise exception with error.
            error = root[0][3].text
            raise APIError(error, 0)
Exemplo n.º 26
0
 async def delete_request(self, uri, headers):
     try:
         async with self.semaphore:
             async with aiohttp.ClientSession(loop=self.loop) as session:
                 async with session.delete(
                         uri,
                         headers=headers,
                         auth=BasicAuth(self.username, self.password),
                         ssl=False,
                 ) as _response:
                     await _response.read()
     except (Exception, TimeoutError):
         logger.exception("Failed to communicate with server.")
         raise BadfishException
     return _response
Exemplo n.º 27
0
    def request(self, method, url, headers=None, **aio_kwargs):
        """Request OAuth2 resource."""
        url = self._get_url(url)
        if self.access_token:
            headers = headers or {'Accept': 'application/json'}
            headers['Authorization'] = "Bearer {}".format(self.access_token)
            auth = None
        else:
            headers = headers or {
                'Accept': 'application/json',
                'Content-Type': 'application/x-www-form-urlencoded;charset=UTF-8',
            }
            auth = BasicAuth(self.client_id, self.client_secret)

        return self._request(method, url, headers=headers, auth=auth, **aio_kwargs)
Exemplo n.º 28
0
async def is_worker(db, request: web.Request) -> Optional[str]:
    auth_header = request.headers.get(aiohttp.hdrs.AUTHORIZATION)
    if not auth_header:
        return None
    auth = BasicAuth.decode(auth_header=auth_header)
    async with db.acquire() as conn:
        val = await conn.fetchval(
            "select 1 from worker where name = $1 "
            "AND password = crypt($2, password)",
            auth.login,
            auth.password,
        )
        if val:
            return auth.login
    return None
Exemplo n.º 29
0
    def _request(self, method, url, headers=None, params=None, **aio_kwargs):
        """Setup Authorization Header.."""
        auth = None
        access_token = params.pop(self.access_token_key, None)
        if access_token:
            headers['Authorization'] = "Bearer %s" % access_token
        else:
            auth = BasicAuth(self.client_id, self.client_secret)

        return super(Bitbucket2Client, self)._request(method,
                                                      url,
                                                      headers=headers,
                                                      params=params,
                                                      auth=auth,
                                                      **aio_kwargs)
Exemplo n.º 30
0
        async def wrapper(self, *args):
            client = os.environ["SCLIENT"]
            secret = os.environ["SSECRET"]
            refresh = os.environ["REFRESH_TOKEN"]
            url = "https://accounts.spotify.com/api/token"

            auth = BasicAuth(client, secret)
            data = {"grant_type": "refresh_token", "refresh_token": refresh}

            async with ClientSession(auth=auth) as session:
                async with session.post(url, auth=auth, data=data) as response:
                    response = await response.json()
                    self.token = "Bearer " + response["access_token"]
                    self.headers = {"Authorization": self.token}
            return await func(self, *args)
Exemplo n.º 31
0
        async def post_all(total_data, connector, loop):
            tasks = []
            sem = asyncio.Semaphore(50)

            auth = BasicAuth('scicrunch', 'perl22(query)')
            async with ClientSession(connector=connector, auth=auth) as session:
                if _print:
                    print('=== {0} ==='.format(action))
                for i, tupdata in enumerate(total_data):
                    url, data = tupdata
                    task = asyncio.ensure_future(
                        post_single(url, data, session, i))
                    tasks.append(task)
                outputs = await asyncio.gather(*tasks)
                return outputs
Exemplo n.º 32
0
    async def fetch(self, request):
        client = request.app['client']
        refresh_due = (time.time() - self.timestamp) > self.lifetime
        if refresh_due and not self.lock.locked():
            async with self.lock:
                logger.info("Refreshing Job Role Dropdown Cache")
                url = FSDR_URL + f'/jobRoles/allJobRoleShorts/distinct'
                auth = BasicAuth(FSDR_USER, FSDR_PASS)
                async with client.get(url, auth=auth) as resp:
                    cache = await resp.json()
                    cache = [x for x in cache if x not in ['null', None]]
                    self.cache = sorted(cache, key=str.lower)

                self.timestamp = time.time()
        return self.cache