3.5 Identities and authentication
Developer identities and ledger accounts are two types of authentication that are used for interacting with canisters and cycles, but what about interacting with applications or websites built on ICP? For that, end users can use Internet Identity. It is ICP's native form of digital identity that can be used to authenticate with apps, such as the NNS dashboard, without having to manage a username or password. Instead, Internet Identity uses a cryptographic key pair that's stored in your computer's hardware. Through this simple and flexible authentication method, developers can provide end users with a frictionless way to authenticate and use applications.
Types of identity
First, let's clearly define the identity and authentication terminology on ICP:
Developer identity: Created using
dfx
. It contains a private/public key pair and has aprincipal
data type derived from the public key. It can be compared to a Bitcoin or Ethereum wallet address.Principals: Generic identifiers that are used for users, canisters, and potentially other future concepts. There is intentionally no way to tell canister principal IDs and user principal IDs apart. You can learn more in the IC specification.
Account identifier: The identifier associated with your ICP ledger account, as specified in the ledger specification.
Wallets: Used to store forms of currency or other assets, such as cycles, ICP, or NFTs.
Internet Identity: ICP's native authentication service. Internet Identity doesn't use usernames and passwords; instead it uses a passkey that is stored in your local device's hardware.
In this guide, you'll learn how to use Internet Identity.
Internet Identity
On traditional Web2 websites and applications, many of them have the option for you to 'Sign in with Google,' which allows you to authenticate with the application using your username and password credentials for Google, preventing you from having to make a new username and password for that application.
ICP uses Internet Identity as the network's native form of authentication.
Internet Identity allows users to register and authenticate with websites or applications without using a username and password. Instead, users can use a unique cryptographic public/private key pair called a passkey that is stored in the secure hardware chip of your computer or phone. This allows you to authenticate with your Internet Identity using methods that unlock your device, such as TouchID, FaceID, or another method.
A different identity is issued for each dapp a user authenticates to and cannot be linked back to the user. With Internet identity, no personal data is shared with dapps or the Internet Identity application itself.
Internet Identity architecture
Internet Identity uses an implementation of the WebAuthn API that runs within a single canister that serves both the II frontend application code and handles the authentication requests. The app's authentication service issues 'delegations' on the user's behalf, which are signed with private cryptographic material created by the WebAuth API that is owned by the user. This private material never leaves the user's device, as it is stored in the local hardware securely. Then, the II frontend uses the WebAuthn API to sign the delegation with the cryptographic material.
For more details on how the Internet Identity architecture works, please refer to the official Internet Identity specification.
Creating an Internet Identity
To create an Internet Identity, navigate to the II frontend URL: https://identity.ic0.app/
Select 'Create New' from the UI.
Next, select 'Create Passkey.'
When prompted, choose how to create your passkey, either on your current device or 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.
With this number and your passkey, you will be able to create and securely connect to ICP dapps. If you lose this number and its associated secret recovery methods, 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.
Then, you can connect your Internet Identity to dapps, such as one shown in the Dapps Explorer:
If you scroll down, you will see an option to add another passkey and options to enable recovery methods. It is highly recommended to enable the recovery methods so that you can recover your Internet Identity if the hardware passkey is ever lost.
Integrating Internet Identity into your dapp
Now let's look at a simple example of how to integrate Internet Identity into the frontend of a dapp.
Open the ICP Ninja Who am I? example. In the project's dfx.json
file, you will see a definition for the Internet Identity canister:
...
"internet_identity": {
"candid": "https://github.com/dfinity/internet-identity/releases/latest/download/internet_identity.did",
"type": "custom",
"specified_id": "rdmx6-jaaaa-aaaaa-aaadq-cai",
"remote": {
"id": {
"ic": "rdmx6-jaaaa-aaaaa-aaadq-cai"
}
},
"wasm": "https://github.com/dfinity/internet-identity/releases/latest/download/internet_identity_dev.wasm.gz"
}
...
In the file, you will see the code that initializes and creates the AuthClient, which uses Internet Identity to provide user authentication:
const App = () => {
const [state, setState] = useState({
actor: undefined,
authClient: undefined,
isAuthenticated: false,
principal: 'Click "Whoami" to see your principal ID'
});
// Initialize auth client
useEffect(() => {
updateActor();
}, []);
const updateActor = async () => {
const authClient = await AuthClient.create();
const identity = authClient.getIdentity();
const actor = createActor(canisterId, {
agentOptions: {
identity
}
});
const isAuthenticated = await authClient.isAuthenticated();
setState((prev) => ({
...prev,
actor,
authClient,
isAuthenticated
}));
};
const login = async () => {
await state.authClient.login({
identityProvider,
onSuccess: updateActor
});
};
const logout = async () => {
await state.authClient.logout();
updateActor();
};
const whoami = async () => {
setState((prev) => ({
...prev,
principal: 'Loading...'
}));
const result = await state.actor.whoami();
const principal = result.toString();
setState((prev) => ({
...prev,
principal
}));
};
This code does the following:
First, it creates an
AuthClient
instance usingAuthClient.create()
. This is from theauth-client
library used for handling authentication with Internet Identity.It gets the user's identity from the
authClient
.Then it creates an actor using the
createActor
function.Checks if the user is authenticated using
authClient.isAuthenticated()
.Updates the component's state with the new actor,
authClient
, andisAuthenticated
status.Lastly, the
result
variable awaits the response of a call to the backend'swhoami
function. When the response is returned, theprincipal
variable stores it as aString
data type.
The backend's whoami
function is defined in backend/app.mo
:
import Principal "mo:base/Principal";
persistent actor Whoami {
public query (message) func whoami() : async Principal {
message.caller;
};
};
Interacting with the integration
Click the "Deploy" button in ICP Ninja. Once deployed, navigate to the application's frontend URL returned in the output log. You will see the frontend of the app:
Then, select 'Log in.' You'll be redirected to the II frontend. Since you're running this locally, note that this is for testing only, and you should not use your production II. It is recommended to create another for local testing purposes. To do so, follow the on-screen steps that you walked through previously.
Once you are redirected back to the frontend of the app, click the 'Who am I?' button.
Your Internet Identity's principal ID will be returned:
You've now integrated Internet Identity into a local dapp! That'll wrap things up for this module.

Did you get stuck somewhere in this tutorial, or do you feel like you need additional help understanding some of the concepts? The ICP community has several resources available for developers, like working groups and bootcamps, along with our Discord community, forum, and events such as hackathons. Here are a few to check out:
- Developer Discord
- Developer Liftoff forum discussion
- Developer tooling working group
- Motoko Bootcamp - The DAO Adventure
- Motoko Bootcamp - Discord community
- Motoko developer working group
- Upcoming events and conferences
- Upcoming hackathons
- Weekly developer office hours to ask questions, get clarification, and chat with other developers live via voice chat.
- Submit your feedback to the ICP Developer feedback board