Internet Identity

repository·main·Indexed 19 days ago

https://github.com/dfinity/internet-identity

An authentication and identity service for the Internet Computer (IC) providing secure, passwordless login via passkeys (WebAuthn) and OpenID Connect (Google, Apple, Microsoft). It consists of a backend canister for user data and authentication logic, and a frontend canister for serving web assets. The service issues signed delegations to ensure user privacy by deriving unique identities for each application.

Tokens
42.7K
Snippets
111
Records
178
Agent score
68%

What's inside Internet Identity

  1. Overview of the Test OpenID Provider

    main

    The Test OpenID provider is a throwaway OpenID Connect (OIDC) identity provider (similar to Okta or OneLogin) designed to test Internet Identity's (II) OpenID and SSO sign-in flows. It is built on node-oidc-provider and provides the necessary endpoints for II's two-hop SSO discovery process.

    Warning: This is for test/dev only. It uses in-memory storage, dev signing keys, hardcoded credentials, and sets Access-Control-Allow-Origin: *. Never use this as a real Identity Provider.

    Supported Endpoints

    EndpointPurpose
    GET /.well-known/ii-openid-configurationII's custom SSO indirection doc (client_id, openid_configuration URL, name) — hop 1
    GET /.well-known/openid-configurationStandard OIDC discovery (issuer, jwks_uri, authorization_endpoint, ...) — hop 2
    GET /jwksSigning keys II verifies the ID token against
    GET/POST /tokenToken endpoints
    GET /authAuthorization endpoint
    POST /account/:id/claimsTest helper: set the claims an account returns in its ID token
  2. Overview of the VC Issuer API

    main

    The VC Issuer API is a TypeScript library providing type and zod definitions for the issuer API.

    Technical details:

    • The types located in src/generated are automatically produced from vc_demo_issuer.did.
    • vc_demo_issuer.did is a vendored copy of the Candid interface, ensuring compatibility with the specific issuer release version pinned in .github/versions/vc-issuer.
  3. Understand Internet Identity user flows

    main

    Internet Identity (II) user flows are categorized into four main areas: Registration, Login, Manage Identity, and Add Device.

    Key flow conventions used in documentation:

    • A diamond {} node represents a user entry point.
    • A question mark ? prefixing a screen name indicates the screen's visibility depends on the current state of the user or the Internet Identity canister.

    Note that these flows describe the II interface screens only; WebAuthn flows (handled by the OS, password managers, or hardware devices) are not included in these diagrams.

  4. Overview of the Internet Identity Architecture

    main

    The Internet Identity service is composed of two primary parts:

    1. Backend: A canister residing on a dedicated subnet on the Internet Computer (ICP) with a well-known canister ID.
    2. Frontend: A web application served by the backend canister.

    When integrating Internet Identity into a client application, the architecture follows a similar split:

    • The Client Application Frontend (served by its own canister or website) is the only component that interacts directly with the Internet Identity Service via the client authentication protocol.
    • The Client Application Backend (one or more canisters) interacts with the user's identity after authentication.
  5. Use the Identity Provider API via window.postMessage()

    main

    Internet Identity (II) implements a window.postMessage() interface that allows a Relying Party (RP) to participate in an attribute sharing flow. This flow enables a user to share Verifiable Credentials (VCs) from an issuer through Internet Identity.

    Interaction Model

    Because the flow is interactive (requiring user consent), the Relying Party should not expect an immediate response. The RP should wait for one of three events:

    1. A successful JSON-RPC response containing the verifiablePresentation.
    2. A JSON-RPC error response.
    3. The user closing the II window (which should be treated as an error).

    It is recommended that the RP implements a timeout mechanism to close the II window if no response is received, notifying the user that the flow failed.

  6. Normalize target_origin for principal derivation

    main

    The principal used for a per-app delegation is derived from the target_origin. To ensure correct derivation, follow these rules:

    1. Use Bare Origins: Pass a bare https://<host> (e.g., https://example.com). Do not include paths, ports, or trailing slashes. Non-bare origins bypass internal remapping and derive different principals.
    2. Gateway Remapping: II automatically folds *.icp0.io and *.icp.net gateway origins to the legacy *.ic0.app origin to ensure stable principals.
    3. Custom Derivation Origins: Some applications use a custom derivation origin declared via /.well-known/ii-alternative-origins (e.g., app.example.com might derive principals as <canister>.ic0.app).

    Troubleshooting Principal Mismatches: If mcp_get_accounts returns an empty set or the user's balance appears incorrect, the application is likely using a custom derivation origin. To resolve this, fetch the app's ii-alternative-origins and use that declared origin as the target_origin in your MCP calls.

  7. Understand DKIM verifier test vectors

    main

    The DKIM verifier test suite uses static fixtures to validate its logic. These fixtures consist of two parts:

    1. .eml files: Real RFC 5322 messages containing a DKIM-Signature header.
    2. .txt files: The corresponding DKIM DNS TXT records containing the public key used for validation.

    Supported canonicalization pairs include:

    • c=relaxed/relaxed (Accepted)
    • c=relaxed/simple (Accepted)
    • c=simple/simple (Rejected with UnsupportedCanonicalization error per design §5.2)
  8. How Internet Identity performs two-hop SSO discovery

    main

    Internet Identity uses a two-hop discovery mechanism to resolve SSO providers. The flow works as follows:

    1. Hop 1: The domain resolves /.well-known/ii-openid-configuration to obtain the client_id, the openid_configuration URL, and the provider name.
    2. Hop 2: II uses the openid_configuration URL to fetch standard OIDC discovery data (issuer, jwks_uri, authorization_endpoint).
    3. Verification: II fetches keys from the jwks_uri to verify the ID token.

    Security Constraints: During verification, the canister cross-checks the ID token:

    • aud must match the discovered client_id.
    • iss must match the discovered issuer.
    • The issuer host must match the openid_configuration host.
    • The authorization_endpoint must share the issuer's host.

    The browser uses response_type=code id_token and response_mode=form_post, posting the result to the II origin's /callback.

  9. Understand the ICRC-3 Certified Attribute encoding pipeline

    main

    Internet Identity certifies user attributes (like email or name) as an ICRC-3 Value map. The encoding process follows these steps:

    1. Map Construction: A BTreeMap<String, Icrc3Value> is built containing requested attributes and three implicit entries:
      • implicit:nonce: A 32-byte Blob.
      • implicit:origin: A Text value representing the requester's origin.
      • implicit:issued_at_timestamp_ns: A Nat timestamp.
    2. Candid Encoding: The map is converted to an Irc3Value::Map (maintaining BTreeMap ordering) and Candid-encoded to create a message blob.
    3. Domain Separation: A domain-separated payload is created for signing: signed_message = [0x0e] || "ic-sender-info" || message (where 0x0e is the 14-byte length of the domain string).
    4. Signing: The payload is signed using an IC canister signature, resulting in a CBOR certificate.
  10. The Credential Issuance Lifecycle: Prepare and Get

    main

    Issuing a credential is a two-step process designed to allow for authenticated state transfer and asynchronous signing (e.g., using canister signatures).

    1. Prepare Credential (prepare_credential)

    The issuer validates the signed_id_alias.credential_jws to ensure the user has a valid has_id_alias principal and that the credential_spec is applicable to the caller.

    If valid, the issuer returns PreparedCredentialData.prepared_context. This context is an opaque blob used to transfer information between the preparation and issuance steps. For example, it might contain a timestamped, unsigned version of the VC.

    2. Get Credential (get_credential)

    This is a query call. The caller must provide the same parameters as the preparation step, plus the prepared_context returned previously. The issuer verifies that the context is consistent with the request and returns the final signed credential in JWS format (vc_jws).

    Security Note: Both calls must be authenticated; the caller's principal must match the principal for which the credential is being requested.

    // Step 1: Prepare
    type PrepareCredentialRequest = record {
        signed_id_alias : SignedIdAlias;
        credential_spec : CredentialSpec;
    };
    type PreparedCredentialData = record { prepared_context : opt vec nat8 };
    
    // Step 2: Get (Query)
    type GetCredentialRequest = record {
        signed_id_alias : SignedIdAlias;
        credential_spec : CredentialSpec;
        prepared_context : opt blob;
    };
    type IssuedCredentialData = record { vc_jws : text };
  11. How session keys and delegation chains work

    main

    To allow a client application to act on behalf of a user without requiring constant interaction with a security device, Internet Identity uses delegation chains.

    The Delegation Flow

    1. Authentication: The user authenticates via a security device.
    2. Session Key: The client application uses a session key (e.g., Ed25519 or ECDSA).
    3. Client Delegation: The Internet Identity Service canister creates a delegation from the user's main identity to the session key. This delegation is:
      • Unscoped: Valid for all canisters.
      • Lifetime: Has a maximum lifetime of 30 days (defaulting to 30 minutes).
      • Signed: Uses a canister signature.
    4. Identity Frontend Delegation: The Internet Identity frontend also manages a delegation from the security device's public key to a session key managed by the frontend, allowing it to interact with the backend without re-invoking the security device for every signature.

    This allows the session key to sign for the user's main identity for a specified duration.

  12. How attribute scoping affects ICRC-3 map keys

    main

    When requesting attributes, the omit_scope flag determines the format of the keys in the resulting Irc3Value map:

    • Scoped Keys (omit_scope = false): Keys are prefixed with the issuer's identity. Example: openid:https://accounts.google.com:email
    • Unscoped Keys (omit_scope = true): Keys are simple attribute names. Example: email

    Both modes include the three implicit entries: implicit:issued_at_timestamp_ns, implicit:nonce, and implicit:origin.