Skip to content

Identity and attributes

An identity is one user inside one tenant. Whatever your product calls them — customer, member, account, user — that's the identity layer.

This page walks the shape of an identity and where each part comes from.

Every identity has:

  • sub — the identity's id, a string like usr_01HZX.... Stable forever; never reuse this across identities.
  • email — primary email. May or may not be verified (see email_verified).
  • email_verified — boolean. True if the user clicked the verification link.
  • created_at — when the identity was first created in this tenant.
  • updated_at — last profile change.

These come back on the user object when you call useIntelliAuth().user or the OIDC /userinfo endpoint.

Standard OIDC claims — what comes back when you ask

Section titled “Standard OIDC claims — what comes back when you ask”

If your application requests the profile scope at sign-in, the identity object also carries:

  • name — display name.
  • given_name / family_name — split parts if available.
  • picture — URL to a profile picture (when set).
  • locale — BCP-47 locale string, e.g. en-US, fr-CA.

If your application requests email, you additionally get email + email_verified (mentioned above).

The full list is per the OIDC specification's standard claims. Your tenant may surface additional standard claims depending on configuration (phone number, address, gender, etc. — though these are rare).

Custom attributes — what your tenant defines

Section titled “Custom attributes — what your tenant defines”

Beyond the OIDC standard claims, your tenant can define custom attributes specific to your product. Examples:

  • subscription_tier: "pro" — the user's plan.
  • business_unit_id: "banking-prod" — which of your internal business units / sub-products they belong to (useful when one tenant serves multiple products with shared identities, rare).
  • feature_flags: ["beta-search", "early-mfa"] — per-user flags.

Custom attributes live on the identity object (alongside email, name, etc.) and flow through to the ID token + access token claims when configured to do so by the tenant admin.

How to set them:

  • At sign-up. The registration flow can collect custom attributes via custom form fields.
  • From your backend. The Node SDK's management client exposes mgmt.users.update(id, { custom_attributes: { ... } }).
  • Via SCIM. If your tenant has SCIM enabled, your identity provider syncs them automatically.

Reading them on the client:

const { user } = useIntelliAuth()
const tier = user?.custom_attributes?.subscription_tier

Reading them on the backend:

// After requireSession middleware:
const tier = req.user.custom_attributes?.subscription_tier

Federated identities — same user, multiple sources

Section titled “Federated identities — same user, multiple sources”

If your tenant has social login or SAML federation enabled, a single identity can have multiple federation links — Google, GitHub, Okta, etc. The identity has one sub (the IntelliAuth-issued id), but the federation links record which external accounts have been associated.

From your code's perspective, this is mostly transparent — useIntelliAuth().user returns the same identity regardless of which federation route they used to sign in. The connection claim names the route (google-oauth2, okta-saml, email-password, etc.) if you need it.

The identity model is "one identity per email per tenant" — if a user signs in with Google using alice@example.com and later signs in with GitHub using the same email, the tenant's link-by-email policy determines whether they become the same identity or two separate ones.

Three things often confused with identities:

  • Identity is not the same as session. Sessions are temporary; identities are durable. One identity can have many sessions (one per device, say). See Sessions and tokens.
  • Identity is not the same as account-in-your-app. Your application probably has its own database row representing the user (orders, preferences, etc.) keyed by sub. The identity is IntelliAuth's view; your row is yours.
  • Identity is not the same as MFA enrolment. A user can have MFA enrolled or not; that's per-identity state, but the identity exists independently of MFA configuration. MFA enrolments are listed under useIntelliAuth().listMfaEnrollments().