How to Call an Endpoint on Client Machine for USB Token Signing (CORS/CRP Issues)

I have a use case involving digital signing with a USB Token connected to the client machine. Here’s the workflow I’m aiming for:

  • There’s data in Directus that needs to be signed.
  • The digital signature must be performed using a USB token (hardware key) present on the client’s machine.
  • I want to trigger the signing action directly from the client browser (not from the Directus server).
  • To achieve this, I’m trying to call an exposed HTTP endpoint on the client’s machine (where the local token software listens for signing requests) from the browser.

However, when I try to make this call from the browser, I get blocked by CORS and Chrome’s “Cross-Origin Resource Policy” (CRP) errors.

Has anyone faced a similar scenario or have recommendations on it?

2 Answers

2

Finally, I managed to solve the issue :white_check_mark:

I think by default Directus sets connect-src in CSP to only allow 'self'. That means no external API calls or connections are allowed unless you explicitly add them.

The fix was to set the following environment variable in my .env file:

CONTENT_SECURITY_POLICY_DIRECTIVES__CONNECT_SRC="'self' http://localhost:port"

After adding this, It’s now possible to make requests to the client’s localhost service, and the signing flow worked as expected.

Hey Abdallah, I was quite curious about this question . Does this actually work for you when Directus is hosted on a public domain? From my understanding browsers CORS should not allow requests from public to localhost as it would basically mean that any random website can request any private endpoints on the users machine.

I don’t have deep experience with all the CORS security edge cases, so I trust you probably know more here. But based on my testing, this setup actually worked for me. What I did first, I exposed the localhost service with Access-Control-Allow-Origin: *, so the browser accepted the request on the local side. Secondly, I added CONTENT_SECURITY_POLICY_DIRECTIVES__CONNECT_SRC in Directus, which allowed the request from the CSP side. With both in place, the flow works even when Directus is hosted on a public domain.

Here’s the flow in my case: 1. The client clicks a button on a custom interface inside the Data Studio. 2. The extension fetches the needed data from Directus. 3. It then sends this data to the client’s localhost service (via fetch/axios), which returns the signature. So yes, in my setup it runs smoothly between the client’s browser and their localhost service.

Oh, you have access to the users machine, now that makes sense. I thought it's about a random machine you can't control what is installed / how the endpoint is served. Thanks for the explanation.

Update:
Thanks for whoever added this in the docs, it would saved me a lot of time if I noticed it :sweat_smile:

Using External APIs
To avoid Cross Site Request Forgery (CSRF), app extensions cannot make requests to external servers by default. A common approach to achieve this is to create a bundle containing an endpoint that makes the external request, and an app extension that uses the now-internal endpoint to retrieve data.