Skip to content

Commit fe0b455

Browse files
authored
docs: Internet Identity spec reference (#91)
## Summary - Identity design: anchor model, principal-per-app isolation with derivation formula, multi-device setup - Passkey management: WebAuthn registration/assertion, ECDSA P-256/Ed25519, OpenID login - Client authentication protocol: step-by-step flow, delegation structure, session key lifecycle - Delegation chain format: wire-level fields, IC verification algorithm - Canister signatures: certified variables, public key OID and encoding - Alternative frontend origins: .well-known/ii-alternative-origins protocol - Protocol guarantees and non-guarantees ## Sync recommendation `informed by dfinity/portal — docs/building-apps/authentication/internet-identity/; dfinity/icskills — skills/internet-identity/SKILL.md`
1 parent 280a55d commit fe0b455

1 file changed

Lines changed: 259 additions & 9 deletions

File tree

‎docs/reference/internet-identity-spec.md‎

Lines changed: 259 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,265 @@ sidebar:
55
order: 12
66
---
77

8-
TODO: Write content for this page.
8+
Internet Identity (II) is the Internet Computer's native authentication system. This page describes the protocol that II uses to authenticate users: how delegation chains are structured, how passkeys and OpenID Connect (OIDC) providers are managed, how canister signatures work, and how the alternative origins mechanism lets multiple domains share the same user principal.
99

10-
<!-- Content Brief -->
11-
Reference for the Internet Identity protocol. Cover delegation chain structure, passkey management (WebAuthn, platform authenticators), canister signatures, alternative origins mechanism, and session management. Link to the full II specification and the II canister source.
10+
For a practical integration guide with working code, see [Internet Identity](../guides/authentication/internet-identity.md).
1211

13-
<!-- Source Material -->
14-
- Portal: references/ (II section)
15-
- icskills: internet-identity
12+
## Canister IDs
1613

17-
<!-- Cross-Links -->
18-
- guides/authentication/internet-identity -- practical integration guide
19-
- reference/system-canisters -- II canister ID
14+
| Canister | ID | URL |
15+
|---|---|---|
16+
| Internet Identity backend | `rdmx6-jaaaa-aaaaa-aaadq-cai` | — |
17+
| Internet Identity frontend | `uqzsh-gqaaa-aaaaq-qaada-cai` | `https://id.ai` |
18+
19+
Both IDs are identical on local replicas when `ii: true` is set in your network configuration. See [System Canisters](system-canisters.md) for the hosting subnet and full canister listing.
20+
21+
## Identity design and data model
22+
23+
Internet Identity uses an **identity anchor** model. Each user creates one or more anchors (numeric identifiers), and each anchor can have multiple authentication devices registered to it.
24+
25+
### Principal-per-app isolation
26+
27+
II derives a **different principal** for each frontend origin. A user logging into `https://app-a.icp0.io` gets a different principal than when logging into `https://app-b.icp0.io`, even with the same anchor and the same passkey. This principal-per-app isolation has two security properties:
28+
29+
- A delegation issued for one dapp cannot be used to authenticate at another.
30+
- Multiple dapps cannot correlate a user's activity across services.
31+
32+
The principal for a user at a given origin is computed as:
33+
34+
```
35+
principal = SHA-224(DER-encoded_canister_signature_public_key) · 0x02
36+
```
37+
38+
where the canister signature public key encodes both the signing canister (`rdmx6-…`) and a seed derived from the anchor number and the frontend origin. This is the self-authenticating principal form defined in the [IC interface specification](ic-interface-spec.md).
39+
40+
### Anchors and devices
41+
42+
An **anchor** is an unsigned 64-bit integer. Users can register multiple devices (passkeys, security keys, recovery phrases) against a single anchor. All devices associated with an anchor produce the same set of principals — the principal depends on the anchor number and origin, not on which device was used to authenticate.
43+
44+
## Passkey management
45+
46+
II uses the [WebAuthn](https://www.w3.org/TR/webauthn/) standard to register and authenticate devices. WebAuthn defines two operations:
47+
48+
- **Registration (`create`)** — generates a new key pair on the authenticator and returns the public key and a credential ID to the relying party (the II frontend).
49+
- **Assertion (`get`)** — proves possession of the private key by signing a challenge.
50+
51+
### Supported key types
52+
53+
II supports the key types used by common platform and roaming authenticators:
54+
55+
| Key type | Curve | Algorithm |
56+
|---|---|---|
57+
| ECDSA P-256 | secp256r1 | ES256 (SHA-256) |
58+
| Ed25519 | Curve25519 | EdDSA |
59+
60+
Platform authenticators (Touch ID, Face ID, Windows Hello) typically use ECDSA P-256. Some hardware security keys support Ed25519; ECDSA P-256 is more universally supported.
61+
62+
### OpenID Connect (OIDC) login
63+
64+
In addition to passkeys, II supports OpenID Connect (OIDC) providers (Google, Apple, Microsoft). An OpenID Connect login produces the same principal as a passkey login for the same anchor — the key type differs, but the principal derivation uses the same anchor number and frontend origin.
65+
66+
## Client authentication protocol
67+
68+
The client authentication protocol is how a dapp frontend requests authentication from II. It uses the browser's `postMessage` API to communicate between the dapp origin and the II frontend origin.
69+
70+
### Overview
71+
72+
1. The dapp frontend generates a **session key pair** (ephemeral Ed25519 key pair) and stores the private key in memory or session storage.
73+
2. The dapp opens the II frontend (`https://id.ai`) in a popup window, passing the session public key and requested delegation parameters.
74+
3. The user authenticates with their passkey.
75+
4. II signs a **delegation** from the anchor's principal key to the session public key.
76+
5. II returns the delegation to the dapp via `postMessage`.
77+
6. The dapp attaches the session key and delegation to canister calls.
78+
79+
The II frontend authenticates the requesting origin using the frontend origin in the `postMessage` call. This is what derives the origin-specific principal — II uses the frontend origin (scheme + host + port) as the seed input when computing the delegation.
80+
81+
### Delegation structure
82+
83+
A delegation in the II protocol has the following fields:
84+
85+
| Field | Type | Description |
86+
|---|---|---|
87+
| `pubkey` | `blob` | The session public key to delegate to |
88+
| `expiration` | `nat` | Expiry timestamp in nanoseconds since Unix epoch |
89+
| `targets` | `array of CanisterId` (optional) | If set, the delegation only applies to these canisters |
90+
91+
The delegation is signed by the II canister using a **canister signature** (see [Canister signatures](#canister-signatures) below). The dapp then uses the session key to sign individual canister calls, attaching the II delegation as `sender_delegation` in the request envelope.
92+
93+
### Expiry constraints
94+
95+
- **Default recommendation:** 8 hours (`BigInt(8) * BigInt(3_600_000_000_000)` nanoseconds).
96+
- **Maximum:** 30 days (2,592,000,000,000,000 nanoseconds). Longer values are silently clamped by II.
97+
98+
The IC validates delegation expiry on every request. Expired delegations are rejected.
99+
100+
### Session key
101+
102+
The session key is a short-lived key pair generated by the dapp frontend. Its purpose is to avoid exposing the user's anchor key to the frontend. The lifecycle is:
103+
104+
- Generated fresh at the start of each authentication flow.
105+
- Private key stays in the browser (memory or `sessionStorage`).
106+
- Discarded after logout or expiry.
107+
108+
The backend canister sees the user's principal (derived from the anchor key), not the session key. The session key is only used to sign the transport layer — the IC verifies the delegation chain and surfaces the anchor-derived principal to canister code.
109+
110+
## Delegation chain format
111+
112+
The IC interface specification defines the complete wire format for delegation chains. The relevant fields in an II-authenticated canister call are:
113+
114+
| Field | Description |
115+
|---|---|
116+
| `sender_pubkey` | DER-encoded session public key |
117+
| `sender_delegation` | Array of signed delegations |
118+
| `sender_sig` | Signature over the request, using the session private key |
119+
120+
The `sender_delegation` field is an array. For a typical II authentication, there is one delegation: from the II canister's per-app key to the session public key. The IC walks the chain:
121+
122+
1. Verifies `sender_pubkey` is a self-authenticating principal encoding of the `sender`.
123+
2. For each delegation in `sender_delegation`, verifies the signature and checks that expiry has not passed.
124+
3. Verifies `sender_sig` using the final key in the chain.
125+
126+
Delegation chains may not contain cycles or self-signed delegations. The maximum chain length accepted by the IC is 20 delegations. See the [IC interface specification](ic-interface-spec.md) for the full verification algorithm.
127+
128+
## Canister signatures
129+
130+
The II canister uses **canister signatures** to sign delegations. A canister signature is an IC-specific signature scheme where a canister proves a value by including it in its certified data.
131+
132+
### How it works
133+
134+
1. The II canister stores an empty blob at path `["sig", SHA-256(seed), SHA-256(payload)]` in its certified variable tree. This causes the certified data root hash to commit to both the seed and the payload.
135+
2. A certification is produced: a certificate containing the certified data root hash derived from this tree.
136+
3. The signature returned to the dapp consists of the certificate plus a witness tree that proves the path existed.
137+
138+
The verifier checks:
139+
- The certificate's root hash matches the IC's certified state root.
140+
- The witness tree has a hash that matches the certified data value in the certificate, and contains the path `["sig", SHA-256(seed), SHA-256(payload)]`.
141+
- The delegation payload hash matches.
142+
143+
### Public key encoding
144+
145+
A canister signature public key is a DER-encoded `SubjectPublicKeyInfo` with OID `1.3.6.1.4.1.56387.1.2`. The `BIT STRING` field encodes:
146+
147+
```
148+
|signing_canister_id| · signing_canister_id · seed
149+
```
150+
151+
where `|signing_canister_id|` is a one-byte length prefix and `·` is concatenation. This encoding is what II uses to produce per-app, per-anchor principal keys — the seed encodes the anchor number and origin.
152+
153+
For the full formal definition, see the "Canister signatures" section of the [IC interface specification](ic-interface-spec.md).
154+
155+
## Alternative frontend origins
156+
157+
By default, a user gets a different principal on each distinct frontend origin. Alternative origins let multiple domains produce the same principal.
158+
159+
### When to use this
160+
161+
Alternative origins are useful when:
162+
163+
- You are migrating from `<canister-id>.icp0.io` to a custom domain and need existing users to keep their principals.
164+
- You serve your app from multiple domains within the same organization and want principals to match.
165+
- You serve your app from `/` and `/login` and want both paths to produce the same principal (though subdirectory paths within the same origin already produce the same principal).
166+
167+
:::note
168+
II automatically handles the `icp0.io` vs `ic0.app` domain difference — you do **not** need alternative origins for that case.
169+
:::
170+
171+
### Protocol
172+
173+
The protocol follows a discovered configuration model. The dapp designates a **primary origin (A)** and lists alternative origins (B, C, …) in a well-known endpoint:
174+
175+
1. The primary origin (A) serves a JSON document at:
176+
```
177+
GET https://<origin-A>/.well-known/ii-alternative-origins
178+
```
179+
with response body:
180+
```json
181+
{
182+
"alternativeOrigins": [
183+
"https://www.alternatedomain.com"
184+
]
185+
}
186+
```
187+
Maximum 10 entries. No trailing slashes or paths. The document must be served from a canister using **certified assets** — II verifies the response is authentic using the IC's certified variables mechanism before honoring it.
188+
189+
2. The alternative origin (B) sets `derivationOrigin` in its login call:
190+
```javascript
191+
// assumes authClient is initialized — see the Internet Identity guide
192+
authClient.login({
193+
identityProvider: "https://id.ai",
194+
derivationOrigin: "https://<origin-A>",
195+
onSuccess: () => { /* ... */ },
196+
});
197+
```
198+
199+
3. II fetches `/.well-known/ii-alternative-origins` from the `derivationOrigin`, verifies the certificate, confirms the requesting origin is listed, and issues a delegation for the principal derived from origin A (not origin B).
200+
201+
The primary origin (A) does not set `derivationOrigin` — it authenticates normally and its origin is the canonical derivation origin.
202+
203+
### Asset canister configuration
204+
205+
The `.well-known/` directory and the `ii-alternative-origins` file (no extension) must be explicitly configured in the asset canister to avoid being treated as hidden files:
206+
207+
```json
208+
[
209+
{
210+
"match": ".well-known",
211+
"ignore": false
212+
},
213+
{
214+
"match": ".well-known/ii-alternative-origins",
215+
"headers": {
216+
"Access-Control-Allow-Origin": "*",
217+
"Content-Type": "application/json"
218+
},
219+
"ignore": false
220+
}
221+
]
222+
```
223+
224+
See the [Internet Identity guide](../guides/authentication/internet-identity.md) for the complete setup with file layout.
225+
226+
## Session management
227+
228+
### Checking authentication state
229+
230+
The `AuthClient` stores the delegation in `localStorage` so sessions persist across page reloads. Call `authClient.isAuthenticated()` on page load to check whether a valid (non-expired) delegation is stored.
231+
232+
If `isAuthenticated()` returns `true`, call `authClient.getIdentity()` to get the delegation identity and create an authenticated agent without prompting the user to re-authenticate.
233+
234+
### Logout
235+
236+
Calling `authClient.logout()` removes the delegation from `localStorage`. The session key is discarded. The delegation that was issued by II remains valid until its expiry — it is not revoked at the protocol level. Logout is a client-side operation only.
237+
238+
### Delegation expiry and "remember me" flows
239+
240+
- **Short session (8 hours):** Use for typical dapps where re-authentication is acceptable. The user will be prompted again after 8 hours.
241+
- **Long session (up to 30 days):** Use for "remember me" flows. The delegation remains valid for 30 days; the user is only prompted if they explicitly log out or if the delegation expires.
242+
243+
## Protocol boundaries
244+
245+
This section clarifies what the II protocol guarantees and what it does not.
246+
247+
**II guarantees:**
248+
- Each (anchor, origin) pair produces a stable, unique principal.
249+
- Delegations are signed by the II canister's key and can be verified using the IC's certified state.
250+
- Alternative origin lookups are verified using certified assets, preventing an attacker from spoofing the `.well-known/ii-alternative-origins` response.
251+
252+
**II does not guarantee:**
253+
- Revoking individual delegations before their expiry. Logout is client-side only.
254+
- Cross-device session synchronization. Sessions are stored per-browser.
255+
- Account recovery by default. Recovery phrases must be explicitly registered as a device.
256+
257+
## Full specification
258+
259+
The complete Internet Identity specification, including the full Candid interface for the II canister, is maintained in the [dfinity/internet-identity](https://github.com/dfinity/internet-identity) repository.
260+
261+
The Candid interface (`internet_identity.did`) describes every method the II canister exposes, including `create_challenge`, `register`, `add`, `remove`, `get_anchor_info`, `get_delegation`, and `prepare_delegation`. Refer to that file for the canonical types and method signatures.
262+
263+
## Next steps
264+
265+
- [Internet Identity guide](../guides/authentication/internet-identity.md) — practical integration with working code examples
266+
- [System Canisters](system-canisters.md) — canister ID, hosting subnet, and lifecycle information
267+
- [IC Interface Specification](ic-interface-spec.md) — delegation chain wire format, canister signature verification, and the full principal encoding spec
268+
269+
<!-- Upstream: informed by dfinity/portal — docs/building-apps/authentication/integrate-internet-identity.mdx, docs/building-apps/authentication/alternative-origins.mdx, docs/building-apps/security/iam.mdx, docs/references/ic-interface-spec.md; dfinity/icskills — skills/internet-identity/SKILL.md -->

0 commit comments

Comments
 (0)