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.

7 Likes

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!

3 Likes

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.

3 Likes

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?
1 Like

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.

3 Likes

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).

1 Like