Skip to content

Latest commit

 

History

History
349 lines (259 loc) · 16.6 KB

V9_MIGRATION_GUIDE.md

File metadata and controls

349 lines (259 loc) · 16.6 KB

Auth0 .NET SDK v8 to v9 Migration Guide

Please review this guide thoroughly to understand the changes required to migrate Auth0.ManagementApi from v8 to v9.

Table of Contents

Overview

The Auth0 .NET SDK v9 builds on the v8 foundation (OpenAPI-generated via Fern, System.Text.Json, ManagementClient with automatic token management). The client initialization, request/response type naming, pagination model (Pager<T>), and sub-client organization introduced in v8 are unchanged in v9.

v9 focuses on:

  • Uniform raw-response access across every operation, including endpoints that return no body
  • Richer exception information: structured API errors, rate limit, and quota details parsed from response headers
  • New Management API surface: Organization Roles members, Token Vault privileged access grants, and Connection lifecycle event streams
  • More precise types: per-attribute Connection identifier types replacing a single shared type
  • Surface removals: the Federated Connections Tokens client and related types have been removed, along with the asn client session transfer device binding value

Scope: This guide covers Auth0.ManagementApi only. If you are still on v7, migrate to v8 first using the v7 to v8 Migration Guide.

Breaking Changes

NuGet Package

The package name is unchanged; only the version changes.

v8:

<PackageReference Include="Auth0.ManagementApi" Version="8.x.x" />

v9:

<PackageReference Include="Auth0.ManagementApi" Version="9.x.x" />

Void-Returning Methods Now Return WithRawResponseTask

In v8, operations with no response body (deletes, unblocks, and other side-effecting calls) returned a plain Task. In v9 these return the new non-generic WithRawResponseTask, mirroring how body-returning methods return WithRawResponseTask<T>. This gives every operation access to raw HTTP response metadata (status code, URL, headers) via .WithRawResponse().

This change affects approximately 97 methods across the client interfaces (DeleteAsync, UnblockIpAsync, CheckIpAsync, SetAsync, UpdateUniversalLoginAsync, and similar void operations).

v8:

Task DeleteAsync(
    string id,
    RequestOptions? options = null,
    CancellationToken cancellationToken = default);

v9:

WithRawResponseTask DeleteAsync(
    string id,
    RequestOptions? options = null,
    CancellationToken cancellationToken = default);

What you need to do — usually nothing. WithRawResponseTask is awaitable and completes with no value (void semantics), and it defines an implicit conversion to Task. Existing await call sites continue to compile and behave identically:

// Works in both v8 and v9
await client.Users.DeleteAsync("user_id");

You only need to change code that relied on the return type being exactly Task:

// v8 — storing the result as Task
Task deletion = client.Users.DeleteAsync("user_id");
await deletion;

// v9 — either await directly, or convert explicitly
await client.Users.DeleteAsync("user_id");

// or, if you must hold a Task reference:
Task deletion = client.Users.DeleteAsync("user_id"); // implicit conversion applies
await deletion;

New capability — you can now read response metadata from these operations:

var raw = await client.Users.DeleteAsync("user_id").WithRawResponse();
Console.WriteLine($"Status: {raw.StatusCode}");
if (raw.Headers.TryGetValue("X-Request-Id", out var requestId))
{
    Console.WriteLine($"Request ID: {requestId}");
}

Note: Method groups passed where a Task-returning delegate is expected (e.g. Func<..., Task>) may need an explicit lambda wrapper, since the method now returns WithRawResponseTask rather than Task.

Connection Attribute Identifier Types

The single shared ConnectionAttributeIdentifier type has been split into three per-attribute types. The Identifier property on each Connection attribute now uses its own type instead of the shared one.

Attribute type v8 Identifier type v9 Identifier type
EmailAttribute ConnectionAttributeIdentifier EmailAttributeIdentifier
PhoneAttribute ConnectionAttributeIdentifier PhoneAttributeIdentifier
UsernameAttribute ConnectionAttributeIdentifier UsernameAttributeIdentifier

Each new type carries an Active flag and an attribute-specific DefaultMethod enum (for example, EmailAttributeIdentifier.DefaultMethod is a DefaultMethodEmailIdentifierEnum?).

v8:

var email = new EmailAttribute
{
    Identifier = new ConnectionAttributeIdentifier { Active = true }
};

v9:

var email = new EmailAttribute
{
    Identifier = new EmailAttributeIdentifier
    {
        Active = true,
        DefaultMethod = DefaultMethodEmailIdentifierEnum.Email
    }
};

What you need to do: Replace references to ConnectionAttributeIdentifier with the type matching the attribute you are configuring. Any code that constructed or read ConnectionAttributeIdentifier directly will fail to compile and must be updated.

Federated Connections Tokens Removed

The Federated Connections Tokens surface has been removed in v9. This affects the Users.FederatedConnectionsTokensets sub-client, its associated types, the federated_connections_access_tokens connection option, and the related OAuth scopes.

Removed members:

Removed in v9 Kind
client.Users.FederatedConnectionsTokensets (ListAsync, DeleteAsync) Sub-client
FederatedConnectionTokenSet Type
ConnectionFederatedConnectionsAccessTokens Type
FederatedConnectionsAccessTokens property on ConnectionPropertiesOptions, UpdateConnectionOptions, ConnectionOptionsAzureAd, ConnectionOptionsCommonOidc, ConnectionOptionsGoogleApps, ConnectionOptionsOidc, ConnectionOptionsOkta Property
OauthScope.ReadFederatedConnectionsTokens (read:federated_connections_tokens) Scope constant
OauthScope.DeleteFederatedConnectionsTokens (delete:federated_connections_tokens) Scope constant

v8:

// Listing / deleting a user's federated connection token sets
var tokenSets = await client.Users.FederatedConnectionsTokensets.ListAsync("user_id");
await client.Users.FederatedConnectionsTokensets.DeleteAsync("user_id");

// Enabling token collection on a connection option
var options = new ConnectionOptionsOidc
{
    FederatedConnectionsAccessTokens = new ConnectionFederatedConnectionsAccessTokens
    {
        Active = true
    }
};

v9: No replacement. Remove the sub-client calls, the FederatedConnectionsAccessTokens assignments, and any use of the removed scope constants. Any code referencing these members will fail to compile and must be deleted.

What you need to do: Delete all usages of the members listed above. If you were relying on federated connection token collection, coordinate the replacement approach with the Auth0 API rather than the SDK.

Asn Device Binding Value Removed

The Asn value has been removed from ClientSessionTransferDelegationDeviceBindingEnum. Only Ip remains.

v8:

var binding = ClientSessionTransferDelegationDeviceBindingEnum.Asn;

v9:

// Asn is no longer available; only Ip remains
var binding = ClientSessionTransferDelegationDeviceBindingEnum.Ip;

What you need to do: Replace any use of ClientSessionTransferDelegationDeviceBindingEnum.Asn (or the string value "asn"). Code referencing the removed value will fail to compile.

Migration Steps

Step 1: Update the NuGet Package

dotnet add package Auth0.ManagementApi --version 9.*

Or update your .csproj:

<PackageReference Include="Auth0.ManagementApi" Version="9.*" />

Step 2: Rebuild and Address Compiler Errors

Most v8 code compiles unchanged. The breaking changes surface as compiler errors:

  1. ConnectionAttributeIdentifier not found — replace with EmailAttributeIdentifier, PhoneAttributeIdentifier, or UsernameAttributeIdentifier as appropriate (see Connection Attribute Identifier Types).
  2. Cannot implicitly convert WithRawResponseTask to Task — only appears where a delete/void method result was stored as an explicit Task or passed to a Task-typed parameter. Await it directly, or rely on the implicit conversion (see Void-Returning Methods).
  3. FederatedConnectionsTokensets / FederatedConnectionTokenSet / ConnectionFederatedConnectionsAccessTokens / FederatedConnectionsAccessTokens not found — the Federated Connections Tokens surface was removed; delete these usages (see Federated Connections Tokens Removed).
  4. ClientSessionTransferDelegationDeviceBindingEnum does not contain a definition for Asn — use Ip; Asn was removed (see Asn Device Binding Value Removed).

Step 3 (Optional): Adopt the Enriched Exception Information

If you handle ManagementApiException (or its subtypes such as TooManyRequestsError), you can now read structured error and rate-limit data. See Enriched Exceptions.

New Features in v9

Enriched Exceptions (ApiError, RateLimit, Quota Limits)

ManagementApiException now exposes structured, lazily-parsed error and rate-limit information. All members are additive — existing StatusCode and Body access is unchanged.

using Auth0.ManagementApi;

try
{
    await client.Users.GetAsync("user_id", new GetUserRequestParameters());
}
catch (TooManyRequestsError ex)
{
    // Structured error payload parsed from the response body
    string? code = ex.ErrorCode;      // machine-readable error code
    string? description = ex.Description; // human-readable message
    ApiError? apiError = ex.ApiError;  // full structured error, or null

    // Rate limit details parsed from response headers
    RateLimit? rl = ex.RateLimit;
    long? remaining = rl?.Remaining;             // x-ratelimit-remaining
    DateTimeOffset? reset = rl?.Reset;           // x-ratelimit-reset
    TimeSpan? retryAfter = rl?.RetryAfter;       // retry-after

    // Quota details (when present)
    var clientQuota = rl?.ClientQuotaLimit;      // Auth0-Client-Quota-Limit
    var orgQuota = rl?.OrganizationQuotaLimit;   // Auth0-Organization-Quota-Limit
}
catch (ManagementApiException ex)
{
    int statusCode = ex.StatusCode;
    object body = ex.Body;
    string? errorCode = ex.ErrorCode;
    string message = ex.Message; // now surfaces the API's error description when available
}

Key additions on ManagementApiException:

Member Description
ApiError? ApiError Structured error (Error, ErrorCode, Message) parsed from the body, or null
string? ErrorCode Machine-readable error code shortcut
string? Description Human-readable error description shortcut
RateLimit? RateLimit Rate limit + quota info parsed from response headers, or null
RawResponse? RawResponse Raw HTTP response (status, URL, headers) when available

Note: Message now returns the API's error description when one was parsed, falling back to the SDK's default message otherwise. If you log or assert on exact message text, review those sites.

Organization Roles Members Sub-client

v9 adds a Members sub-client under Organization Roles, letting you list the organization members assigned a specific role within an organization.

var pager = await client.Organizations.Roles.Members.ListAsync(
    id: "org_id",
    roleId: "rol_id",
    new ListOrganizationRoleMembersRequestParameters());

await foreach (var member in pager)
{
    Console.WriteLine(member);
}

The result is a Pager<RoleMember>, consistent with the v8 pagination model.

Token Vault Privileged Access Grants

v9 adds the TokenVaultPrivilegedAccessGrant type for granting client credential (M2M) applications privileged access to Token Vault connections and scopes.

var grant = new TokenVaultPrivilegedAccessGrant
{
    Connection = "google-oauth2",
    Scopes = new[] { "https://www.googleapis.com/auth/calendar" }
};

Connection Lifecycle Events

The Event Streams surface now includes Connection lifecycle CloudEvents (for example, EventStreamCloudEventConnectionCreated), enabling event-driven workflows that react to connection changes. Event stream delivery and redelivery clients were extended accordingly, backed by a new server-sent-events (SSE) reconnect helper for resilient streaming.

Network ACL auth0_managed Matches

NetworkAclMatch gains an optional Auth0Managed property (IEnumerable<string>?, JSON auth0_managed), letting you match against Auth0-managed network lists in ACL rules.

var match = new NetworkAclMatch
{
    Auth0Managed = new[] { "some-managed-list" }
};

Typed Error Bodies

v9 introduces typed error body records — NotFoundErrorBody and TooManyRequestsErrorBody (with their nested *Error types) — carrying Message, StatusCode, and a structured Error. These complement the enriched exception members above when you need to deserialize an error payload into a strong type.

Additional Notes

  1. No client initialization changes: ManagementClient, ManagementClientOptions, ITokenProvider, and the token provider implementations are unchanged from v8.
  2. No pagination changes: List operations continue to return Pager<T> with IAsyncEnumerable<T> iteration, AsPagesAsync(), and GetNextPageAsync().
  3. Optional<T> for PATCH semantics are unchanged from v8.
  4. Uniform raw-response access: every operation — including void operations — now supports .WithRawResponse() for status code, URL, and header inspection.

Troubleshooting

Common Issues

  1. The type or namespace name 'ConnectionAttributeIdentifier' could not be found: Replace with EmailAttributeIdentifier, PhoneAttributeIdentifier, or UsernameAttributeIdentifier matching the attribute.
  2. Cannot implicitly convert type 'WithRawResponseTask' to 'System.Threading.Tasks.Task': Await the call directly instead of assigning to a Task variable, or rely on the implicit conversion. Wrap in a lambda if passing as a Func<..., Task> delegate.
  3. Unexpected exception message text: ManagementApiException.Message now surfaces the parsed API error description when available — update log assertions if needed.
  4. 'IUsersClient' does not contain a definition for 'FederatedConnectionsTokensets' (or missing FederatedConnectionTokenSet / ConnectionFederatedConnectionsAccessTokens / FederatedConnectionsAccessTokens): the Federated Connections Tokens surface was removed in v9 — delete these usages.
  5. 'ClientSessionTransferDelegationDeviceBindingEnum' does not contain a definition for 'Asn': the Asn value was removed — use Ip.

Getting Help


This migration guide covers the changes needed to upgrade Auth0.ManagementApi from v8 to v9. The breaking-change surface is small — most v8 code compiles unchanged — while v9 adds richer exceptions, uniform raw-response access, and new Management API capabilities.