Identity Attributes

Summary

We propose a design that allows sharing attributes associated with an Internet Identity (II) with the app a user is signing into, upon their agreement. This enables the development of II-powered apps that offer richer features with fewer distractions, such as sending email notifications without requiring most users to confirm their email addresses. Furthermore, II will evolve into a central control panel where users can specify their preferences for sharing identity attributes and with whom.

Implications for Developers

The underlying API closely resembles the one provided by the authClient. Developers who already integrate with id.ai can request attributes such as usernames and emails. The returned attributes will be certified by id.ai, enabling convenient and secure verification against the user’s principal.

Implications for End Users

There will be two distinct attribute-sharing flows:

  1. Regular Flow: This begins when the user taps the “Sign in with Internet Identity” button in the app. After a successful sign-in, id.ai will request explicit confirmation for each attribute requested by the app before sharing it.
  2. 1-Click Flow: This starts when the user taps, for example, “Sign in with Google (powered by id.ai)”. Upon successful sign-in, id.ai will automatically share basic attributes associated with the corresponding user account without requiring additional explicit confirmation. Note that in this case, implicit consent is a UX optimization, not a removal of user control.

Problem

As you may already know, id.ai now supports users signing in via OpenID using their existing Google, Apple, or Microsoft accounts. To safeguard user privacy, Internet Identity keeps all OpenID data confidential, never sharing it with the apps users interact with. However, when apps require additional user attributes, such as names, to deliver useful services, users often must re-enter the same information across multiple apps. Attributes like emails also necessitate confirmation, creating significant distractions from users’ primary objectives within the app.

Let’s examine why apps need these user attributes to begin with. When users are offline (or not signed into a specific app), they may still want email notifications for relevant events, such as an airdrop arriving in their wallet. Building custom email confirmation flows demands substantial extra effort from app developers. Meanwhile, users signing in with Google, for instance, have already verified a compatible email address through Internet Identity; requiring reconfirmation for the app introduces unnecessary redundancy. Ultimately, this friction hinders seamless onboarding.

Approach

To address this issue, we propose a solution that operates as follows:

  • Simple API: Internet Identity introduces a new API enabling apps to request OpenID attributes. This API mirrors the existing mechanism for II-powered apps to request certified principals for user identification. For instance, an app might request an attribute like openid:google:email.
  • User Consent: Internet Identity secures user consent for each requested attribute. For example: “The app requests your email address associated with Google; please confirm sharing.”
  • Certification: II delivers certified attributes to the app, allowing verification that these attributes belong to the user with a specific principal.
  • 1-Click Flow: From the user’s perspective, the 1-click flow initiates by tapping, e.g., “Sign in with Google (powered by id.ai),” which redirects to accounts.google.com (in principle, this could extend to any OpenID provider supported by id.ai, but initially, we prioritize Google as the most popular option). After signing in with the desired account, the user is seamlessly redirected back to the app. In this flow, id.ai can share basic identity attributes (such as email and name) without additional consent, given the clear user intent.

Regular Flow

Let’s explore how identity attributes work in the regular flow based on a concrete example. A user named Bob wants to sign into an app. The app’s business logic relies on the email and the name of the user.

When id.ai processes the ii_attributes request, it proceeds as follows:

  1. Bob taps the Sing in button in the app, which requests email and name attributes from id.ai.
  2. id.ai directs Bob through the regular sign in flow.
  3. Once Bob is signed into id.ai, it informs Bob about the requested attributes, providing previously used values, when available. For each attribute, Bob can either consent to sharing a previously used value, modify the value to be shared, or deny sharing it with the app at this time.
  4. Bob consents to share the previous email, but modifies the value of the name attribute to be shared.
  5. [not shown on the diagram] II needs to verify the new name, e.g., by comparing it against the user’s OpenID credentials linked to this account. If automatic verification is not possible, II falls back to explicit verification (e.g., “please verify that you have this email”).
  6. II forwards the allowed attributes to the app.
  7. The app greets Bob by his preferred name and is also able to send emails to Bob’s (verified) email address.

This way, II serves as the control panel for users to specify their intent about how their identity attributes are shared, and with whom.

1-Click Flow

A cornerstone of the design discussed above is that Internet Identity (II) always requires user consent before sharing identity attributes. Typically, this consent is obtained by explicitly prompting the user, as illustrated in the sequence diagram above.

However, in the special case of the 1-click flow, an opportunity arises to further enhance the user experience, as illustrated in the following scenario:

  1. A user is onboarding an II-powered app for the first time and selects "Sign in with Google (powered by id.ai).”
  2. On the accounts.google.com sign in screen, the user chooses a Google account.
  3. Google requests consent to share the email associated with that account with id.ai.
  4. id.ai can securely forward that email to the app, without additional explicit consent from the user, since they initiated the 1-click flow with Google, indicating their intent to link one of their Google accounts to the app.

Let’s explore how identity attributes work in the 1-click flow based on a concrete example. Once again, Bob wants to sign into an app that relies on the email and the name of the user. But this time the app provides a dedicated "Sign in with Google (powered by id.ai)” button.

  1. Bob taps the Sign in with Google button in the app, which requests email and name attributes (associated with Bob’s Google account) from id.ai.
  2. id.ai directs Bob through the Google sign in flow.
  3. Upon successful authentication on accounts.google.com, II forwards the requested attributes to the app.

Attribute scopes

Identity attributes that an app can request should maintain consistent values regardless of the user’s chosen sign-in method. For instance, we aim to prevent scenarios where a different user email is selected based on whether they sign in via Google, Microsoft, or passkey. To eliminate ambiguity, attributes may include scopes that specify two elements:

  • The attribute’s source (and its semantics; e.g., a Google email differs from a Microsoft email).
  • The type of consent the user provides before II can share the attribute.

For now, the only two attributes requestable in the 1-click flow with implicit consent are:

  • openid:https://accounts.google.com:email
  • openid:https://accounts.google.com:name

Both attributes share the scope openid:https://accounts.google.com, signifying that they pertain specifically to the email address and name associated with the user’s Google account.

Note that for the time being, all other attributes require explicit consent, and scopes from other OpenID issuers generally available in II (Microsoft, Apple) are not covered yet. However, adding other issuers in the future is conceptually simple, at which point one could imagine a streightforward extension of this design in which implicit consent applies if the scope of the requested attributes matches openid:{issuer} for the same issuer that is used in the 1-click flow.

Discussion

Currently, users of II-powered apps must provide similar data across each ICP app they use, often involving redundant actions like email verification. Above, we outlined a vision for how id.ai could implement identity attribute sharing in a privacy-preserving manner, subject to user consent. We welcome community feedback on this design proposal.

As a first step towards implementing this design, we have proposed this feature (proposal/140313) as a pilot for caffeine.ai to gain experience and refine the API, before incorporating feedback and making it available to all II-powered apps. Please let us know if you are developing an app that would like to be an early adopter of identity attributes or the 1-click flow.

Hi @aterga and team,

Love this proposal — certified attributes via 1-click Google/Apple sign-in will make ICP apps feel just like normal Web2 logins, but decentralized and private.

No more annoying “verify your email” steps — users jump right in with their real, verified email (or name) automatically shared. This gives amazing user flow for everyday people, letting us compete directly with big wallets like Coinbase on simplicity while being more trustless and on-chain.

For my B3Pay project (a fully decentralized PayPal alternative), this would be perfect: verified emails for quick payments, notifications, or links — all without custom friction.

One big suggestion: any plans for multi-attribute requests (batching email + name + future ones like phone)? Phone number validation tied to II would be a massive win — it could unlock even smoother mobile-first flows and 2FA-like security without central services.

I’d love early access once the pilot is ready — happy to test, share feedback, and build example integrations to show the power for payment/wallet apps.

Thanks — this could change everything!

Hi @b3hr4d,

Thanks for your feedback:

Yes, the high-level app developer API will look roughly like this:

let { delegationChain, certifiedAttributes } = await authenticate({
    direct_openid_auth: "https://accounts.google.com",
    attributes: [
        "openid:https://accounts.google.com:email",
        "openid:https://accounts.google.com:name"
    ],
});

// This should happen on the backend,
// since the (browser-based) app frontend may not be trusted.
let { principal, attributes } = verify(delegationChain, certifiedAttributes, issuer);

let { email, name } = (attributes.get("email"), attributes.get("name"));

In this pseudocode snippet, we can see a few things:

  • The app can request any set of attributes in one go. But, as mentioned here, the implicit consent optimization is strictly limited (at least for now) to email and name; future extensions to this list would are subject to community discussion.
  • The response contains a subset of attributes from the request. Even in the optimized 1-click flow, there is no guarantee that the OpenID credentials of a particular user contain the requested data, although we expect that this would work for most users.
  • Each attribute in the response can be independently verified against the delegation chain / user principal. This ensures flexibility for developers who can, e.g., store and verify user emails in the app backend while displaying the names only in the app frontend (without having to store them in the backend).

I agree that this would be interesting. We didn’t consider phone numbers in the first iteration of the Identity Attributes design because they are not provided by Google’s OIDC API, which is the most popular source of identity attributes right now. But we’ll definitely revisit this once we look closer into adding identity attribute verification to II.

Hi @aterga,

Thanks for this announcement. This sounds like very useful functionality. I’m curious about use cases that involve attributes that have been certified by one dapp, and which another dapp would like to make use of (without the user having the ability to spoof that attribute).

For example, a service like decide.ai may verify a user as a unique human and assign a distinct certificate as an attribute. Downstream services could then simply request the certificate from II as an attribute to establish unique personhood.

Other examples might include services that have some means of verifying a user’s age, and that they’re over 18 for example. As user should not be able to modify this attribute before it is received by a downstream service (or it would defy the verifiability).

More IC-specific use cases could include a dapp that deals with cycles management, and assigning users attributes that verify they have topped up a specific canister a certain amount over a certain timeframe. Any number of downstream dapps could then look for an II attribute that confirms this user has contributed a minimum amount to the running of the service they are about to log into (without all of those services having to implement that functionality themself). This could help address reverse-gas-fee criticisms.

So essentially two questions:

  • Will dapps be able to set custom attributes for downstream dapps to retrieve?
  • Will it be feasible to prevent users from intercepting those attributes and changing their values to deceive downstream dapps?

Hi @Lorimer,

Thanks for reviewing this design and asking these questions.

On the one hand, the design described in this thread currently focuses on attributes that an II already has, so the added service provided to app developers is read-only. This is an important because II needs to be very scalable, so it cannot simply provide unbounded storage for app to create arbitrary attributes for their users. Currently, this isn’t an issue, as attributes are based on data that’s anyway persisted in II (e.g., the so-called JWT tokens supplied by OpenID issuers typically contain emails and user names).

On the other hand, the design is trying to be agnostic to the source of attributes data which enables some of the use cases you bring up. For example, one could imagine a “verify your age” button on https://id.ai that would trigger an AI verification service (implemented as an II plugin service), setting, e.g., is_over_18_years_old and is_over_21_years_old — attributes that could then be requested in the sign-in flow by any II-powered app. Similarly, I would love to see a decide.ai II plugin that would in a similar, simple way.

To summarize, we do have ideas for a follow-up feature that could enable other interesting use cases, but it’s a bit too early to say how exactly that should work. In particular, the idea described in the paragraph above is just one possible design.

Once I’ve finished what I’m currently working on I’ll be moving onto something that would benefit from easy access to a username instead of just the user principal. I’d be happy to try this out and offer feedback (may not be working on this for a month or so though).

Hi @aterga,

I wanted to share a concrete use case from Rabbithole.app.

Rabbithole is a sovereign encrypted file vault on the IC. One of the places where Identity Attributes are useful for us is shared access by verified email.

The flow is simple: a user can share access to a vault, folder, or file with an email address. When the recipient signs in, the app needs a way to resolve that verified email to the user’s principal without forcing every app to build its own email verification flow.

For this use case, certified Identity Attributes are very helpful because the email is not just a value typed into the app frontend. It can be verified against the delegation / principal, and the user still keeps explicit control over what is shared.

For Rabbithole, this is not mainly about notifications or marketing emails. It is part of the access model and onboarding UX for shared private data.

I would be happy to test the API and share feedback from a real app integration.

Some context about the app:

Interesting proposal. I’m building a regulated conveyancing platform on ICP (PropXchain) and this is directly relevant to our architecture.

One of the harder problems we’ve had to solve is the identity verification gap. We use Internet Identity for authentication, but II’s pseudonymity-by-design means we get a principal with no verified real-world attributes attached. For a regulated service, we then have to bolt on a separate KYC/AML flow via third-party IDSPs (Yoti, OneID) that operates entirely outside the II ecosystem.

The idea of II evolving into a central control panel where users can specify which attributes to share — and having those attributes be certified — would close that gap neatly. For conveyancing specifically, being able to request verified attributes like name and address (for the AML check) and have them certified by the II anchor would replace one of the clunkiest parts of the current onboarding flow.

The API resembling authClient is a good design choice — minimal migration cost for existing II-integrated apps. Would be interested to see how the certification chain works in practice, particularly around attribute freshness (address changes, etc.).

Happy to test the API against a real regulated workflow when it’s available.

Great to hear about more potential real-world use cases (Rabbithole, PropXchain, etc.) for Identity Attributes!

We’re happy to announce that the feature is now live. This means II-powered apps can now onboard users more seamlessly and provide services based on user names and verified user emails. Here is a high-level (agent-friendly) summary that describes what is needed from your frontend and backend.

In the meantime, I invite @Lorimer, @rabbithole, @Madhatt4, and others to try this out and get back to us with your questions and feedback.

In particular, I think the feature should work for Rabbithole out of the box.

For projects like PropXchain, note that Identity Attributes do not currently provide attributes freshness info. Practically, user names are not verified by the OpenID providers we rely on, so it’s whatever the user types in. (Fortunately, II does guarantee that verified emails were associated with the user in the near past.)

Hi @aterga, this sounds exciting. Is it possible for an email address to be associated with an II without it being a recovery mechanism? e.g. If I want a verified email address associated with my II, but I don’t want access to that email address (if it becomes compromised) to act as a backdoor into my II

Is it possible for an email address to be associated with an II without it being a recovery mechanism?

Yes. In fact, our idea is that recovery emails should never be used by II for any purpose that isn’t recovery. And they are not sharable right now.

To try out attribute sharing flows, feel free to use our powerful test-app; the screenshot below shows which settings to pick for requesting the user’s verified email and name.

After you sign in with II, your should see the attribute sharing confirmation dialogue, e.g.:

As of today, the only source of verified emails is an OpenID connection with Google and Microsoft. (Apple OpenID is a bit special, but we might find a solution for that in the coming weeks; although the number of users who authenticate into II via their Apple ID is quite small).

Later this week, we’re planning to propose a feature to allow users registering non-recovery emails with II that would appear in this confirmation screen, catering to passkey-only users and power users who may want to provide a separate email to apps for privacy reasons.

Here’s a preview of the upcoming UI extension for associating emails (this is not in production yet):

Sounds great! This will be very useful, thank you

Thanks @aterga, I tried the flow in Rabbithole and can confirm that user attributes are received by the app.

I also tested Apple sign-in. As mentioned above, it does not currently provide the verified email attribute in the same way, so I will treat that as future II coverage rather than something to rely on today.

The part about non-recovery emails is especially relevant for Rabbithole. If users can associate a verified, non-recovery email with their Internet Identity and share it as a certified attribute, that could become the preferred path for shared access by email.

For Rabbithole, the important claim is simple: this principal has proven control of this email address. If II can provide that claim as a certified attribute, the app does not need to duplicate email verification for those users.

I may still need an app-level fallback for arbitrary email addresses or users who have not configured this in II, but I would rather rely on II-certified attributes where possible.

One detail about name: Rabbithole does not automatically set the II-provided name into the user profile. That is intentional.

Sharing search is currently based on explicit profiles or exact full email/principalId matches. When a user creates a profile, they also agree to appear in search results.

So in practice, the most useful attribute for Rabbithole right now is verified email. I would be interested in feedback on whether `name` should be used differently, but for now I prefer to keep profile discovery explicit.

:100:

Good point.

If you could provide metrics for which email providers are the most popular ones among your users, we could use that to prioritize enabling more of them in II.

That makes sense.

I do not have meaningful Rabbithole-specific metrics yet. The app was made public only a couple of days ago, so there is not enough real user data to draw conclusions from.

So far, nobody from the forum has requested access to the test vault I created, and I do not yet have enough users creating their own vaults to provide useful provider distribution numbers.

The only practical signal I can share right now is from my own testing and early setup: almost all successful OpenID attribute flows I see are Google.

Once Rabbithole has enough real usage, I can share more useful numbers.

Thanks @aterga — great to see this go live.

I’ve been thinking about how this fits into PropXchain’s regulated workflow. The verified email and name attributes via OpenID providers are a solid step — they solve the “is this principal tied to a real email” problem cleanly, and we can stop building our own email verification flow.

For a regulated conveyancing platform though, the gap is wider. UK AML rules require identity verification from a reliable, independent source on a risk-based basis — and in practice that means government-ID plus liveness via a DIATF-certified IDSP (Yoti, OneID). That’s data those providers hold, not something Google or Apple can attest to via OpenID.

The interesting question for us is whether II could eventually carry richer certified attributes that a regulated app could rely on without re-running the check every time. Concretely: could II carry a third-party-issued certified attribute — kyc_passed: {provider, date, level} — where the issuer is an accredited IDSP rather than the OpenID provider, with a freshness/expiry field a relying app can enforce? That’s the primitive a regulated app needs. Lorimer touched on the cross-dapp attribute idea earlier in the thread — for us it’s not just convenience, it’s a compliance requirement.

In the meantime, we’ll integrate the email/name attributes as part of our onboarding flow and report back. The non-recovery email separation that came up later in the thread is important for us too — conveyancing involves sensitive data, so the last thing we want is a recovery email doubling as an identity attribute.

Will feedback once we’ve tested with real flows.