You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
fix(internet-identity): document available attribute keys and email vs verified_email
- list the unscoped attribute keys (name, email, verified_email) with
guidance on when to use each: email for soft uses (mailing lists,
contact), verified_email for access gating (admin allowlists)
- document scopedKeys() resolution including the literal Microsoft
provider URL (the {tid} segment is part of the URL, not a tenant
placeholder)
- add Mistake 10: substituting {tid} into the Microsoft URL silently
breaks attribute lookups
- add Mistake 11: treating email as verified — only verified_email
carries the source provider's verification signal
- new evals: Microsoft tid substitution, email-vs-verified_email for
access gating
Copy file name to clipboardExpand all lines: evaluations/internet-identity.json
+19Lines changed: 19 additions & 0 deletions
Original file line number
Diff line number
Diff line change
@@ -71,6 +71,25 @@
71
71
"Decodes msg_caller_info_data as a Candid-encoded ICRC-3 Value::Map and looks up the requested attribute key only after the signer check passes"
72
72
]
73
73
},
74
+
{
75
+
"name": "Adversarial: substituting tid in the Microsoft scoped-key URL",
76
+
"prompt": "I'm using scopedKeys({ openIdProvider: 'microsoft' }) on the frontend. My Azure tenant ID is 11111111-2222-3333-4444-555555555555. How do I update the {tid} placeholder in the URL my backend looks for?",
77
+
"expected_behaviors": [
78
+
"Tells the user NOT to substitute the tenant GUID into the URL",
79
+
"Explains that the {tid} part of https://login.microsoftonline.com/{tid}/v2.0 is a literal segment, not a placeholder, and that bundle keys arrive as openid:https://login.microsoftonline.com/{tid}/v2.0:<key> exactly",
80
+
"Tells the backend to look up the literal key (e.g. openid:https://login.microsoftonline.com/{tid}/v2.0:email) without modification"
81
+
]
82
+
},
83
+
{
84
+
"name": "Adversarial: using email instead of verified_email for access gating",
85
+
"prompt": "I have an admin allowlist of email addresses. I want to gate a sensitive update method on the caller's email being in that list. Show me how to request the email from II and check it on the backend.",
86
+
"expected_behaviors": [
87
+
"Requests verified_email (not just email) for access-gating use cases",
88
+
"Explains that email is whatever the user's II-linked account reports while verified_email is only present when the source OpenID provider (e.g. Google) marked the email as verified and II surfaced that signal — only verified_email is trustworthy for authorisation",
89
+
"On the backend, looks up implicit:nonce, implicit:origin, signer (against rdmx6-jaaaa-aaaaa-aaadq-cai), and the verified_email attribute key (or the openid:<provider>:verified_email scoped variant) before the allowlist check",
90
+
"Does NOT recommend reading the email field as a substitute for verified_email"
91
+
]
92
+
},
74
93
{
75
94
"name": "Adversarial: build target suggestion",
76
95
"prompt": "I'm getting 'Top-level await is not available in the configured target environment' when building my Vite frontend with II auth. How do I fix this?",
Copy file name to clipboardExpand all lines: skills/internet-identity/SKILL.md
+31Lines changed: 31 additions & 0 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -45,6 +45,10 @@ Internet Identity (II) is the Internet Computer's native authentication system.
45
45
46
46
9.**Reading attribute data without verifying the signer.**`msg_caller_info_data` (Rust) and `Prim.callerInfoData` (Motoko) return whatever bundle the caller provided. The IC verifies the signature, not the identity of the signer — any canister can produce a valid bundle. Check `msg_caller_info_signer` / `Prim.callerInfoSigner` against `rdmx6-jaaaa-aaaaa-aaadq-cai` (Internet Identity) before trusting any attribute, otherwise an attacker canister can forge attributes like `email = "admin@you.com"`.
47
47
48
+
10.**Substituting `{tid}` in the Microsoft scoped-key prefix.** The `microsoft` OpenID provider URL is the literal string `https://login.microsoftonline.com/{tid}/v2.0` — `{tid}` is part of the URL, not a tenant-ID placeholder you fill in. Bundle keys returned by `scopedKeys({ openIdProvider: 'microsoft' })` look like `openid:https://login.microsoftonline.com/{tid}/v2.0:email` exactly, and the backend must look up that literal key. Replacing `{tid}` with a tenant GUID will silently miss every attribute lookup.
49
+
50
+
11.**Treating `email` as verified.**`email` and `verified_email` are distinct keys. `email` is whatever the user's II-linked account reports; `verified_email` is only present when the source OpenID provider (e.g., Google) marked the email as verified, and II surfaces that signal through. Use `verified_email` for any access gating (admin allowlists, capability checks); use `email` only for soft uses like contact info or mailing lists. Request both for fallback behaviour: both are returned with the same value when the source provider marked the email as verified, only `email` when it didn't.
51
+
48
52
## Using II during local development
49
53
50
54
You have two choices for local development:
@@ -150,6 +154,33 @@ init();
150
154
151
155
When the backend needs more than the user's principal (e.g., a verified email), Internet Identity can return signed attributes alongside the delegation. The backend issues a nonce scoped to a specific action; the frontend requests the attributes during sign-in; the backend verifies the bundle when the user calls the protected method.
152
156
157
+
#### Available attribute keys
158
+
159
+
`requestAttributes({ keys })` accepts the following keys:
160
+
161
+
| Key | Meaning | When to use |
162
+
|---|---|---|
163
+
| `name` | The user's display name. | Personalisation in the UI. |
164
+
| `email` | The user's email as reported by their II linked account. | Mailing-list signups, contact email, anything where you don't gate access on the email. |
165
+
| `verified_email` | Same value as `email`, but only present when the source OpenID provider (e.g., Google) marked the email as verified, and II surfaces that signal. | Access gating (e.g. an admin allowlist by email). Treat this as the only trustworthy email for authorisation. |
166
+
167
+
Request both `email` and `verified_email` if you want fallback behaviour: when the source provider marked the email as verified, both keys are present with the same value; when it didn't, only `email` is returned.
168
+
169
+
`scopedKeys({ openIdProvider, keys? })` rewrites the keys above into provider-scoped keys of the form `openid:<provider-url>:<key>`, so II returns the values from the linked OpenID account directly (with implicit consent, no extra prompt). Provider URLs:
0 commit comments