Authenticating to Active Directory Federation Services (ADFS) 2019 with .NET Core 3.1
Googling this shows only one sample and that sample uses WS-Federation not OpenID Connect (OIDC)!
There doesn’t appear to be anything else and you can’t use the usual ADAL / MSAL libraries because there aren’t .NET Core versions yet.
(There are however, a number of .Net Core samples for accessing Azure AD).
As always, when there’s a vacuum …
I started by creating a MVC ASP.Net Core application in VS 2019 with no authentication.
Then I added code to Startup.cs to enable this.
I used many samples to get this working and found identityserver 4 to be helpful.
(I used “dotnet new is4inmem” from the identityserver4 templates as a reference).
As usual, the code is in the gist.
There may well be extraneous code here but it works against IIS and IIS Express.
I added these NuGet packages.
In the launchSettings.json:
"iisExpress": {
"applicationUrl": "http://localhost:51136",
"sslPort": 44366
}
So using SSL, the URL is:
https://localhost:44366
The OIDC configuration is:
.AddOpenIdConnect(options =>
{
options.SignInScheme = "Cookies";
options.Authority = "https://localhost:44366";
options.RequireHttpsMetadata = true;
options.ResponseType = OpenIdConnectResponseType.Code;
options.UsePkce = false;
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.SaveTokens = true;// MetadataAddress represents the Active Directory instance used to authenticate users.
options.MetadataAddress = "https://my-adfs/adfs/.well-known/openid-configuration"; options.ClientId = "79ede524-aceb-4824-b25e-a4a8b08e5156";
});
The key points here are the clientID, the well-known discovery endpoint (metadata) and the scopes.
To kick off the authentication, I added the [Authorize] annotation to the home controller.
using System.Diagnostics;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using CoreWebApplication.Models;
using Microsoft.AspNetCore.Authorization;
namespace CoreWebApplication.Controllers
{
[Authorize]
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
public HomeController(ILogger<HomeController> logger)
{
_logger = logger;
}
...
and I changed privacy.cshtml to display the claims as per the gist.
On the ADFS side, we need to add an application group. This needs to be a “Web browser accessing a web application”.
This generates two parts; a native and a web application.
The native application is configured as below.
Note that the “Client Id” is used to configure the option as above:
options.ClientId = "79ede524-aceb-4824-b25e-a4a8b08e5156";
and the “Redirect URI” derives from the SSL URL as above plus “signin-oidc”.
For the web application, we configure some claims rules:
Now lets run it.
This brings up the ADFS login screen:
We enter our credentials and get redirected back to the application.
Clicking the “Privacy” tab shows:
and
As an exercise, I turned PKCE support on as this is supported in ADFS 2019.
options.UsePkce = true;
It works as expected and you can see the extra parameters (the “code challenge” ones) in the request:
All good!