Creating a web canister

Thanks, kpeacock Can you give recommendations for correction, excluding the removal of Plug auth from the functionality :slightly_smiling_face:

okay, it’s hacky since plug is creating the agent for you, but you should be able to access _identity from the agent, and then re-create a new one using https://icp-api.io as the host

This is not an option. My attempts failed to get Identity from Plug. That’s why I used the Actor Plug. In Stoiс, by the way, I get the identity directly and recreate the HttpAgent.

There is very little documentation from Plug, but I realized that they hide identity behind closed fields

Gotcha. I’ve raised the issue though with boundary nodes - I don’t think that Plug is technically doing anything wrong here

That is, it will be fixed?

Hey @Safik, could you please disable these lines of code when you deploy to mainnet and try again?

You can wrap them in a call similar to this:

  if (process.env.DFX_NETWORK !== "ic") {
    agent.fetchRootKey();
  }

Calling fetchRootKey on mainnet is a big security risk because it would allow a potentially malicious replica to give agent-js the wrong public key for verifying responses from the IC, which would be very dangerous.

The issue you’re seeing comes from the Service Worker not forwarding the fetchRootKey API call properly, but since we shouldn’t ever make that call on mainnet, this is not something that we’ll fix. We could add a more helpful debugging message if this call is made though, I think that would help developers that fall into this situation.

Okay, I know. These are functions for local deployment. I did not think that they would interfere with “production” Because it is not used in “production”. I will now remove them from the module completely and try.

Update:

The error remained.
I have completely cleaned up the local development call functions. And commented them out. That is, even hypothetically agent.fetchRootKey() cannot be called.

And one more thing: in the final version there will only be a “Production” version. (without agent.fetchRootKey()) So that this vulnerability is not exploited.

Update 2
Another mistake. Refers to Vite. And most likely to the Plug button. Related to HttpAgent

I will freeze this error. There’s something else to do. With this problem, it can be a long time

The error remained.

There’s one more place where this is called: https://github.com/fury02/rbac-motoko/blob/main/src/declarations/rbac/index.js#L26-L33

The problem here is that DFX_NETWORK is not defined through Vite, so the process.env.DFX_NETWORK !== "ic" condition is always true and so fetchRootKey is still called on mainnet. You need to define DFX_NETWORK in vite.config.ts. You can see example of this here: examples/svelte/sveltekit-starter/vite.config.ts at master · dfinity/examples · GitHub

That is, even hypothetically agent.fetchRootKey() cannot be called

This will break your application when it’s running locally.

1 Like

I changed the configs. The problems remained.


I think I’ll come back to the problem later
Thanks,
NathanosDev !

Okay sure. When you come back to this, the problem still lies in the vite.config.ts. If you debug the code through the browser you can see this:

    {}.DFX_NETWORK !== "ic" && et.fetchRootKey().catch(tt=>{
        console.warn("Unable to fetch root key. Check to ensure that your local replica is running"),
        console.error(tt)
    }

{}.DFX_NETWORK will always be undefined so the condition will always be true.

Maybe the problem is what parameters I pass during the build?

npm ci && dfx canister create rbac && dfx generate rbac && dfx deploy

so these commands give an indefinite interpretation?

In vite.config.ts and .env fixed on “ic”

export default defineConfig({
    plugins: [react()],
    define: {
        DFX_NETWORK: 'ic',
        ...Object.fromEntries(
            Object.entries(canisterIds).map(([name, ids]) => [
                `process.env.${name.toUpperCase()}_CANISTER_ID`,
                JSON.stringify(ids[network] || ids[localNetwork]),
            ]),
        ),
    },
});

Update

I tried to manually fix

dfx canister --network=ic install --mode=reinstall frontend

The error remained:

async fetchRootKey() is still being called

Instead of relying on define, you can use EnvironmentPlugin from 'vite-plugin-environment':

You probably don’t need the the two entries that include the defineOn option, I had to do that because of the way env vars get shared with webworkers. Anyways, if you do use:

EnvironmentPlugin("all", { prefix: "DFX_" }),
EnvironmentPlugin("all", { prefix: "CANISTER_" }),

(given that you have a .env and it does include DFX_NETWORK and the CANISTER_* ids, see below)

will make it so process.env.DFX_NETWORK is defined (as if you had manually set it in the define: { ... }).

I got this plugin from Kyle’s auth client project.

(see below here:)
Note that this requires that you also have dfx.json such that:

"output_env_file": ".env",

is included and points to the same directory where your vite config is.

Also, the way .env is generated it will add all the canister ids (and network) of the last deployed canister (and any of its dependencies).

In other words, if you have canisters A and B and C and your script to deploy is

dfx deploy A && dfx deploy B && dfx deploy C the final .env will only include the ids of canister c (and whatever dependencies it has). To get around this you can add A and B as dependencies to C (I’m not sure if there is a penalty for doing this if they are not actually need, but doing this guarantees they’ll be included in the .env ?).

2 Likes

On a related note, to polyfill global, I found this to work the best:

<!--Script polyfills global.-->
 <script>window.global ||= window</script>

in your index.html:

  <body>
    <div id="root"></div>
    <script type="module" src="main.jsx"></script>
    <!--Script polyfills global.-->
    <script>window.global ||= window</script>
  </body>

In the project I linked, the config file also had:

  optimizeDeps: {
    esbuildOptions: {
        // Node.js global to browser globalThis.
        // (Makes it possible for WebWorker to use imports.) 
        define: {
            global: 'globalThis'
        },
    }
  },

but, as the comment states, this was again because of that project requiring webworkers.


Also you might check out GitHub - rvanasa/vite-react-motoko: Starter project for Vite + React + TypeScript + Motoko which is Typescript based (and what I originally based the project I originally linked on).

1 Like

Thanks!
I saw that the Vite-React template was changed.
In the near future:
I will create a project from scratch and try the Plug button taking into account your recommendations. If it works, I will transfer all the rest of the functionality.