From bd90222cfb6e4dbbac81cbea10d057b25f1435ee Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 19 Aug 2026 08:31:06 +0000 Subject: [PATCH 1/3] docs: cover the ii-app-metadata well-known file in the II guide Apps can now provide their own name, description, and logo for the Internet Identity sign-in screens by serving /.well-known/ii-app-metadata on the origin their identities are derived for, replacing the curated list that used to be the only way to get branded. Nothing in the guide covered it. The new section sits between Alternative origins and Common mistakes, which is where it belongs: it reuses the derivation origin the reader has just configured, and extends the same .ic-assets.json5 with CORS entries for the document and the logo. It carries the limits an integrator has to respect (field lengths, the raster-only logo rules, the document cap), the fact that one invalid field drops the whole document and why the browser console is the place to look, and the reminder that this metadata proves nothing about an app's identity, which is why the origin stays on screen next to it. --- .../authentication/internet-identity.mdx | 57 ++++++++++++++++++- 1 file changed, 56 insertions(+), 1 deletion(-) diff --git a/docs/guides/authentication/internet-identity.mdx b/docs/guides/authentication/internet-identity.mdx index b21edb7..7e8562c 100644 --- a/docs/guides/authentication/internet-identity.mdx +++ b/docs/guides/authentication/internet-identity.mdx @@ -603,6 +603,61 @@ To keep principals consistent across your own custom domains, configure **altern For full details, see the [Internet Identity specification](../../references/internet-identity-spec.md). +## App metadata + +By default, the sign-in screens identify your app by its origin alone. To have II show your app's name, a short description, and its logo, serve a JSON document at `/.well-known/ii-app-metadata`. Any app can publish it: there is no list to join and no approval step. + +```json +{ + "name": "Example App", + "description": "A short tagline shown on the sign-in screen", + "logo": "/logo.png" +} +``` + +II fetches this document when the authorization flow starts, from the origin your users' identities are derived for: your `derivationOrigin` when you set one (see [Alternative origins](#alternative-origins) above), and the origin the request came from otherwise. Publish it once on that origin, and every alternative origin listed there is presented with the same name, description, and logo, with nothing to keep in sync between them. + +All three fields are optional, and unknown fields are ignored, so a document stays valid as fields are added: + +- `name` is limited to 40 characters and `description` to 120, counted in Unicode code points on the value as served. Runs of whitespace are collapsed before display. +- Control characters and the bidirectional embedding and override characters `U+202A` to `U+202E` are rejected, since they can make rendered text read differently from what it contains. The bidirectional marks and isolates that mixed-direction names legitimately need are accepted. +- A field that fails validation invalidates the **whole document**, which is then ignored, so an app is never shown with half of its metadata applied. II logs which field is at fault to the browser console: check the console on the sign-in screen if your metadata does not appear. +- `logo` must point to a raster image on the same origin as the document (relative URLs resolve against it), served as `image/png`, `image/jpeg`, `image/webp`, `image/gif`, or `image/avif`, at most 1 MiB and 4096 pixels per side. SVG is not accepted. II downloads the image, re-encodes it at up to 512 pixels on its longest side, and renders its own copy, so a roughly square PNG or WebP of about 512 pixels works well. +- The document must not exceed 8 KiB, must be answered with `200`, and must not redirect. II requests it without credentials and gives up after 10 seconds. + +Both the document and the logo are read cross-origin, so they need CORS headers. Extend the `.ic-assets.json5` shown under [Alternative origins](#alternative-origins) with an entry for each: + +```json +[ + { + "match": ".well-known", + "ignore": false + }, + { + "match": ".well-known/ii-app-metadata", + "headers": { + "Access-Control-Allow-Origin": "*", + "Content-Type": "application/json" + }, + "ignore": false + }, + { + "match": "logo.png", + "headers": { + "Access-Control-Allow-Origin": "*" + } + } +] +``` + +If the document is missing, unreachable, or invalid, sign-in is unaffected: the screens fall back to showing your origin, exactly as they do without it. Metadata is a display nicety and never blocks authentication. + +:::note +This metadata is exactly as trustworthy as the origin serving it, and publishing it does not verify your app's identity in any way. II therefore keeps displaying the origin alongside whatever you provide, since the origin is the value users can actually check. +::: + +For the normative rules, including a JSON schema to validate your document against, see the app metadata section of the [Internet Identity specification](../../references/internet-identity-spec.md). + ## Common mistakes - **Using the wrong II URL per environment**: local development must point to `http://id.ai.localhost:8000`, mainnet to `https://id.ai`. Use the `getIdentityProviderUrl` helper (shown above) to switch based on hostname. @@ -625,4 +680,4 @@ For full details, see the [Internet Identity specification](../../references/int {/* TODO: Add Unity native app integration via deep links: see portal native-apps/unity_ii_* */} -{/* Upstream: informed by dfinity/portal (docs/building-apps/authentication/overview.mdx, docs/building-apps/authentication/integrate-internet-identity.mdx, docs/building-apps/authentication/alternative-origins.mdx); dfinity/icskills (skills/internet-identity/SKILL.md); dfinity/icp-js-sdk-docs (public/auth/latest.zip api/client/: AuthClient, scopedKeys, SignedAttributes, AuthClientCreateOptions; public/core/latest.zip libs/identity/api.md: AttributesIdentity); dfinity/cdk-rs (ic-cdk/src/api.rs); dfinity/motoko-identity-attributes (README.md, src/lib.mo, src/Internal/Verify.mo @ v0.4.1: the mixin and its verification order); caffeinelabs/motoko-core (src/CallerAttributes.mo getAttributes wrapper, src/Map.mo); caffeinelabs/motoko (src/prelude/prim.mo callerInfoData/Signer, test/run-drun/caller-info/caller-info.mo); dfinity/icp-cli (docs/reference/canister-settings.md#environment_variables) */} +{/* Upstream: informed by dfinity/internet-identity (docs/ii-spec.mdx: the App metadata section, #4221); dfinity/portal (docs/building-apps/authentication/overview.mdx, docs/building-apps/authentication/integrate-internet-identity.mdx, docs/building-apps/authentication/alternative-origins.mdx); dfinity/icskills (skills/internet-identity/SKILL.md); dfinity/icp-js-sdk-docs (public/auth/latest.zip api/client/: AuthClient, scopedKeys, SignedAttributes, AuthClientCreateOptions; public/core/latest.zip libs/identity/api.md: AttributesIdentity); dfinity/cdk-rs (ic-cdk/src/api.rs); dfinity/motoko-identity-attributes (README.md, src/lib.mo, src/Internal/Verify.mo @ v0.4.1: the mixin and its verification order); caffeinelabs/motoko-core (src/CallerAttributes.mo getAttributes wrapper, src/Map.mo); caffeinelabs/motoko (src/prelude/prim.mo callerInfoData/Signer, test/run-drun/caller-info/caller-info.mo); dfinity/icp-cli (docs/reference/canister-settings.md#environment_variables) */} From bb5bdc4b75558b058101fc5b8dbebb186490f726 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 24 Aug 2026 13:03:26 +0000 Subject: [PATCH 2/3] docs: link the app metadata spec section by anchor main now mirrors the App metadata section (#350 synced .sources/internetidentity to release-2026-08-21), so the guide can point at #app-metadata instead of the specification page root. This commit originally carried the submodule bump and the regenerated spec files. The rebase dropped them: #350 landed the identical sync first, so only the anchor change remains. --- docs/guides/authentication/internet-identity.mdx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/guides/authentication/internet-identity.mdx b/docs/guides/authentication/internet-identity.mdx index 7e8562c..9150ca4 100644 --- a/docs/guides/authentication/internet-identity.mdx +++ b/docs/guides/authentication/internet-identity.mdx @@ -656,7 +656,7 @@ If the document is missing, unreachable, or invalid, sign-in is unaffected: the This metadata is exactly as trustworthy as the origin serving it, and publishing it does not verify your app's identity in any way. II therefore keeps displaying the origin alongside whatever you provide, since the origin is the value users can actually check. ::: -For the normative rules, including a JSON schema to validate your document against, see the app metadata section of the [Internet Identity specification](../../references/internet-identity-spec.md). +For the normative rules, including a JSON schema to validate your document against, see [App metadata](../../references/internet-identity-spec.md#app-metadata) in the Internet Identity specification. ## Common mistakes From f9115216f84d213b175abcc8189553662d18fa09 Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 24 Aug 2026 13:58:41 +0000 Subject: [PATCH 3/3] docs: correct the logo failure semantics in the app metadata section Review feedback on #347. The bullet stating that a failed field invalidates the whole document sat directly above the logo requirements, which read as though a logo that fails to fetch or decode takes the name and description down with it. It does not: only the shape of `logo` is validated with the rest of the document, and an asset-level failure costs the logo alone. Someone debugging an intermittent 500 on their logo would have drawn the wrong conclusion. Also from the review, both optional: - `U+FEFF` is rejected alongside the control characters, and isolates must be balanced. - A missing or invalid document falls back to the curated entry II still ships for a small list of apps before falling back to the origin alone, so "exactly as they do without it" overstated it. --- docs/guides/authentication/internet-identity.mdx | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/docs/guides/authentication/internet-identity.mdx b/docs/guides/authentication/internet-identity.mdx index 9150ca4..6b89724 100644 --- a/docs/guides/authentication/internet-identity.mdx +++ b/docs/guides/authentication/internet-identity.mdx @@ -620,9 +620,10 @@ II fetches this document when the authorization flow starts, from the origin you All three fields are optional, and unknown fields are ignored, so a document stays valid as fields are added: - `name` is limited to 40 characters and `description` to 120, counted in Unicode code points on the value as served. Runs of whitespace are collapsed before display. -- Control characters and the bidirectional embedding and override characters `U+202A` to `U+202E` are rejected, since they can make rendered text read differently from what it contains. The bidirectional marks and isolates that mixed-direction names legitimately need are accepted. +- Control characters, `U+FEFF`, and the bidirectional embedding and override characters `U+202A` to `U+202E` are rejected, since they can make rendered text read differently from what it contains. The bidirectional marks and isolates that mixed-direction names legitimately need are accepted, provided every isolate a field opens it also closes. - A field that fails validation invalidates the **whole document**, which is then ignored, so an app is never shown with half of its metadata applied. II logs which field is at fault to the browser console: check the console on the sign-in screen if your metadata does not appear. - `logo` must point to a raster image on the same origin as the document (relative URLs resolve against it), served as `image/png`, `image/jpeg`, `image/webp`, `image/gif`, or `image/avif`, at most 1 MiB and 4096 pixels per side. SVG is not accepted. II downloads the image, re-encodes it at up to 512 pixels on its longest side, and renders its own copy, so a roughly square PNG or WebP of about 512 pixels works well. +- Only the shape of `logo` (a non-empty URL on the document's own origin) is part of the validation above. Once it passes, a logo that cannot be fetched or decoded, or that breaks the content type, size, or dimension rules, costs you the logo alone: the name and description still render. Fetching a second resource can fail transiently, so that is treated differently from a mistake in the document itself. - The document must not exceed 8 KiB, must be answered with `200`, and must not redirect. II requests it without credentials and gives up after 10 seconds. Both the document and the logo are read cross-origin, so they need CORS headers. Extend the `.ic-assets.json5` shown under [Alternative origins](#alternative-origins) with an entry for each: @@ -650,7 +651,7 @@ Both the document and the logo are read cross-origin, so they need CORS headers. ] ``` -If the document is missing, unreachable, or invalid, sign-in is unaffected: the screens fall back to showing your origin, exactly as they do without it. Metadata is a display nicety and never blocks authentication. +If the document is missing, unreachable, or invalid, sign-in is unaffected: the screens fall back to the curated entry II still ships for a small list of apps (the mechanism this file supersedes), and to showing your origin alone otherwise. Metadata is a display nicety and never blocks authentication. :::note This metadata is exactly as trustworthy as the origin serving it, and publishing it does not verify your app's identity in any way. II therefore keeps displaying the origin alongside whatever you provide, since the origin is the value users can actually check.