Skip to content
Version v3.2.0

Unified invitations ​

Unified invitations let an administrator invite a person to one application while offering one or more eligible identity-provider routes, including local UserStore and federated providers. One route completes the invitation; the other routes become unusable.

Why unified invitations are needed ​

A legacy invitation marker is not enough for enterprise onboarding. Administrators need to know who was invited, for which tenant and application, which IDPs were permitted, whether the address or login name could change, which approvals and assignments were required, and whether the invitation expired, was cancelled, or was replaced.

The unified invitation is a central lifecycle record for those decisions. It prevents the same invitation from creating multiple identities, prevents email similarity from silently linking accounts, and keeps application or group assignments pending until enrollment is complete.

Choose an invitation design ​

RequirementRecommended choice
The address in the invitation is authoritativeSet AllowEmailChange to false. The user cannot redirect the invitation to another mailbox.
The user may have received the invitation at an alias or temporary addressSet AllowEmailChange to true. ProAuth requires proof of both the invited address and the replacement address.
The administrator assigns workforce login namesSupply LoginName and keep AllowLoginNameChange set to false.
The user chooses a local login nameSupply an initial reserved value and set AllowLoginNameChange to true. The replacement is reserved before it is accepted.
Either a corporate IDP or UserStore account is acceptableInclude both IDP types in EligibleIdpInstanceIds. The first successfully completed route wins atomically.
The invitation targets an existing ProAuth subjectSet IntendedProAuthUserId. ProAuth does not infer this relationship from an email address.
Regulated onboardingSet RequiredApprovals to the required independent approval count and include the approved change reference in the surrounding administrative process.

No email-based account linking

An email address can prove control of a mailbox. It does not prove that two provider identities belong to the same ProAuth subject. Use an explicitly targeted invitation or the identity replacement workflow instead of automatic email linking.

Lifecycle ​

The aggregate also records each route as Eligible, Selected, BootstrapInProgress, AwaitingApproval, Completed, Failed, Cancelled, or Superseded.

The following rules apply throughout the lifecycle:

  • the invitation secret and route bootstrap secret have 256 bits of entropy and are stored only as hashes;
  • expiry and state are checked again at every transition;
  • route selection and completion use concurrency-protected transitions;
  • only one route can win;
  • a GET request does not consume or advance the invitation;
  • reminders rotate the invitation secret, which invalidates an older link;
  • cancellation and supersession release active reservations and invalidate secrets;
  • ordinary application tokens are issued only after enrollment, approvals, and assignments complete.

Create an invitation ​

Use Management API v2:

http
POST /api/management/v2/unified-invitations
Content-Type: application/json
json
{
  "subscriptionId": "<subscription-id>",
  "tenantId": "<tenant-id>",
  "clientAppId": "<target-client-id>",
  "emailAddress": "alex@example.com",
  "allowEmailChange": false,
  "loginName": "alex@example.com",
  "allowLoginNameChange": false,
  "eligibleIdpInstanceIds": ["<userstore-idp-id>", "<federated-idp-id>"],
  "lifetimeHours": 168,
  "policyFingerprint": "<approved-policy-fingerprint>",
  "requiredApprovals": 0,
  "authorizedClientAppIds": ["<additional-client-id>"],
  "groupIds": ["<group-id>"]
}

Command fields ​

FieldRequiredValid values and effect
SubscriptionIdYesSubscription that owns the intended ProAuth user.
TenantIdYesTenant in which redemption and assignments occur.
ClientAppIdYesApplication for which the invitation was issued.
IntendedProAuthUserIdNoExplicit existing subject. If omitted, ProAuth stages a new inactive subject.
EmailAddressYesValid invited email address.
AllowEmailChangeNofalse by default. When true, replacement requires dual proof.
LoginNameNoInitial local login name. If omitted, UserStore bootstrap uses the email address.
AllowLoginNameChangeNofalse by default. When true, a new canonical login name must be reserved.
EligibleIdpInstanceIdsYesOne or more eligible UserStore or federated IDP instances. The snapshot is immutable.
LifetimeHoursNo1–2160; default 168 (7 days).
PolicyFingerprintYesRecords the policy decision under which the invitation was issued.
RequiredApprovalsNo0–5; default 0. The requester cannot satisfy an independent approval requirement alone.
AuthorizedClientAppIdsNoClient assignments applied only during successful finalization.
GroupIdsNoGroup memberships applied only during successful finalization.

LifetimeHours, identifier mutability, approvals, routes, and assignments are properties of an invitation. They are not UserStore IDP options.

UserStore bootstrap ​

When the user selects a UserStore route, ProAuth creates a provisional local user that cannot authenticate normally. The route then guides the user through the permitted credential enrollment:

  • set an initial password when password creation is allowed;
  • register a login passkey when passkeys are enabled;
  • satisfy the effective recovery-readiness requirements;
  • accept the immutable identifiers or complete an allowed identifier change.

Password and passkey policy are evaluated by the same server services used during normal credential management. Completing credential enrollment does not by itself activate the account. Central approval and assignment orchestration must still succeed.

Mutable identifiers ​

Changing the email address ​

When AllowEmailChange is true, ProAuth starts a 30-minute identifier-change attempt and sends separate proof codes to:

  1. the original invited address; and
  2. the proposed replacement address.

Both codes must be valid for the same invitation, route, attempt, and security state. Five failed proof attempts terminate the change attempt and release the pending reservation. A successful change transfers the reservation and updates the provisional UserStore user.

This dual proof prevents a forwarded or stolen invitation from being redirected to an attacker-controlled mailbox without the original recipient's participation.

Changing the login name ​

When AllowLoginNameChange is true, ProAuth canonicalizes and reserves the proposed login name before accepting it. A duplicate or quarantined canonical value fails closed. No database collation or case-sensitive race decides the winner.

Reminders, cancellation, and reissue ​

OperationEndpointBehavior
ReadGET /api/management/v2/unified-invitations/{id}Returns lifecycle, route, approval, assignment, reminder, and supersession state.
RemindPOST /api/management/v2/unified-invitations/{id}/remindAllowed at most twice, at least 24 hours apart. Rotates the invitation secret and queues durable delivery.
CancelPOST /api/management/v2/unified-invitations/{id}/cancelRequires a reason. Invalidates secrets, releases reservations, and cancels pending routes and assignments.
ReissuePOST /api/management/v2/unified-invitations/{id}/reissueCreates a replacement for 1–2160 hours and supersedes the source. Fails once route bootstrap has started.
ApprovePOST /api/management/v2/unified-invitations/{id}/approvalsRequires ProAuthUser.ApproveInvitation; records an independent actor.

Delivery is durable. The invitation link and recipient are stored inside a protected outbox payload, and the built-in job scheduler checks for pending delivery every minute. Delivery uses leases and retries. The same maintenance cycle processes expired history, invitation expiry and ready invitations; a failure in one operation does not prevent the others from running. Management read APIs never return the bearer secret.

Deleting the intended ProAuth user, an eligible identity provider (including a UserStore), target client application, tenant, subscription or customer also retires the affected unified invitations. You do not need to cancel each invitation first. Existing deletion prerequisites still apply: remove dependent resources (such as users, providers, clients and tenants) before deleting their parent subscription or customer. Retained invitation history does not add another prerequisite.

  • Active invitations become Cancelled. Invitations already redeemed, cancelled, expired, superseded or failed keep their final outcome.
  • Invitation links and bootstrap proofs stop working. Pending deliveries, identifier reservations, approvals, routes and assignment instructions are removed. An archived invitation cannot be reminded, approved, cancelled again or reissued.
  • A minimal history record remains: invitation ID, subscription/tenant/client scope IDs, lifecycle timestamps, final outcome, archive time, retention deadline and a fixed deletion reason. Email addresses, login names, intended-user references, provider identities, actor identifiers, policy fingerprints and secret/proof material are removed from the invitation record.

The v2 read endpoint returns this redacted record while its retention period is valid. ArchivedOn identifies history; HistoryExpiresOn is its deadline, and CancellationReason identifies the deleted resource type. Scope IDs can refer to deleted resources and do not keep those resources alive. Access still requires authorization. After the deadline, reads return not found; the background worker physically removes expired history in batches.

This cleanup concerns invitation data. It does not erase previously delivered email, separately retained audit logs, backups or independently managed provider accounts. In particular, an unfinished provisional UserStore account is a separate account record; review it using the store's account-management procedures. Removing an invitation does not activate it.

Administrator procedure ​

  1. Confirm the target and whether any invitation journey is currently being completed. Deleting a shared provider or a parent scope affects every invitation that depends on it, including invitations offering other eligible providers.
  2. Delete the resource using its management API or an available AdminApp deletion action. The ProAuth Users view currently exposes editing and deactivation; use the management API to delete a central ProAuth user. Successful deletion archives affected invitations in the same transaction.
  3. If the service returns 409 Conflict because delivery, provisioning or activation is in progress, allow that operation to finish and refresh before retrying. Investigate a repeatedly stuck operation; cancelling an invitation is not a way to bypass in-flight work.
  4. For a new onboarding attempt after deletion, create a fresh invitation for valid resources. History cannot restore a deleted user, assignments or secret.

We recommend keeping a short history window that covers your support and incident-review needs, while managing audit-log and backup retention separately. Cancelling an invitation without deleting a related resource continues to use the ordinary cancellation workflow; it does not start this deletion-history retention period.

Configure history retention ​

The default is 90 days from archival. Configure ProAuthRoot:InvitationHistoryRetentionDays to a whole number from 1 to 3650. Invalid values prevent application startup. Use the same value on every serving instance. The deadline is recorded when deletion occurs; changing the setting does not shorten or extend records already archived.

For containers, set:

text
ProAuthRoot__InvitationHistoryRetentionDays=30

For Helm deployments:

yaml
appsettings:
  proauthroot:
    invitationhistoryretentiondays: 30

An unset Helm value uses the application default. History is unavailable through the API as soon as its deadline passes, although physical removal can take longer if the worker is stopped or a purge backlog exists.

Assignment orchestration ​

Authorized-client and group assignments are validated when the invitation is created and remain Pending until the winning route is ready. Finalization applies each assignment idempotently. An assignment failure keeps the invitation from becoming Redeemed and records a privacy-safe failure code for operations.

This ordering avoids granting access to a provisional or partially enrolled identity.

Mixed federated and UserStore invitations ​

It is safe to offer both route types because the central invitation, not the provider, chooses the subject and consumes the winning route. A federated callback must match its selected IDP, issuer, subject, route secret, invitation, and intended user. A UserStore completion must match its provisional user and route.

If an intended subject already has a different active identity, the invitation does not silently attach another identity. Use the governed identity replacement workflow.

Operations and troubleshooting ​

Monitor these conditions:

  • invitations approaching expiry;
  • repeated identifier-proof failures;
  • reminder delivery failures or dead letters;
  • assignment failures;
  • invitations waiting for approval;
  • route conflicts and replay rejections;
  • provisional UserStore users that never complete bootstrap.

For legacy marker migration, see UserStore migration and activation.