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

Schema Analyzer calls don't have the refreshed token which causes 401 error #564

Open
greggailly opened this issue May 31, 2024 · 4 comments

Comments

@greggailly
Copy link

API Platform version(s) affected: api: 3.3, admin: 3.4.6

Description
When accessing a resource from the admin, several extra calls seem to be made on top of the main call fetching the data:
Screenshot 2024-05-31 at 14 11 12
These calls seem to be initiated by the Guesser Components to fetch the schema:
Screenshot 2024-05-31 at 15 35 15

These calls do include a JWT but this token is not refreshed if expired. The JWT in the "main" call is correctly updated.

How to reproduce

  1. Clone Api Platform Demo repository
  2. Remove components so that the Guesser components do their job

Possible Solution
n/a

Additional Context

  • Code is very close to the Demo:
// Admin.jsx

const apiDocumentationParser = (session) => async () => {
  try {
    return await parseHydraDocumentationWithEnums(ENTRYPOINT, {
      headers: {
        Authorization: `Bearer ${session?.accessToken}`,
      },
    });
  } catch (result) {
    // @ts-ignore
    const { api, response, status } = result;
    if (status !== 401 || !response) {
      throw result;
    }

    return {
      api,
      response,
      status,
    };
  }
};

const AdminUI = ({ children, session }) => {

  const dataProvider = useRef();
  const { docType } = useContext(DocContext);

  dataProvider.current = hydraDataProvider({
    entrypoint: ENTRYPOINT,
    httpClient: (url, options = {}) => fetchHydra(url, {
      ...options,
      headers: {
        Authorization: `Bearer ${session?.accessToken}`,
      },
    }),
    apiDocumentationParser: apiDocumentationParser(session),
  });

  return docType === "hydra" ? (
    <HydraAdmin
      requireAuth
      authProvider={authProvider}
      // @ts-ignore
      dataProvider={dataProvider.current}
      entrypoint={window.origin}
      i18nProvider={i18nProvider}
      layout={MyLayout}
    >
      {!!children && children}
    </HydraAdmin>
  ) : (
    <OpenApiAdmin
      requireAuth
      authProvider={authProvider}
      // @ts-ignore
      dataProvider={dataProvider.current}
      entrypoint={window.origin}
      docEntrypoint={`${window.origin}/docs.json`}
      i18nProvider={i18nProvider}
      layout={MyLayout}
    >
      {!!children && children}
    </OpenApiAdmin>
  );
};

const AdminWithContext = ({ session }) => {

  const [docType, setDocType] = useState(
    store.getItem("docType", "hydra"),
  );

  return (
    <DocContext.Provider
      value={{
        docType,
        setDocType,
      }}>
      <AdminUI session={session}>
          // No Resources defined here unlike in the demo repo
      </AdminUI>
    </DocContext.Provider>
  );
};
  • parseHydraDocumentationWithEnums is based on Admin interface not rendering dropdown for Enum on HydraAdmin #494 (comment) doesn't seem to be the source as when using the normal parseHydraDocumentation problem remains.
  • Calls are made every time we access the resource from the admin if no ApiFilter is defined in the API
  • If ApiFilter is defined in the API then calls are only made the first time we try to access the resource. If the resource is not accessed at least once before the initial token expires the problem remains
@greggailly
Copy link
Author

greggailly commented Jun 3, 2024

Issue seems to be coming from the api-doc-parser where the getParameters function is returned for each Resource with the token saved into it. Since parseHydraDocumentation is only called once when the page is loaded the JWT is never updated in the resource function call.

resource.getParameters = (): Promise<Parameter[]> => getParameters(resource, options);

https://github.com/api-platform/api-doc-parser/blob/e8b49f2b452c4a19fab5eea86ec742c8201d381f/src/hydra/parseHydraDocumentation.ts#L475-L476

@greggailly
Copy link
Author

@dunglas would such a change to the getParameters callback be accepeted ? Adding a "in_options" argument to eventually override at runtime the headers that can be sent to fetch resource parameters.

resource.getParameters = (in_options: RequestInitExtended = {}): Promise<Parameter[]> =>
          getParameters(resource, {...options, ...in_options});

If yes then to be discussed, the schemaAnalyzer could be modified to take a new argument with the options.

export const resolveSchemaParameters = (schema: Resource, options: RequestInitExtended = {} ) => {
  if (!schema.parameters || !schema.getParameters) {
    return Promise.resolve([]);
  }

  return !schema.parameters.length
    ? schema.getParameters(options)
    : Promise.resolve(schema.parameters);
};

};

Options (with Authentication headers) could then either be passed down from the FilterGuesser (and other Guessers) or (less likely I guess) fetched directly in the schemaAnalyzer (using local storage maybe ?).

Unless you see another solution to have the updated tokens passed down to the getParameter requests !

@papppeter
Copy link

papppeter commented Oct 2, 2024

Do you have a solution? it v4 is affected.

@papppeter
Copy link

papppeter commented Oct 2, 2024

#578 helped me to solve my issue. i created a custom parser where i did set the proper headers for authentication. but any better idea is wellcome.

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

2 participants