Authentication overview
Beginner
Concept
When building an application that enables users to have profiles or buy and
sell assets, you must implement an authentication method. An authentication
method allows users to log into an application by providing some form of
credential or verification of identity. Authentication methods vary in levels of
security and data privacy.
To implement authentication in your dapp, your application frontend must
provide a user interface component that triggers an authentication workflow.
Then, the backend logic must implement code to handle the authentication
and return a response to the frontend service.
A simple example of this workflow is a basic 'Who am I?' application that uses
Internet Identity for authentication. View the integrating with Internet Identity
documentation for more information.
Authentication methods
Authentication methods available on ICP include:
● Internet Identity: ICP's native identity service that uses a cryptographic
public/private key pair for authentication.
● Email and password: Authentication with an email and password.
● NFID: A digital form of identity that allows users to use an email and
password or their Google account.
● ic-auth: A modular tool to integrate wallet providers into ICP apps.
Supports Stoic, Plug, Internet Identity, and NFID.
● Plug wallet: An in-browser wallet for managing all ICP assets such as
cycles, ICP, tokens, and NFTs.
The following tools enable authenticating with ICP dapps using wallet
addresses from other chains and ecosystems:
● Sign in with Ethereum: An authentication standard that enables
Ethereum wallet-based authentication for ICP applications.
● Sign in with Solana: An authentication standard that enables Solana
wallet-based authentication for ICP applications.
● MSQ library: A client library for dapps to enable user interaction with
ICP solely via their existing MetaMask wallet using the Metamask
Snaps feature.
Internet Identity overview
Intermediate
Concept
Internet Identity is the ICP's native form of identity used for authenticating with
ICP dapps.
Internet Identity doesn't use usernames and passwords. Instead, users utilize
a passkey to register and authenticate with websites and applications.
Passkeys are a unique cryptographic public/private key pair. Internet Identity
issues a new identity for each dapp that a user authenticates with, and the
identity cannot be linked back to the user. No personal data is shared with
dapps or the Internet Identity application itself, and no software downloads are
required.
Internet Identity uses a form of WebAuthn API running in a single canister that
serves both the Internet Identity frontend and backend code. When a user
sends a request to the frontend code, the backend authentication service
issues a delegation on the user's behalf. This delegation is then signed with
the user's passkey.
Internet Identity can be integrated into your dapp for users to authenticate with
as a form of user sign-up and login.
Creating an Internet Identity
Check out how to create an Internet Identity.
Integrating Internet Identity into your dapp
Check out how to integrate Internet Identity into your dapp.
Resources
● Internet Identity dashboard.
● Internet Identity specification.
● Internet Identity GitHub repository.
● Internet Identity alternative frontend origins.
● Internet Identity integration.
Integrating with II
Intermediate
Tutorial
Overview
This guide shows an example of how to integrate Internet Identity into an
application by using a simple 'Who am I?' backend canister and a frontend UI
that returns the Internet Identity principal of the user who calls the backend's
whoami method.
This project uses the pullable version of the Internet identity canister. A
pullable canister is a canister that provides a public service at a static canister
ID. To learn more about pullable canisters, please see the documentation.
Prerequisites
Before you start, verify that you have:
● Downloaded and installed dfx version 0.14.1 or later.
● Node.js v16+.
Step 1: To get started, open a terminal window and create a new project:
● dfx v0.17.0 or newer
● dfx v0.16.1 or older
Start dfx:
dfx start --clean --background
Use dfx new <project_name> to create a new project:
dfx new ii_integration
You will be prompted to select the language that your backend canister will
use. Select 'Motoko':
? Select a backend language: ›
❯ Motoko
Rust
TypeScript (Azle)
Python (Kybra)
Then, select a frontend framework for your frontend canister. Select 'Vanilla
JS':
? Select a frontend framework: ›
SvelteKit
React
Vue
❯ Vanilla JS
No JS template
No frontend canister
Lastly, you can include extra features to be added to your project. Select
'Internet Identity'.
? Add extra features (space to select, enter to confirm) ›
x Internet Identity
⬚ Bitcoin (Regtest)
⬚ Frontend tests
Step 2: For this project, you'll use a simple 'Who am I?' function for the
backend canister. Open the src/ii_integration_backend/main.mo
file and replace the existing content with the following:
actor {
public shared (msg) func whoami() : async Principal {
msg.caller
};
};
In this actor, there is a single method that responds with the caller's principal.
This will show if you make a request from the application's frontend using an
authenticated Internet Identity or an AnonymousIdentity.
Step 3: Install the @dfinity/auth-client package:
npm install @dfinity/auth-client
Step 4: Insert the following code into the
src/ii_integration_frontend/src/index.js file:
/* A simple webapp that authenticates the user with Internet Identity and that
* then calls the whoami canister to check the user's principal.
*/
import { Actor, HttpAgent } from "@dfinity/agent";
import { AuthClient } from "@dfinity/auth-client";
const webapp_id = process.env.WHOAMI_CANISTER_ID;
// The interface of the whoami canister
const webapp_idl = ({ IDL }) => {
return IDL.Service({ whoami: IDL.Func([], [IDL.Principal], ["query"]) });
};
export const init = ({ IDL }) => {
return [];
};
// Autofills the <input> for the II Url to point to the correct canister.
document.body.onload = () => {
let iiUrl;
if (process.env.DFX_NETWORK === "local") {
iiUrl = `http://localhost:4943/?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 start the login process.
// First we have to create and AuthClient.
const authClient = await AuthClient.create();
// 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,
onSuccess: resolve,
onError: reject,
});
});
// 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,
});
// 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();
});
Depending on your web browser, you may need to change the
http://rdmx6-jaaaa-aaaaa-aaadq-cai.localhost:4943 value:
● Chrome, Firefox: http://<canister_id>.localhost:4943
● Safari: http://localhost:4943?canisterId=<canister_id>
This code does the following:
● Interacts with the backend actor to call the whoami method.
● Creates an AuthClient using the auth-client library that is used to
authenticate with Internet Identity.
● Retrieves the identity from the AuthClient.
● Uses the identity to create an agent that interacts with ICP.
● Then, uses the interface description of the app to create an actor that's
used to call the app's service methods.
If you used a project name other than ii_integration, you will need
to rename the imports and environment variable in the code.
Step 5: Insert the following code into the
src/ii_integration_frontend/src/index.html file:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width" />
<title>greet</title>
<base href="/" />
<link rel="icon" href="favicon.ico" />
<link type="text/css" rel="stylesheet" href="main.css" />
</head>
<body>
<main>
<img src="logo2.svg" alt="DFINITY logo" />
<br />
<br />
<form>
<button id="login">Login!</button>
</form>
<br />
<form>
<button id="whoAmI">Who Am I</button>
</form>
<section id="principal"></section>
</main>
</body>
</html>
This code provides a simple UI for us to interact with our application.
If you'd rather clone the repo for this code, it can be found here.
Step 6: Deploy the project:
dfx deps deploy
dfx deploy
Step 8: Navigate to the frontend canister's URL in your web browser. You
will see the frontend of the app:
Step 7: Then, select 'Log in'.
You'll be redirected to the II frontend. Since you're running this locally, this will
be using a local, non-production Internet Identity. To create one, follow the
on-screen steps.
Step 8: Create a local Internet Identity
● Select 'Create New' from the UI.
● Next, select 'Create Passkey'.
● When prompted, choose how to create your passkey, either on your
current device or you can use another device.
● Then, enter the CAPTCHA to continue.
Your Internet Identity has been created! It'll be shown on the screen, and it is
recommended that you write it down in a safe location to save it.
This number is your Internet Identity. With this number and your passkey, you
will be able to create and securely connect to Internet Computer dapps. If you
lose this number, you will lose any accounts that were created with it. This
number is not secret, but is unique to you.
Once you save it, select the 'I saved it, continue' button.
Step 9: Once you are redirected back to the frontend of the app, click the
'Click me!' button.
Step 10: Your Internet Identity's principal ID will be returned:
Local frontend development
When modifying this example's frontend, it is recommended to develop using
a local development server instead of using the deployed frontend canister.
This is because using a local development server will enable Hot Module
Reloading, allowing you to see any modifications made to your frontend
instantaneously, rather than having to redeploy the frontend canister to see
the changes.
To start a local development server, run npm run start. The output will
contain the local address the project is running at, such as 127.0.0.1:4943.
Resources
● Internet Identity dashboard.
● Internet Identity specification.
● Internet Identity GitHub repository.
● Internet Identity alternative frontend origins.