Initialize canister only by a given user

I need to initialize a backend canister B passing into it a user’s principal “seen” from a frontend canister F, where the user principal must correspond to the same user as one who ran my app to create canisters B and F.

I set in frontend (of an app that creates B and F) a private key (known only to frontend), store its public key in the app, then redirect this to F with private key in URL string. B can verify that its public key corresponds to the private key, to check that B is initialized by the same user that created the private key.

I noticed that the above algorithm has a security flaw: a malicious node can front-run intializing B with private key it got but with another user, so initialize B with a wrong user.

Is there any way to do this without the flaw?

Again, I need to initialize B with the principal “seen” from frontend F, by the same user (but different principal) as one who runs the app that created B.

The task in more detail is: In my package manager initialize apps, that it installs, with a principal of the same user as one who installed the app.

Oh, it seems I know what to do:

  1. Generate a priv/pub key pair in the package manager’s frontend.
  2. Store pub key (without priv key) in the backend.
  3. Pass the priv key to F (in an URL string).
  4. Generate user’s principal (as “seen” from F).
  5. Sign the user’s principal with the priv key.
  6. Pass the user’s principal and its signature to the backend.
  7. The backend verifies the signature using stored pub key.
  8. If verification passed, set the user’s principal in B.

This way, verification happens without passing priv key to the network.

The verification passes, only if it is the user’s principal “seen” from F, and it is the same as the user who stored the pub key.

I rewrote the algorithm above, because it was erroneous.

Is your goal to authorize the user in the canister the package manager has created? If that’s the case, I think you can create a canister for the user, then present the canister id to the user in the frontend, and then the user can generate the principal the user will have for that canister. To generate the principal, you can use the @dfinity/auth-client package, I believe. That principal can be used to initialize the canister created by the package manager.

Or is the goal different?

The goal is not different, but your algorithm has a flaw: In principle, somebody may have watch for newly created canisters on IC and initialize the user’s canister front-ruinning the user.

Thus I invented my algorithm for this involving generating private key in the frontend and signing the user’s principal by this key (without delivering the private key outside the browser).

Couldn’t you require authentication for the initializations? So that nobody can frontrun it and you only need to exchange public keys between frontends, instead of secrets. Delegations are also an option (e.g. from the package manager to the frontend) in case you don’t want to have additional interaction with the backend canister.

I don’t understand you: How to do it with public keys only?

I don’t understand, also, how to use delegations. Could you explain?

For example, once you know the principal/public key of the user from the frontend, you can pass this to the package manager who can then initialize the canister with the principal. Assuming that the initialization requires a signature from the package manager, then no one can front-run you, and the user can just authenticate from the frontend using their keys. Using delegations is just a variation of this: the password manager can just set its own principle when initializing the canister. Then you can create a delegation from the password manager to the user (again only by handing over the user’s principal). The user can then authenticate using their keys and the delegation from the password manager.

I hardly understand. How is delegation created? Is it in frontend or backend?

Can you point me APIs for delegation?

I probably don’t understand at all, how delegation works.