Typed Identifiers
ProAuth 3.x introduces typed identifiers for the v2 Management API and User Store API .NET clients. Typed identifiers are small value types such as ClientAppId, SubscriptionId, TenantId, UserId, and GroupId that wrap the underlying GUID for a specific domain concept.
The HTTP contract remains GUID-based. JSON payloads, path parameters, query parameters, and OpenAPI schemas still use string values with format: uuid. The typed identifier names are exposed as OpenAPI metadata through the x-reafx-typed-id extension so ProAuth's generated .NET clients can preserve the stronger type information.
Why It Matters
Typed identifiers reduce accidental cross-use of IDs in .NET integrations. For example, a method that expects a ClientAppId communicates that a tenant, subscription, user, or group ID is not valid for that argument, even though all of those values are GUIDs on the wire.
This is especially useful in ProAuth's multi-tenant API surface, where many resources have parent-child relationships and several endpoints include more than one identifier.
Wire Format
API requests and responses continue to use plain UUID strings:
GET /api/management/v2/clientapp/2bf42f1d-24d7-4ce3-b9df-7d27dfb45de0{
"id": "2bf42f1d-24d7-4ce3-b9df-7d27dfb45de0",
"subscriptionId": "84be971e-6cd7-49e9-90d7-02f9216af6ac",
"name": "my-app"
}Third-party clients, scripts, CLI imports, and hand-written HTTP calls should keep sending and reading UUID strings. No JSON shape change is required when migrating from GUID-based v2 prerelease clients or from direct HTTP integrations.
.NET Client Usage
The generated v2 .NET clients use typed IDs in DTO properties and method parameters:
using ProAuth.Clients.Management.V2;
using ProAuth.ManagementServices.Model.Dtos.V2;
using ProAuth.TypedIds;
SubscriptionId subscriptionId = Guid.Parse("84be971e-6cd7-49e9-90d7-02f9216af6ac");
var command = new CreateClientAppCommand
{
Name = "my-app",
SubscriptionId = subscriptionId,
Enabled = true
};
var created = await managementClient.CreateClientAppAsync(command, cancellationToken);
ClientAppId clientAppId = created.Result.Id;User Store client calls follow the same pattern:
using ProAuth.Clients.UserStore.V2;
using ProAuth.TypedIds;
IdpInstanceId userStoreId = Guid.Parse("f116e7df-fb4b-4980-a21a-f45a33f76993");
UserId userId = Guid.Parse("34d6af04-278c-47f1-8d9e-41ca3dfb0be4");
var user = await userStoreClient.GetUserAsync(userStoreId, userId, cancellationToken);Typed IDs have implicit conversion from Guid, serialize as UUID strings, and deserialize from UUID strings. Use the typed value throughout client code once the ID's resource type is known.
OpenAPI Metadata
Typed IDs appear in the OpenAPI schema as UUID strings with an additional vendor extension:
{
"type": "string",
"format": "uuid",
"x-reafx-typed-id": {
"name": "ClientAppId",
"namespace": "ProAuth.TypedIds",
"underlyingType": "Guid"
}
}OpenAPI generators that do not understand x-reafx-typed-id can safely ignore it and generate string or Guid properties. The extension is additive metadata for generators that want stronger domain-specific ID types.
Migration Notes
When moving .NET code to the v2 client packages:
- Replace generic
Guidvariables in API-facing method signatures with the matching typed ID where possible. - Convert boundary values once, close to the input boundary, for example
ClientAppId clientAppId = Guid.Parse(value). - Keep persisted configuration, YAML imports, scripts, and HTTP examples as UUID strings.
- When generating custom clients from OpenAPI, either preserve
x-reafx-typed-idor treat the schema as a normal UUID string.
The typed identifier feature is a .NET client and server implementation improvement. It does not introduce a new external identifier format.