-
Notifications
You must be signed in to change notification settings - Fork 367
msal net 4
Note
This is a preview of the release documentation for MSAL 4.0 it's not completely up to date and might still change
We are excited to announce that three weeks after MSAL.NET GA-ed, we are now releasing a first incremental update bringing features you've been asking for:
- ADFS 2019 support
- Asynchronous token cache serialization
- Interactive token acquisition on .NET Core (through the OS browser), including on Linux and Mac
Unfortunately, the asynchronous token cache serialization introduced a breaking change, so we'll have to bump-up the major version of MSAL. In practice, there is little code so you should not be impacted at all, or too much. As we were taking a breaking change we've decided to take other breaking changes as well on Telemetry (which, we are pretty sure won't impact you)
You can now connect directly to ADFS 2019. This is especially important if you intend to write an app working with Azure Stack
To connect directly to ADFS, you'll use the existing WithAdfsAuthority
Builder method:
var app = PublicClientApplicationBuilder.Create(clientId)
.WithAdfsAuthority("https://somesite.contoso.com/adfs/")
.Build();
You can then use the AcquireTokenXX methods as usual.
For more details see ADFS support
Until MSAL.NET 3.1, when you wanted to customize token cache serialization, you had to provide synchronous methods. This means that the whole process was blocked when storage was happening, which could be damageable for performance, for instance of Web Apps or Web APIs using a SQL token cache. Indeed, it's a frequent use case to persist the Token Cache in a distributed manner. Several among you have asked to have BeforeAccess/AfterAccess with an async signature, since most of the time the implementation is doing some IO, which can take time.
The ITokenCache
interface now contains three new methods to set asynchronous callbacks: SetAfterAccessAsync
, SetBeforeAccessAsync
, SetBeforeWriteAsync
public interface ITokenCache
{
...
void SetAfterAccessAsync(Func<TokenCacheNotificationArgs, Task> afterAccess);
void SetBeforeAccessAsync(Func<TokenCacheNotificationArgs, Task> beforeAccess);
void SetBeforeWriteAsync(Func<TokenCacheNotificationArgs, Task> beforeWrite);
...
}
Given that .NET Core does not provide a Web browser control, until MSAL.NET 3.1, the interactive token acquisition was not supported. From this version, you can now use AcquireTokenInteractive
with MSAL.NET. The experience for the end user will be the following
- The default browser for the operating system will be launched (a new tab in an existing browser can be opened)
- The user will then go through the sign-in and consent (if needed) in this browser/tab
- when the interaction is done, the browser will display will just display that the authentication is successful. The sentence is currently
Authentication complete. You can return to the application. Feel free to close this browser tab
. It's not yet customizable (See below).
Note that the experience is what it is, and in particular, when the interactive authentication has happened, the end user sees that the page which was displayed is localhost:someport?code=XYZTqlsdkfslkhskgh The code is the authorization code. Even if the code was copied, it would not be usable as MSAL.NET uses the PKCE to protect the authorization code flow.
Even if this experience is not as neat as with embedded web view used on the .NET Framework platform, it has the advantage of enabling SSO with Web applications on the platform, which is a great plus. Chances are that your users won't even need to sign-in!
- You'll need to register "http://localhost" as a Public client (mobile & desktop) redirect URI for your application. In that case, Azure AD accepts any http://localhost:port. This is used by MSAL which finds an empty port, serves an HTML page and listen to this port to get the authentication code.
- alternatively you can specify a localhost URL with a port if you don't want to let MSAL.NET choose a port.
The code is almost the same as if you were writing .NET Framework code, except that:
- This is .NET Core
- You need to specify a RedirectUri set to "http://localhost" (or "http://localhost:port" if you registered a URL with a port)
Here is the complete code for a .NET Core console application using this feature:
using Microsoft.Identity.Client;
using System;
using System.Linq;
using System.Threading.Tasks;
namespace ConsoleApp1
{
class Program
{
static async Task Main(string[] args)
{
string[] scopes = new[] { "user.read" };
string clientId = "e9f70606-879c-4f0b-87cd-2754fccc4f44";
var app = PublicClientApplicationBuilder.Create(clientId)
.WithRedirectUri("http://localhost")
.Build();
var accounts = await app.GetAccountsAsync();
AuthenticationResult result;
try
{
result = await app.AcquireTokenSilent(scopes, accounts.FirstOrDefault())
.ExecuteAsync();
}
catch (MsalUiRequiredException)
{
result = await app.AcquireTokenInteractive(scopes)
.ExecuteAsync();
}
Console.WriteLine($"Hello {result.Account.Username}");
}
}
}
This kind of code used to throw a PlatformNotSupportedException
before MSAL 3.1, with an explicit message telling you that on .NET Core interactive authentication was not supported, and advising to use Device Code Flow. This now works with the user experience described above.
As a support for this new feature, MSALError
gets four additional strings used in MsalClientExceptions when things don't work as expected.
public static class MsalError
{
...
public const string InvalidAuthorizationUri = "invalid_authorization_uri";
public const string LinuxXdgOpen = "linux_xdg_open_failed";
public const string LoopbackRedirectUri = "loopback_redirect_uri";
public const string LoopbackResponseUriMisatch = "loopback_response_uri_mismatch";
...
}
Error | Description |
---|---|
LoopbackRedirectUri | This error happens when you forgot to add the .WithRedirectUri("http://localhost") modifier when building the application. An MsalClientException is then thrown by MSAL.NET with the following error message 'Only loopback redirect uri is supported, but urn:ietf:wg:oauth:2.0:oob was found. Configure http://localhost or http://localhost:port both during app registration and when you create the PublicClientApplication object. See https://aka.ms/msal-net-os-browser for details' . |
LinuxXdgOpen | On Linux, this MsalClientException occurs when MSAL.NET is unable to open a web page specified at the redirect URI or selected port) using xdg-open . The inner exception provides more details. Possible causes for this error are that xdg-open is not installed or it cannot find a way to open an url. As a first mitigation, the end user needs to make sure they can open a web page by invoking from a terminal: xdg-open https://www.bing.com
|
InvalidAuthorizationUri and LoopbackResponseUriMisatch | An MSALClientException with one of these ErrorCode is thrown when the response from the Microsoft identity platform v2.0 authorize endpoint is not what MSAL.NET expected, and therefore MSAL.NET cannot extract the authorization code. The best is to look at the inner exception for details |
This is a start. In a next version to come we'll add additional customization so that you can provide URLs to have your browser navigate in case of success and failure;
Until MSAL.NET 3.0.8, you could subscribe to telemetry by adding a telemetry callback .WithTelemetry(), and then sending to your telemetry pipeline of choice a list of events (which themselves were dictionaries of name, values)
From MSAL.NET 4.0, if you want to add telemetry to your application, you need to create a class implementing ITelemetryConfig
. MSAL.NET provides such a class (TraceTelemetryConfig
) which does not send telemetry anywhere, but uses System.Trace.TraceInformation
to trace the telemetry events. You could take it from there and add trace listeners to send telemetry.
public interface ITelemetryConfig
{
TelemetryAudienceType AudienceType { get; }
Action<ITelemetryEventPayload> DispatchAction { get; }
string SessionId { get; }
}
public class TraceTelemetryConfig : ITelemetryConfig
{
public TraceTelemetryConfig();
public IEnumerable<string> AllowedScopes { get; }
public TelemetryAudienceType AudienceType { get; }
public Action<ITelemetryEventPayload> DispatchAction { get; }
public string SessionId { get; }
}
You initialize this config object with:
- the audience (pre-production or production)
- a callback that will process the
ITelemetryEventPayload
which is a set of typed dictionary containing telemetry values by their name. The allowed types arebool
,long
,int
, andstring
public enum TelemetryAudienceType
{
PreProduction = 0,
Production = 1,
}
public interface ITelemetryEventPayload
{
IReadOnlyDictionary<string, bool> BoolValues { get; }
IReadOnlyDictionary<string, long> Int64Values { get; }
IReadOnlyDictionary<string, int> IntValues { get; }
string Name { get; }
IReadOnlyDictionary<string, string> StringValues { get; }
string ToJsonString();
}
Finally, you create you app by passing the telemetry config
var app = PublicClientApplication.Create(clientId)
.WithTelemetry(telemetryConfig)
.Build();
- Home
- Why use MSAL.NET
- Is MSAL.NET right for me
- Scenarios
- Register your app with AAD
- Client applications
- Acquiring tokens
- MSAL samples
- Known Issues
- Acquiring a token for the app
- Acquiring a token on behalf of a user in Web APIs
- Acquiring a token by authorization code in Web Apps
- AcquireTokenInteractive
- WAM - the Windows broker
- .NET Core
- Maui Docs
- Custom Browser
- Applying an AAD B2C policy
- Integrated Windows Authentication for domain or AAD joined machines
- Username / Password
- Device Code Flow for devices without a Web browser
- ADFS support
- High Availability
- Regional
- Token cache serialization
- Logging
- Exceptions in MSAL
- Provide your own Httpclient and proxy
- Extensibility Points
- Clearing the cache
- Client Credentials Multi-Tenant guidance
- Performance perspectives
- Differences between ADAL.NET and MSAL.NET Apps
- PowerShell support
- Testing apps that use MSAL
- Experimental Features
- Proof of Possession (PoP) tokens
- Using in Azure functions
- Extract info from WWW-Authenticate headers
- SPA Authorization Code