Skip to content

Commit

Permalink
More comments in example and expanded readme (#622)
Browse files Browse the repository at this point in the history
  • Loading branch information
frederikrothenberger authored Apr 20, 2022
1 parent 439aca6 commit 5dcffde
Show file tree
Hide file tree
Showing 2 changed files with 61 additions and 16 deletions.
38 changes: 37 additions & 1 deletion demos/using-dev-build/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,10 +27,46 @@ At this point, the replica (for all practical matters, a local version of the In
};
};
```
On the IC, principals are basically the "identity" of someone performing a request or "call" (hence "caller"), and every call must be authenticated — i.e., must have a valid principal. When using Internet Identity you are using [self-authenticating principals](https://smartcontracts.org/docs/interface-spec/index.html#principal), which is a very fancy way of saying that you have a private key on your laptop (hidden behind TouchID, Windows Hello, etc) that your browser uses to sign and prove that you are indeed the person issuing the calls to the IC.
On the IC, a principal is the identifier of someone performing a request or "call" (hence "caller"). Every call must have a valid principal. There is also a special principal for anonymous calls. When using Internet Identity you are using [self-authenticating principals](https://smartcontracts.org/docs/interface-spec/index.html#principal), which is a very fancy way of saying that you have a private key on your laptop (hidden behind TouchID, Windows Hello, etc) that your browser uses to sign and prove that you are indeed the person issuing the calls to the IC.

If the IC actually lets the call (request) through to the `whoami` canister, it means that everything checked out, and the `whoami` canister just responds with the information the IC adds to requests, namely your identity (principal).

### Using the Auth-Client Library To Log In With Internet Identity

DFINITY provides an [easy-to-use library (agent-js)](https://github.com/dfinity/agent-js) to log in with Internet Identity.

These are the steps required to log in and use the obtained identity for canister calls:
```
// First we have to create and AuthClient.
const authClient = await AuthClient.create();
// Call authClient.login(...) to login with Internet Identity. This will open a new tab
// with the login prompt. The code has to wait for the login process to complete.
// We can either use the callback functions directly or wrap in a promise.
await new Promise((resolve, reject) => {
authClient.login({
onSuccess: resolve,
onError: reject,
});
});
```
Once the user has been authenticated with Internet Identity we have access to the identity:
```
// Get the identity from the auth client:
const identity = authClient.getIdentity();
// Using the identity obtained from the auth client, we can create an agent to interact with the IC.
const agent = new HttpAgent({ identity });
// Using the interface description of our webapp, we create an Actor that we use to call the service methods.
const webapp = Actor.createActor(webapp_idl, {
agent,
canisterId: webapp_id,
});
// Call whoami which returns the principal (user id) of the current user.
const principal = await webapp.whoami();
```
See [`index.js`](./webapp/index.js) for the full working example.
A detailed description of what happens behind the scenes is available in the [client auth protocol specification](https://github.com/dfinity/internet-identity/blob/main/docs/internet-identity-spec.adoc#client-auth-protocol).

### Getting the Canister IDs

Let's now use those canisters. Don't care about details? Skip to the [helpers](#helpers).
Expand Down
39 changes: 24 additions & 15 deletions demos/using-dev-build/webapp/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,22 +17,28 @@ export const init = ({ IDL }) => {

// Autofills the <input> for the II Url to point to the correct canister.
document.body.onload = () => {
const testnetII =
process.env.DFX_NETWORK == "local"
? `http://localhost:8000/?canisterId=${process.env.II_CANISTER_ID}`
: process.env.DFX_NETWORK == "ic"
? `https://${process.env.II_CANISTER_ID}.ic0.app`
: `https://${process.env.II_CANISTER_ID}.dfinity.network`;
document.getElementById("iiUrl").value = testnetII;
let iiUrl;
if (process.env.DFX_NETWORK === "local") {
iiUrl = `http://localhost:8000/?canisterId=${process.env.II_CANISTER_ID}`;
} else if (process.env.DFX_NETWORK === "ic") {
iiUrl = `https://${process.env.II_CANISTER_ID}.ic0.app`;
} else {
iiUrl = `https://${process.env.II_CANISTER_ID}.dfinity.network`;
}
document.getElementById("iiUrl").value = iiUrl;
};

document.getElementById("loginBtn").addEventListener("click", async () => {
// When the user clicks, we let agent-js do its thing and redirect open an II
// tab for authentication
const iiUrl = document.getElementById("iiUrl").value;
// When the user clicks, we start the login process.
// First we have to create and AuthClient.
const authClient = await AuthClient.create();

// This API is just weird
// Find out which URL should be used for login.
const iiUrl = document.getElementById("iiUrl").value;

// Call authClient.login(...) to login with Internet Identity. This will open a new tab
// with the login prompt. The code has to wait for the login process to complete.
// We can either use the callback functions directly or wrap in a promise.
await new Promise((resolve, reject) => {
authClient.login({
identityProvider: iiUrl,
Expand All @@ -41,14 +47,17 @@ document.getElementById("loginBtn").addEventListener("click", async () => {
});
});

// At this point, we're authenticated with II and we can query the whoami canister
// At this point we're authenticated, and we can get the identity from the auth client:
const identity = authClient.getIdentity();
// Using the identity obtained from the auth client, we can create an agent to interact with the IC.
const agent = new HttpAgent({ identity });
// Using the interface description of our webapp, we create an actor that we use to call the service methods.
const webapp = Actor.createActor(webapp_idl, {
agent,
canisterId: webapp_id,
});
const whoAmI = await webapp.whoami();

document.getElementById("loginStatus").innerText = whoAmI.toText();
// Call whoami which returns the principal (user id) of the current user.
const principal = await webapp.whoami();
// show the principal on the page
document.getElementById("loginStatus").innerText = principal.toText();
});

0 comments on commit 5dcffde

Please sign in to comment.