junobuild / juno-js

JavaScript libraries for interfacing with Juno
MIT License
14 stars 1 forks source link

Signing messages after authentication #113

Closed CodingFu closed 7 months ago

CodingFu commented 7 months ago

Greetings,

Apologies for my inquiry, as I am transitioning from the Ethereum ecosystem and require clarification regarding user authentication within the Juno framework.

Currently, I have been exploring the user object, which allows me to ascertain whether a user is logged in or not. However, I am seeking guidance on how to utilize this user object to facilitate message signing with the user's private key. Additionally, I am curious if there is a method available to retrieve the user's private key for signature verification purposes.

My envisioned workflow is outlined as follows:

  1. The user successfully logs in with Juno.
  2. A subsequent call is made to a third-party service, which could be another canister or an external API.
  3. The third-party service furnishes a nonce.
  4. In the browser environment, I sign the nonce using the user's private key and transmit the signed message to the API.
  5. Subsequently, the API derives the user's public key from their address and validates the signed message to ensure the authenticity of the user's identity and prevent any impostors from infiltrating the system. Any insights or suggestions on how to achieve this workflow would be greatly appreciated.

Thank you.

peterpeterparker commented 7 months ago

Hi @CodingFu ,

Thanks for your questions. First off, I want to clear up any potential confusion.

Juno (Build, this project), uses the Internet Computer as blockchain infrastructure, not Juno Network. Just want to be sure.

Regarding your envisioned workflow, I see two distinct use cases: querying a canister or an external API.

To query a canister, you can use the Principal (essentially a public key) assigned to your user after they sign in. This principal can be retrieved from the user entity (you get it with authSubscribe). Once you have this principal, you can query canisters on the Internet Computer using the agent-js library. This is one commone or the standard manner.

When it comes to querying an external API, there are two scenarios. The first, querying from the client side, should ideally not involve using the private key, as it would be insecure to expose this key on the client side. I'm not entirely sure what method you'd use for secure client-side API querying, but I can look up some references if you're interested.

The alternative approach involves making the HTTP call from the backend side—within the smart contract or satellite—using HTTP outcalls (for example, see this example).

I admit that my answer might not fully address your question, as Juno doesn't yet support these advanced manipulations in a straightforward manner. Nonetheless, I hope this provides a starting point.

What are your thoughts?

CodingFu commented 7 months ago

That pretty much covers my question, thank you very much!

By private key usage I actually meant asynchronous cryptography where I would encrypt some message with principal’s private key and then decrypt it with principal’s public key somewhere else.

On Feb 13, 2024, at 4:49 AM, David Dal Busco @.***> wrote:

Hi @CodingFu https://github.com/CodingFu ,

Thanks for your questions. First off, I want to clear up any potential confusion.

Juno (Build, this project), uses the Internet Computer https://internetcomputer.org/ as blockchain infrastructure, not Juno Network. Just want to be sure.

Regarding your envisioned workflow, I see two distinct use cases: querying a canister or an external API.

To query a canister, you can use the Principal (essentially a public key) assigned to your user after they sign in. This principal can be retrieved from the user entity (you get it with authSubscribe https://juno.build/docs/build/authentication#subscription). Once you have this principal, you can query canisters on the Internet Computer using the agent-js https://github.com/dfinity/agent-js/ library. This is one commone or the standard manner.

When it comes to querying an external API, there are two scenarios. The first, querying from the client side, should ideally not involve using the private key, as it would be insecure to expose this key on the client side. I'm not entirely sure what method you'd use for secure client-side API querying, but I can look up some references if you're interested.

The alternative approach involves making the HTTP call from the backend side—within the smart contract or satellite—using HTTP outcalls (for example, see this example https://juno.build/docs/guides/rust#http-outcalls).

I admit that my answer might not fully address your question, as Juno doesn't yet support these advanced manipulations in a straightforward manner. Nonetheless, I hope this provides a starting point.

What are your thoughts?

— Reply to this email directly, view it on GitHub https://github.com/junobuild/juno-js/issues/113#issuecomment-1939549619, or unsubscribe https://github.com/notifications/unsubscribe-auth/AANCTDLFIQGZE2RJBT5YG6DYTJ55LAVCNFSM6AAAAABDETG54GVHI2DSMVQWIX3LMV43OSLTON2WKQ3PNVWWK3TUHMYTSMZZGU2DSNRRHE. You are receiving this because you were mentioned.

CodingFu commented 7 months ago

@peterpeterparker Actually I have another question about http outcalls from canisters, maybe you could help me out since you have lots more of experience.

A lot of API cals are usually use some api key.

For example GET https://mydomain.com/api/v1/posts?apiKey=xxx_xxxxxx

Or, sometimes the api key is in the headers.

I read somewhere that http traffic is unencrypted within a subnet and potential hacker could just sniff all the traffic from my canister and obtain my apiKey that is used for http outcalls. (I think I read it in azle docs or I may be mistaken)

Is my concern about security true and if yes is there a common way to avoid apiKeys getting leaked?

CodingFu commented 7 months ago

My another concern is that canister is just WASM code, so it could be disassembled by attacker to get my api key this way

tthebst commented 7 months ago

hi @CodingFu. I work at Dfinity on the https outcalls feature.

I read somewhere that http traffic is unencrypted within a subnet and potential hacker could just sniff all the traffic from my canister and obtain my apiKey that is used for http outcalls.

The feature only allows HTTPS so your traffic to the outcalls destination is always encrypted and therefore sniffing is not possible. Do you have a link to the azle docs such that I can suggest a change?

One thing to keep in mind is that the API key is visible to nodes on the subnet. So they could extract it if they act maliciously. This problem is inherit in any public blockchain but reducing the capabilities of your API key to a minumum together with key rotation can reduce the risk to an acceptable level.

peterpeterparker commented 7 months ago

I gonna close this issue given that it seems that the questions have been addressed. Please feel free to ping me if anything is unclear, happy to reopen the thread.