dfinity / ICRC

Repository to ICRC proposals
Apache License 2.0
31 stars 5 forks source link

ICRC-32: Sign challenge #32

Open dostro opened 1 year ago

dostro commented 1 year ago

Note: We decided to use one method for getting a delegation and will therefore use this to track https://github.com/dfinity/wg-identity-authentication/blob/main/topics/icrc_32_sign_challenge.md.

The below is kept for historical purposes for now.


This reserves the ICRC number for safely working with global delegations as per https://forum.dfinity.org/t/proposal-to-add-security-for-ic-wallet-users/21873, summarized below:

Problem

Most users and developers want to sign in with the same principal across applications.

Proposed solution

Applications request delegations from wallets that can make authenticated calls to their own canisters, and will require user approval to make authenticated calls to canisters it doesn't own.

Example

Proposed implementation

To work from the client side, it is necessary to provide a list of canisters for which the 3rd-party developer requests delegation.

In each of the requested canisters, the method get_trusted_origins: () -> (vec text) needs to be defined. It is expected that this method returns a list of origins that have access to the target canister.

// Rust implementation

#[update]
async fn get_trusted_origins() -> Vec<String> {
    vec![
        String::from("https://dscvr.one") // to be replaced with application's frontend origin(s)
    ]
}

Client implementation example in agent.js.

Origins should be in the format defined by the Window.postMessage method (https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage#the_dispatched_event):

The origin of the window that sent the message at the time postMessage was called. This string is the concatenation of the protocol and '://', the host name if one exists, and ':' followed by a port number if a port is present and differs from the default port for the given protocol. Examples of typical origins are https://example.org/ (implying port 443), http://example.net/ (implying port 80), and http://example.com:8080.

Why not use certified query calls

Consensus is important to reach when verifying canister permissions. If one of the nodes returns an incorrect origin, it could lead to the generation of an incorrect delegation and provide malicious actors with access to the user's assets.

We propose update calls here because it is the lowest lift for developers, and ultimately wouldn't introduce any latency during authentication if wallet providers run this call in parallel with an optimistic call to create the delegation. Certified query calls will require more advanced skills from the developer, which is not a priority for the first version of the library.

krpeacock commented 1 year ago

I would propose reserving a public metadata section of icp:public trusted_origins alongside the canister method, allowing for tooling to pull the same information out of the state tree