U17 Active Directory backoffice authentication

Hi everyone,

I’m trying to update an internal website from Umbraco 13 to 17. It uses Active Directory authentication, so when a user opens /umbraco it just logs in automatically. I’m struggling to get this working in Umbraco 17.

The code I’m using is adapted from what I was doing in 13, which in turn was adapted from 10, and probably 8 before that. It might not be following current best practice :slight_smile:

I have a file called BackofficeAuthenticationExtensions.cs as follows. I’ve added comments showing what I’ve changed from the U13 version.

using Microsoft.AspNetCore.Authentication.MicrosoftAccount;
using Microsoft.Extensions.Options;
using Umbraco.Cms.Core;
using Umbraco.Cms.Api.Management.Security; // Was Umbraco.Cms.Web.BackOffice.Security

namespace KnowledgeBase
{
    public static class BackofficeAuthenticationExtensions
    {
        public static IUmbracoBuilder ConfigureAuthentication(this IUmbracoBuilder builder)
        {
            builder.Services.ConfigureOptions<AzureB2CBackofficeExternalLoginProviderOptions>();
            builder.AddBackOfficeExternalLogins(logins =>
            {
                const string schema = MicrosoftAccountDefaults.AuthenticationScheme;

                logins.AddBackOfficeLogin(
                    backOfficeAuthenticationBuilder =>
                    {
                        backOfficeAuthenticationBuilder.AddMicrosoftAccount( // Was BackOffice with a capital B
                            BackOfficeAuthenticationBuilder.SchemeForBackOffice(schema) ?? string.Empty,
                            options =>
                            {
                                options.AuthorizationEndpoint = "https://login.microsoftonline.com/MY GUID/oauth2/v2.0/authorize";
                                options.CallbackPath = "/umbraco-signin-microsoft/";
                                options.ClientId = "MY CLIENT ID";
                                options.ClientSecret = "MY CLIENT SECRET";
                                options.TokenEndpoint = "https://login.microsoftonline.com/MY GUID/oauth2/v2.0/token";
                            });
                    });
            });
            return builder;
        }
    }

    public class AzureB2CBackofficeExternalLoginProviderOptions : IConfigureNamedOptions<BackOfficeExternalLoginProviderOptions>
    {
        public const string SchemeName = "Microsoft";
        public void Configure(string? name, BackOfficeExternalLoginProviderOptions options)
        {
            // Was if (name != Constants.Security.BackOfficeExternalAuthenticationTypePrefix + SchemeName)
            if (name != BackOfficeAuthenticationBuilder.SchemeForBackOffice(SchemeName))
            {
                return;
            }

            Configure(options);
        }

        public void Configure(BackOfficeExternalLoginProviderOptions options)
        {
            options.AutoLinkOptions = new ExternalSignInAutoLinkOptions(
                autoLinkExternalAccount: true,
                defaultUserGroups: new[] { "editor" }, // Was Constants.Security.EditorGroupAlias
                defaultCulture: null,
                allowManualLinking: false
            )
            {
                OnAutoLinking = (autoLinkUser, loginInfo) =>
                {
                    autoLinkUser.IsApproved = false;
                },
                OnExternalLogin = (user, loginInfo) =>
                {
                    return true;
                }
            };

            options.DenyLocalLogin = true;
            // options.AutoRedirectLoginToExternalProvider = true; removed
        }
    }
}

As you can see, very little has changed between the working U13 version and the non-working U17 version.

My Program.cs contains .ConfigureAuthentication() just before the .Build() call. Web.config contains <requestLimits maxQueryString="8192" maxUrl="16384" />.

The issue is that when I browse to /umbraco, I get the message “Unfortunately, direct login is not possible. It has been disabled by a provider.” The log contains an authentication attempt:

{"@t":"2026-03-31T21:45:09.6254005Z","@mt":"The request URI matched a server endpoint: {Endpoint}.","@tr":"5d72fcdad7ea46da61e4e5844974d41c","@sp":"0d96d97163bb3f89","Endpoint":"Authorization","EventId":{"Id":6053},"SourceContext":"OpenIddict.Server.OpenIddictServerDispatcher","RequestId":"400003f5-0000-f700-b63f-84710c7967bb","RequestPath":"/umbraco/management/api/v1/security/back-office/authorize","ProcessId":2488,"ProcessName":"w3wp","ThreadId":3,"ApplicationId":"21f1660fa8588b317dc9e30a8881e8ad97f69792","MachineName":"BRCSVWEBT4","Log4NetLevel":"INFO ","HttpRequestId":"741c812c-dd61-4633-8121-50f44e4c6fb8","HttpRequestNumber":3,"HttpSessionId":"0"}
{"@t":"2026-03-31T21:45:09.6266188Z","@mt":"The authorization request was successfully extracted: {Request}.","@tr":"5d72fcdad7ea46da61e4e5844974d41c","@sp":"0d96d97163bb3f89","Request":"{\r\n  \"redirect_uri\": \"https://kbtest.mydomain.net/umbraco/oauth_complete\",\r\n  \"client_id\": \"umbraco-back-office\",\r\n  \"response_type\": \"code\",\r\n  \"state\": \"HXE1rFsm5N\",\r\n  \"scope\": \"offline_access\",\r\n  \"prompt\": \"consent\",\r\n  \"access_type\": \"offline\",\r\n  \"code_challenge\": \"REDACTED\",\r\n  \"code_challenge_method\": \"S256\"\r\n}","EventId":{"Id":6030},"SourceContext":"OpenIddict.Server.OpenIddictServerDispatcher","RequestId":"400003f5-0000-f700-b63f-84710c7967bb","RequestPath":"/umbraco/management/api/v1/security/back-office/authorize","ProcessId":2488,"ProcessName":"w3wp","ThreadId":3,"ApplicationId":"21f1660fa8588b317dc9e30a8881e8ad97f69792","MachineName":"BRCSVWEBT4","Log4NetLevel":"INFO ","HttpRequestId":"741c812c-dd61-4633-8121-50f44e4c6fb8","HttpRequestNumber":3,"HttpSessionId":"0"}
{"@t":"2026-03-31T21:45:09.6511115Z","@mt":"The authorization request was successfully validated.","@tr":"5d72fcdad7ea46da61e4e5844974d41c","@sp":"0d96d97163bb3f89","EventId":{"Id":6031},"SourceContext":"OpenIddict.Server.OpenIddictServerDispatcher","RequestId":"400003f5-0000-f700-b63f-84710c7967bb","RequestPath":"/umbraco/management/api/v1/security/back-office/authorize","ProcessId":2488,"ProcessName":"w3wp","ThreadId":3,"ApplicationId":"21f1660fa8588b317dc9e30a8881e8ad97f69792","MachineName":"BRCSVWEBT4","Log4NetLevel":"INFO ","HttpRequestId":"741c812c-dd61-4633-8121-50f44e4c6fb8","HttpRequestNumber":3,"HttpSessionId":"0"}

So it does appear to be trying to authenticate, but there’s nothing in the log past that “successfully validated” entry. I have no idea where I’m supposed to look to figure out why it isn’t logging in.

The really bizarre thing is that this worked yesterday. I immediately checked my working code into source control, but now the same revision is failing. It was completely stable under Umbraco 13, so I’m at a complete loss here. I feel like I might have missed something obvious.

Can anyone help?

Thanks :slight_smile:

Of course, after going around in circles for two hours, I make a forum post and then immediately figure out what the problem is. I needed to add “my-auth-providers” to App_Plugins as documented in the instructions.

As for how it worked yesterday: I was playing around with trying to do everything “by the book” but ultimately gave up on it and fell back to updating the existing code. Although I’d deleted my-auth-providers from source control, thinking it wasn’t needed, I presumably never deleted it from the web server until I redeployed the entire site this morning.