Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .sources/VERSIONS
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,4 @@
# -------------------------------------------------------

motoko v1.16.1 01aee06
internetidentity release-2026-09-25 64ba1637
internetidentity release-2026-10-16 8d3e876b
2 changes: 1 addition & 1 deletion .sources/internetidentity
Submodule internetidentity updated 239 files
2 changes: 1 addition & 1 deletion docs/references/internet-identity-spec.md
Original file line number Diff line number Diff line change
Expand Up @@ -457,7 +457,7 @@ The complete Candid interface definition is available at [`internet-identity.did

**Authorization**: This `register` request must be sent to the canister with `caller` that is the self-authenticating id derived from the given `DeviceKey`.

The `register` method is used to create a new user. The Internet Identity Service backend creates a _fresh_ Identity Anchor, creates the Identity record, and adds the given device as the first device.
The `register` method is used to create a new user. The Internet Identity Service backend creates a _fresh_ Identity Anchor, creates the Identity record, and adds the given device as the first device. If the public key or the credential id of the given device is already used by an identity, the call returns `device_already_used` and no Identity Anchor is created.

In order to protect the Internet Computer from too many "free" update calls, and to protect the Internet Identity Service from too many user registrations, this call is protected using a CAPTCHA challenge. The `register` call can only succeed if the `ChallengeResult` contains a `key` for a challenge that was created with `create_challenge` (see below) in the last 5 minutes _and_ if the `chars` match the characters that the Internet Identity Service has stored internally for that `key`.

Expand Down
149 changes: 134 additions & 15 deletions public/references/internet-identity.did
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,8 @@ type RegisterResponse = variant {
canister_full;
// The challenge was not successful.
bad_challenge;
// The device (its public key or credential id) is already used by an identity.
device_already_used;
};

type AddTentativeDeviceResponse = variant {
Expand Down Expand Up @@ -304,6 +306,11 @@ type InternetIdentityInit = record {
// serve the list over plain http. null / opt false (the default) require https
// for every notifying origin, and a non-loopback origin always requires https.
notifications_allow_insecure_sender_list : opt bool;
// Deploy flag relaxing the https requirement for the Web Push endpoint a
// browser registers, for a deployment whose relay is a local server rather
// than a push service. As above, only loopback hosts (localhost / 127.0.0.1)
// may then be plain http; null / opt false (the default) require https.
notifications_allow_insecure_endpoint : opt bool;
// Configuration for Web Analytics
analytics_config : opt opt AnalyticsConfig;
// Configuration to show dapps explorer or not
Expand Down Expand Up @@ -339,12 +346,11 @@ type InternetIdentityInit = record {
// set/clear pattern as `dnssec_config`: null keeps the previously stored
// value, `opt null` clears it, `opt opt "https://..."` sets it.
mcp_official_url : opt opt text;
// Server-side kill switch for the notifications feature. null / `opt false`
// (the default) disables every notification endpoint; `opt true` enables
// them. Omitting it on upgrade keeps the stored value.
// Apps allowed to notify. Omitted on upgrade keeps the stored list, an empty list
// turns notifications off, and entries enable them for those origins only.
notifications_enabled_origins : opt vec text;
// Server-side switch for the notifications feature. `opt true` enables every
// notification endpoint, for any app; `opt false` disables them. Omitting it on
// upgrade keeps the stored value, and a canister that never stored one has them
// disabled.
notifications_enabled : opt bool;
};

// DNSSEC trust-anchor list. Any feature that needs DNSSEC-verified DNS
Expand Down Expand Up @@ -451,6 +457,10 @@ type OpenIdEmailVerification = variant {
Unknown;
Google;
Microsoft;
// Trusts email_verified like Google. Apple's private relay addresses,
// which only senders registered with II's Apple developer team can deliver
// mail to, are not kept on the credential at all.
Apple;
};

type OpenIdConfig = record {
Expand Down Expand Up @@ -491,12 +501,24 @@ type SsoDiscovery = record {
session_max_age_ns : nat64;
};

// Status of a domain's SSO discovery, read by `get_sso_discovery_status`. A
// failed fetch isn't a distinct status — it reads as `Pending` and the frontend
// times out — so the statuses are: resolved, or in flight.
// Status of a domain's SSO discovery, read by `get_sso_discovery_status`.
// `Failed.retry_after` is when II fetches the domain again (a retry before then
// fails the same way), and is absent when no retry can help, such as a value
// that is not a domain. `reason` explains the failure, to show as is, when II
// has one.
type SsoDiscoveryStatus = variant {
Resolved : SsoDiscovery;
Pending;
Failed : record { retry_after : opt Timestamp; reason : opt text };
};

// Whether an organization domain can be used for SSO sign-in, read by
// `app_sso_domain_status`. `name` is the organization's display name;
// `retry_after` and `reason` are as for `SsoDiscoveryStatus.Failed`.
type AppSsoDomainStatus = variant {
Available : record { name : opt text };
Pending;
Unavailable : record { retry_after : opt Timestamp; reason : opt text };
};

// Request for `get_sso_discovery_status`.
Expand Down Expand Up @@ -1509,6 +1531,43 @@ type AccountUpdate = record {
name : opt text;
};

// An app the identity decided a permission for, allowed or denied, for the user's own
// list of their apps.
type ApplicationInfo = record {
// The origin the app's identity is derived for: what its accounts and its
// notification consent are stored under.
origin : FrontendHostname;
// The latest sign-in to any of the identity's accounts at the app, or null where
// none was used.
last_used : opt Timestamp;
// Whether the app may notify the identity: it holds consent, and this deployment
// notifies for it, as notification_consent_granted answers.
notifications_allowed : bool;
// When the app last had a notification queued for one of the identity's browsers,
// or null where it never has.
last_notified : opt Timestamp;
};

type ListApplicationsRequest = record {
anchor_number : UserNumber;
};

type ListApplicationsError = variant {
Unauthorized : principal;
InternalCanisterError : text;
};

type ForgetApplicationsRequest = record {
anchor_number : UserNumber;
// As list_applications spells them.
origins : vec FrontendHostname;
};

type ForgetApplicationsError = variant {
Unauthorized : principal;
InternalCanisterError : text;
};

type DummyAuthConfig = record {
// Prompts user for a index value (0 - 255) when set to true,
// this is used in e2e to have multiple dummy auth identities.
Expand Down Expand Up @@ -1907,6 +1966,44 @@ type NotificationDelegationError = variant {
InternalCanisterError : text;
};

// ===== Notifications a browser has yet to show =====

type GetNextNotificationRequest = record {
anchor_number : UserNumber;
};

// What a service worker shows for one wake-up: the app and account it is for, the
// canister holding its content, and which notification.
type NotificationToShow = record {
origin : FrontendHostname;
account_number : opt AccountNumber; // null = the unreserved default account
canister_id : principal;
id : NotificationId;
};

// Null once nothing is left to show.
type GetNextNotificationResponse = record {
notification : opt NotificationToShow;
};

type GetNextNotificationError = variant {
// Also a caller that is no browser of the identity.
InternalCanisterError : text;
};

type RemoveNotificationRequest = record {
anchor_number : UserNumber;
// As browser_get_next_notification returned it.
notification : NotificationToShow;
};

type RemoveNotificationResponse = record {};

type RemoveNotificationError = variant {
// Also a caller that is no browser of the identity.
InternalCanisterError : text;
};

service : (opt InternetIdentityInit) -> {
// Legacy identity management API
// ==============================
Expand Down Expand Up @@ -2049,16 +2146,24 @@ service : (opt InternetIdentityInit) -> {
openid_prepare_delegation : (JWT, Salt, SessionKey, opt text) -> (variant { Ok : OpenIdPrepareDelegationResponse; Pending; Err : OpenIdDelegationError });
openid_get_delegation : (JWT, Salt, SessionKey, Timestamp, opt text) -> (variant { Ok : SignedDelegation; Pending; Err : OpenIdDelegationError }) query;

// SSO discovery for the sign-in initiation flow. The frontend polls
// `get_sso_discovery_status` (query) and, while it reads `Pending`, drives the
// on-demand two-hop discovery fetch with `discover_sso` (update); once the
// fetch completes the query returns `Resolved` with the config.
// SSO discovery for the sign-in initiation flow. The frontend calls
// `discover_sso` (update) once, which starts the two-hop discovery fetch and
// the domain's key fetch, or refreshes a stale result, then polls
// `get_sso_discovery_status` (query) until it reads `Resolved` or `Failed`.
//
// The optional second argument is the target dapp origin; when supplied,
// `resolved_client_id` reports the client that origin must use (`null` = denied).
discover_sso : (text) -> ();
get_sso_discovery_status : (GetSsoDiscoveryStatusRequest) -> (SsoDiscoveryStatus) query;

// Whether an organization domain can be used for SSO sign-in, for apps that
// check a domain before sending the user into the flow. Call
// `app_sso_domain_check` (update) once to start the fetch, then poll
// `app_sso_domain_status` (query) until it reads `Available` or
// `Unavailable`.
app_sso_domain_check : (text) -> ();
app_sso_domain_status : (text) -> (AppSsoDomainStatus) query;

// SSO sign-in path. Mints a delegation only if the JWT's `aud` matches the
// client the target origin resolves to. `Pending` means the discovery/JWKS
// cache is cold — re-call to drive the fetch.
Expand Down Expand Up @@ -2185,6 +2290,15 @@ service : (opt InternetIdentityInit) -> {
origin : FrontendHostname,
) -> (variant { Ok : vec AccountInfo; Err: GetAccountsError }) query;

// Every app the identity decided a permission for, so the user can change or forget
// what they decided. Authorized by the identity's own access methods.
list_applications : (ListApplicationsRequest) -> (variant { Ok : vec ApplicationInfo; Err : ListApplicationsError }) query;
// Undoes every permission decision for the apps, drops what they queued for the
// identity's browsers and signs out every session at them, as one write. Accounts and
// the default account stay. An origin the identity holds nothing at is already
// forgotten.
forget_applications : (ForgetApplicationsRequest) -> (variant { Ok; Err : ForgetApplicationsError });

create_account : (
anchor_number : UserNumber,
origin : FrontendHostname,
Expand Down Expand Up @@ -2391,13 +2505,18 @@ service : (opt InternetIdentityInit) -> {
prepare_notification_delegation : (PrepareNotificationDelegationRequest) -> (variant { Ok : PrepareNotificationDelegationResponse; Err : NotificationDelegationError });
get_notification_delegation : (GetNotificationDelegationRequest) -> (variant { Ok : GetNotificationDelegationResponse; Err : NotificationDelegationError }) query;

// Called by the service worker on a wake-up, signed with the browser key: the oldest
// notification its browser has yet to show, passing over the ones it skips.
browser_get_next_notification : (GetNextNotificationRequest) -> (variant { Ok : GetNextNotificationResponse; Err : GetNextNotificationError }) query;
// Called by the service worker for the one it shows, while it fetches the content.
browser_remove_notification : (RemoveNotificationRequest) -> (variant { Ok : RemoveNotificationResponse; Err : RemoveNotificationError });

// Called by the browser itself, signed with the browser key it signs in with.
set_webpush_subscription : (SetWebPushSubscriptionRequest) -> (variant { Ok; Err : SetWebPushSubscriptionError });
// Called by the identity, so one browser can silence another.
remove_webpush_subscription : (RemoveWebPushSubscriptionRequest) -> (variant { Ok; Err : RemoveWebPushSubscriptionError });
get_webpush_subscription_status : (GetWebPushSubscriptionStatusRequest) -> (opt WebPushSubscriptionStatus) query;

// Called by an app's backend canister for the origin it names. Not
// implemented yet: every call is refused.
// Called by an app's backend canister for the origin it names.
app_send_notification : (SendNotificationArg) -> (variant { Ok : SendNotificationResponse; Err : SendNotificationError });
};
Loading