Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ability to set callback that return fresh API Key #1307

Open
LeComptoirDesPharmacies opened this issue Sep 29, 2021 · 6 comments
Open

Ability to set callback that return fresh API Key #1307

LeComptoirDesPharmacies opened this issue Sep 29, 2021 · 6 comments

Comments

@LeComptoirDesPharmacies

Context :
Following the issue #772, we can now check remaining validity of API Key.

Problem :
In our application, we are generating very short term API Keys (5 minutes) to always be compliant with filters and visibility that are set in the Key (from our backend according to user access rights).

It could be very cool to add a callback while creating the searchclient which will be called when API Key is near expiration and which should return a fresh API Key.

Workaround :
Currently, we are wrapping the search methods from searchclient into some of our wrappers that do the check before every request.
If we detect that API Key is expired, we generate a new searchclient with the updated API Key and use it to execute the query.
However there is two bad concerns about this workaround :

  1. As searchclient instance change, the InstantSearch node seems to detect it and relaunch a new query (which is now duplicated).
  2. As searchclient instance change, what happen to the currently built query cache ? Reset ?

Yours faithfully,
LCDP

@Haroenv
Copy link
Contributor

Haroenv commented Sep 30, 2021

Before thinking further on if and how to implement this, I'd like to answer your questions:

  • InstantSearch has to redo a search when the search client instance changes, because it could for example change from a search client that is a noop to one that actually searches Algolia. These use cases are fairly rare, but it's easier to assume the search needs to be redone
  • The cache is indeed recreated when you create a new search client, unless you manually create the cache outside of the algoliasearch call and pass that same instance when you recreate the client
import algoliasearch from 'algoliasearch/lite';
import { createBrowserLocalStorageCache } from '@algolia/cache-browser-local-storage';
import { createFallbackableCache } from '@algolia/cache-common';
import { createInMemoryCache } from '@algolia/cache-in-memory';

const appId = '...';

const caches = {
  responsesCache: createInMemoryCache(),
  requestsCache: createInMemoryCache({ serializable: false }),
  hostsCache: createFallbackableCache({
    caches: [
      createBrowserLocalStorageCache({
        key: `${algoliasearch.version}-${appId}`,
      }),
      createInMemoryCache(),
    ],
  }),
};

const client = algoliasearch(appId, '...', { ...caches });

@LeComptoirDesPharmacies
Copy link
Author

Hi @Haroenv,

Nice, thanks for this answer which is really informative !
I think that we are going to create the cache outside the client which will be a good fix for the second point !

Yours faithfully,
LCDP

@AntoineDuComptoirDesPharmacies

Hi @Haroenv,

Is there any news about this feature request ?
We are still overidding the algolia search client methods with custom async to verify our api key prior to request but it is very ugly and hard to understand/maintain.

It could be good if we can give to the search client a method to generate an api key. It will work in combination of getSecuredApiKeyRemainingValidity. Before each algolia call, if the result of api key remaning validity is below a given value (1 minute ?) then method to generate a new api key is called prior to request.

Yours faithfully,
LCDP

@Haroenv
Copy link
Contributor

Haroenv commented Apr 5, 2023

Unfortunately I think that you wouldn't want to generate a secured API key frontend, as when you generate it, you need access to the api key with higher permission to be able to generate the secured API key from. If that's available frontend, you could just as well not use secured API keys, but just a regular API key.

@AntoineDuComptoirDesPharmacies
Copy link

AntoineDuComptoirDesPharmacies commented Apr 5, 2023

In our context, we can generate a secured frontend API Key without javascript client accessing the "mother" API Key with higher permission.

Context :
When a user login into our app, it get a JWT access token and JWT refresh token which have different lifespan (see Oauth mechanism with token renewal).

When user want to contact Algolia, it request a secured API Key to our backend, using his JWT Access Token.
The new Algolia Secured API Key will inherit the "Mother" API Key, have some restrictions linked to the user and have the same lifespan as the user JWT access token.

As it have a limited lifespan, the Secured API Key need to be refreshed and we would like to execute this check on Algolia Query to avoid trigger useless API Key generation every X minutes even if user is not interacting with Algolia.

In this context, the "Mother" api key can not be accessed directly in frontend (which would be a security flaw). The Secured API Key is temporary and can be generated only by logged in users.

What we are doing at the moment :
We override every async network request from Algolia Search Client (search, searchForFacetValues, ...) and call a validity check against the Algolia Secured API Key lifespan.
If timing is below a given value (1 minute for example), a request is sent to our backend to generate a new Secured API Key and this new key is used in the initial method/request call.

This is hard to maintain as we can miss some methods doing network request to Algolia API and we can have new ones or renaming on library version update.

@lennertsoffers
Copy link

In our case, we are running into the same problems as @AntoineDuComptoirDesPharmacies described above. The lack of the ability to set the search api key during requests, or any other way to change the api key of the searchClient

Context:
We've implemented a search box with the help of the Algolia Autocomplete library. As described in the Security Best Practices section of the Algolia documentation, we generate a derived key at our back end, that can be used for front end searches.

A diagram of the situation we would like to accomplish:
image

We've implemented this autocomplete similarly to this article of the algolia docs https://www.algolia.com/doc/ui-libraries/autocomplete/integrations/with-react-instantsearch/

Problem:
As you can see, we'll have to pass the searchClient to the autocomplete components. To instantiate the searchClient itself, we use the function provided by the algoliasearch library called algoliasearch.

const searchClient = algoliasearch("<appId>", "<searchApiKey>");

The instantiation of the searchClient takes the appId and api key. But following best practises, if the api key expires, we want to do some error handling, and recover by requesting a new api key to our server. This should happen without the user noticing an unresponsive search box.

The problem is that the searchClient provided doesn't allow us to do any of this, there is no option for error handling nor for updating the api key in the searchClient itself.

What we are doing at the moment:
Our current workaround is somewhat similar to the suggestion of @AntoineDuComptoirDesPharmacies #1307 (comment)

While this is a good workaround for the time being, it's not perfect. This is a solution that works for the searchClient only, but not for the recommendClient which we also use. We use a similar solution for working with the recommendClient, but can't reuse the code for the searchClient. We also have a strong dependence on the implementation of the Algolia library itself, which may be changed in the future.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants