Rokstep.IdentityModel.Clients.ActiveDirectory.Shims 0.2.0-alpha

This is a prerelease version of Rokstep.IdentityModel.Clients.ActiveDirectory.Shims.
dotnet add package Rokstep.IdentityModel.Clients.ActiveDirectory.Shims --version 0.2.0-alpha
                    
NuGet\Install-Package Rokstep.IdentityModel.Clients.ActiveDirectory.Shims -Version 0.2.0-alpha
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="Rokstep.IdentityModel.Clients.ActiveDirectory.Shims" Version="0.2.0-alpha" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Rokstep.IdentityModel.Clients.ActiveDirectory.Shims" Version="0.2.0-alpha" />
                    
Directory.Packages.props
<PackageReference Include="Rokstep.IdentityModel.Clients.ActiveDirectory.Shims" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add Rokstep.IdentityModel.Clients.ActiveDirectory.Shims --version 0.2.0-alpha
                    
#r "nuget: Rokstep.IdentityModel.Clients.ActiveDirectory.Shims, 0.2.0-alpha"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package Rokstep.IdentityModel.Clients.ActiveDirectory.Shims@0.2.0-alpha
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=Rokstep.IdentityModel.Clients.ActiveDirectory.Shims&version=0.2.0-alpha&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=Rokstep.IdentityModel.Clients.ActiveDirectory.Shims&version=0.2.0-alpha&prerelease
                    
Install as a Cake Tool

Rokstep.IdentityModel.Clients.ActiveDirectory.Shims

Apache 2.0 License NuGet preview

Drop-in replacement shim for the deprecated Azure Active Directory Authentication Library (ADAL). Replace your Microsoft.IdentityModel.Clients.ActiveDirectory NuGet reference with Rokstep.IdentityModel.Clients.ActiveDirectory.Shims and your existing ADAL code compiles and runs on .NET 6 / .NET 8 without modification. Internally, this shim delegates every token request to Microsoft's supported replacement, the Microsoft Authentication Library (MSAL).

Why this exists

ADAL (Microsoft.IdentityModel.Clients.ActiveDirectory) has been deprecated by Microsoft. The library reached end of support in June 2023 — no security fixes, no new features, no .NET 9/10/11 guarantees. Microsoft's recommended replacement is MSAL (Microsoft.Identity.Client), but the two libraries have different APIs. The migration is not a find-and-replace — it is a rewrite of every authentication call site.

Applications that still reference ADAL face a choice:

  1. Stay on ADAL, risk breakage on future .NET and accept no security support.
  2. Rewrite every authentication call to MSAL. Days to weeks of work for a medium codebase, with a non-trivial risk of subtle runtime regressions (cache behaviour, error-code shapes, claims handling).
  3. Use Rokstep.IdentityModel.Clients.ActiveDirectory.Shims. Replace one NuGet reference, keep existing ADAL call sites, and let the shim translate each ADAL call into the equivalent MSAL call at runtime. Done in minutes.

Rokstep.IdentityModel.Clients.ActiveDirectory.Shims is option 3. It is an independent reimplementation of the ADAL public API surface, powered internally by the supported MSAL library. It is not a fork of ADAL, not an official successor, and not endorsed by Microsoft. It exists to keep your existing code working while you plan the real MSAL migration at your own pace.

Installation

dotnet remove package Microsoft.IdentityModel.Clients.ActiveDirectory
dotnet add package Rokstep.IdentityModel.Clients.ActiveDirectory.Shims --version 0.2.0-alpha

Nothing in your source code needs to change. Every using Microsoft.IdentityModel.Clients.ActiveDirectory; keeps working.

Quick start

using Microsoft.IdentityModel.Clients.ActiveDirectory;

#pragma warning disable CS0618 // Accept the migration hints, address them gradually.

var context = new AuthenticationContext("https://login.microsoftonline.com/contoso.onmicrosoft.com");
var cred = new ClientCredential(clientId: "<app-id>", clientSecret: "<secret>");

var result = await context.AcquireTokenAsync("https://graph.microsoft.com", cred);
Console.WriteLine(result.CreateAuthorizationHeader());

This is the exact same shape you would write against the real ADAL library. Under the hood, the shim:

  1. Builds an MSAL IConfidentialClientApplication lazily on the first call.
  2. Translates the ADAL resource (https://graph.microsoft.com) into the MSAL scope (https://graph.microsoft.com/.default).
  3. Delegates to AcquireTokenForClient(new[] { scope }).ExecuteAsync().
  4. Projects the MSAL AuthenticationResult into an ADAL AuthenticationResult so the caller sees the expected type.
  5. Wraps any MsalServiceException / MsalException as the corresponding AdalServiceException / AdalException so catch blocks continue to work.

What's in v0.2.0-alpha

ADAL type Status RKSAD ID Notes
AuthenticationContext Implemented RKSAD0001 Four constructors (authority, authority, validateAuthority, authority, TokenCache, authority, validateAuthority, TokenCache); Authority/ValidateAuthority/TokenCache properties; two AcquireTokenAsync overloads (client-credentials + ROPC); two AcquireTokenSilentAsync overloads ((resource, clientId) and (resource, ClientCredential, UserIdentifier)); interactive AcquireTokenAsync(resource, clientId, redirectUri, IPlatformParameters) stub that throws NotSupportedException.
AuthenticationResult Implemented RKSAD0002 AccessToken, AccessTokenType, ExpiresOn, ExtendedExpiresOn, IdToken, TenantId, UserInfo, CreateAuthorizationHeader().
ClientCredential Implemented RKSAD0003 (clientId, clientSecret) constructor. Secret is write-only.
UserPasswordCredential Implemented RKSAD0004 (userName, password) constructor. Password is write-only. ROPC flow.
UserCredential Stub RKSAD0005 Data holder only; interactive flow (browser popup) deferred to v0.3.
AdalException Implemented RKSAD0006 Three constructors; ErrorCode property.
AdalServiceException Implemented RKSAD0007 Inherits AdalException; StatusCode and ServiceErrorCodes init-only properties.
TokenCache Implemented RKSAD0008 Serialize(), Deserialize(byte[]), Clear(), BeforeAccess / AfterAccess hooks. Backed by MSAL's ITokenCacheSerializer; wired into the underlying MSAL application on first token request.
TokenCacheNotificationCallback (delegate) Implemented — Matches original ADAL delegate shape.
TokenCacheNotificationArgs Implemented — Event data passed to persistence hooks; exposes the firing TokenCache.
AdalSilentTokenAcquisitionException Implemented RKSAD0009 Inherits AdalException. Thrown by AcquireTokenSilentAsync on cache miss or when the MSAL in-memory cache reports MsalUiRequiredException.
UserIdentifier Implemented RKSAD0010 Id, Type, AnyUser sentinel. Resolves against MSAL's IAccount collection for silent flows.
UserIdentifierType (enum) Implemented RKSAD0010 UniqueId, OptionalDisplayableId, RequiredDisplayableId.
UserInfo Implemented — Populated from MSAL's AuthenticationResult and decoded ID-token claims: UniqueId, DisplayableId, GivenName, FamilyName, IdentityProvider.
IPlatformParameters (marker interface) Stub RKSAD0011 Structural compatibility only — methods that accept it throw NotSupportedException in v0.2.
PlatformParameters Stub RKSAD0011 Concrete IPlatformParameters. Constructors compile and store PromptBehavior; interactive flow throws.
PromptBehavior (enum) Stub RKSAD0011 Auto, Always, Never, RefreshSession.

Internal helpers (Microsoft.IdentityModel.Clients.ActiveDirectory.Internal):

  • AdalErrorCodes — MSAL-to-ADAL error-code translation catalog (17+ mappings). Routes through AcquireTokenAsync and AcquireTokenSilentAsync. Unmapped codes are returned with a "msal_" prefix so consumers can still distinguish them.
  • ResourceToScopeConverter — translates the ADAL resource URI into MSAL's resource/.default scope form.
  • ShimArgumentGuards — polyfills ArgumentException.ThrowIfNullOrEmpty / ThrowIfNullOrWhiteSpace on the net6.0 target framework leg.

See docs/api-surface.md for the full implementation plan and the v0.3+ roadmap.

What's not in v0.2.0-alpha

Tracked for v0.3:

  • Interactive authentication flow — the AcquireTokenAsync(resource, clientId, redirectUri, IPlatformParameters) overload exists and compiles, but always throws NotSupportedException. UserCredential remains a data-holder stub because the interactive flow resolves it.
  • Device code flow — DeviceCodeResult is not shimmed; a v1-style MSAL builder pattern (AcquireTokenWithDeviceCode) is required and is tracked for v0.3.
  • On-behalf-of flow — UserAssertion is not shimmed; middle-tier APIs using OBO should port directly to MSAL's AcquireTokenOnBehalfOf.
  • End-to-end live token acquisition parity against a real Entra ID tenant — tracked for v0.5-beta and requires a dedicated CI test tenant.

See docs/known-quirks.md for the full behavioral-delta list and docs/compatibility-matrix.md for the explicit parity table.

Proven drop-in compatibility

The test suite includes parity tests: same-process structural assertions run against BOTH the original ADAL 5.2.9 and Rokstep.IdentityModel.Clients.ActiveDirectory.Shims via extern alias. 24 parity scenarios currently pass on net8.0, covering:

  • AuthenticationContext type exists on both sides, in the same namespace
  • AuthenticationContext has the (string authority) constructor on both sides
  • AuthenticationContext has the (string authority, bool validateAuthority) constructor on both sides
  • AuthenticationContext has the (string authority, TokenCache) constructor on both sides
  • AuthenticationContext exposes Authority as a string property on both sides
  • AuthenticationContext exposes AcquireTokenSilentAsync on both sides
  • AuthenticationResult has AccessToken, ExpiresOn, and CreateAuthorizationHeader() on both sides
  • ClientCredential has the (string, string) constructor and ClientId property on both sides
  • Shim AuthenticationContext.AcquireToken* methods are a subset of the original
  • AdalException derives from System.Exception on both sides
  • AdalServiceException inherits from AdalException on both sides
  • AdalException.ErrorCode is a string property on both sides
  • AdalSilentTokenAcquisitionException inherits from AdalException on both sides
  • TokenCache type exists on both sides, in the same namespace, with a default constructor
  • UserIdentifier type exists on both sides with the AnyUser sentinel
  • UserIdentifierType enum exists on both sides

UserPasswordCredential parity assertions are shim-only because ADAL 5.x for netstandard1.3 removed the ROPC type from the public surface (ROPC is only present in the net45 leg of the original package). Shim assertions still fire and fail loudly if we ever break the type.

On top of the parity suite, 96 unit tests (xUnit) cover constructor validation, property population, scope conversion, the MSAL-to-ADAL error-code catalog, obsolete-attribute presence, silent-flow argument validation, token-cache serialization round-trips, interactive-flow NotSupportedException surface, and user-identifier resolution.

End-to-end token-acquisition parity against live Entra ID is tracked for v0.5-beta and requires a dedicated test tenant; see docs/compatibility-matrix.md for the plan.

Migration path

Rokstep.IdentityModel.Clients.ActiveDirectory.Shims is a transitional package. Every public type carries an [Obsolete] attribute with a DiagnosticId of the form RKSAD####, pointing to migration documentation. The recommended path:

  1. Install the shim today. Zero code changes. Your existing ADAL code compiles and runs on .NET 6/8. Buy time.
  2. Install Rokstep.Analyzers (companion package). Enables IDE-level diagnostics for all RKSAD rules, with code fixes that can either keep the shim or open the MSAL migration guide.
  3. Gradually migrate directly to MSAL (Microsoft.Identity.Client). This is the long-term target. The shim's [Obsolete] hints point to dev.rokstep.eu/migrations/RKSAD#### pages that document the MSAL equivalent for each ADAL call.

The shim's job is to buy you time while you plan the real rewrite to MSAL. Do not plan to run the shim in production forever.

Limitations and known differences

See docs/known-quirks.md for the complete list. Short summary:

Scenario Behavior Notes
Client-credentials flow Fully supported Delegates to MSAL AcquireTokenForClient.
ROPC (UserPasswordCredential) Fully supported Delegates to MSAL AcquireTokenByUsernamePassword.
TokenCache persistence Supported in v0.2 BeforeAccess / AfterAccess hooks wired into MSAL's ITokenCacheSerializer; serialize/deserialize to your durable store.
AcquireTokenSilentAsync Supported in v0.2 Backed by MSAL's in-memory cache; translates MsalUiRequiredException into AdalSilentTokenAcquisitionException.
Error code mapping Catalog in v0.2 17+ MSAL codes mapped to ADAL equivalents; unmapped codes are prefixed msal_ for discoverability.
Rich UserInfo Supported in v0.2 Populated from MSAL's AuthenticationResult and decoded ID-token claims.
Interactive authentication Stub in v0.2, throws NotSupportedException Full browser flow planned for v0.3. Port directly to MSAL's AcquireTokenInteractive(...) until then.
Device code flow Not supported Planned for v0.3.
On-behalf-of flow Not supported Planned for v0.3.

License

Licensed under the Apache License 2.0.

Attribution

Rokstep.IdentityModel.Clients.ActiveDirectory.Shims is an independent drop-in replacement for ADAL, which is licensed by Microsoft under the MIT License. Portions of the public API surface are derived from ADAL — Copyright (c) Microsoft Corporation. No ADAL source code has been copied; all wrappers are original implementations that translate ADAL calls into calls on MSAL (Microsoft.Identity.Client), also Microsoft, also MIT.

"ADAL", "Azure Active Directory", "Microsoft.IdentityModel.Clients.ActiveDirectory", and "MSAL" are used solely to identify the original library this shim replaces and the library it delegates to. Rokstep is not affiliated with, endorsed by, or sponsored by Microsoft Corporation.

See LICENSE-AUDIT.md for the full derivative-work analysis.

Product Compatible and additional computed target framework versions.
.NET net6.0 is compatible.  net6.0-android was computed.  net6.0-ios was computed.  net6.0-maccatalyst was computed.  net6.0-macos was computed.  net6.0-tvos was computed.  net6.0-windows was computed.  net7.0 was computed.  net7.0-android was computed.  net7.0-ios was computed.  net7.0-maccatalyst was computed.  net7.0-macos was computed.  net7.0-tvos was computed.  net7.0-windows was computed.  net8.0 is compatible.  net8.0-android was computed.  net8.0-browser was computed.  net8.0-ios was computed.  net8.0-maccatalyst was computed.  net8.0-macos was computed.  net8.0-tvos was computed.  net8.0-windows was computed.  net9.0 was computed.  net9.0-android was computed.  net9.0-browser was computed.  net9.0-ios was computed.  net9.0-maccatalyst was computed.  net9.0-macos was computed.  net9.0-tvos was computed.  net9.0-windows was computed.  net10.0 was computed.  net10.0-android was computed.  net10.0-browser was computed.  net10.0-ios was computed.  net10.0-maccatalyst was computed.  net10.0-macos was computed.  net10.0-tvos was computed.  net10.0-windows was computed. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

NuGet packages

This package is not used by any NuGet packages.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
0.2.0-alpha 111 4/17/2026