Long delay after logging in with custom Microsoft auth provider (Umbraco 16)

I’m working on a custom Microsoft login provider for the Umbraco 16 backoffice, using Azure AD. It’s based on some code I had working in an Umbraco 13 project, and the login itself works — users can sign in and get into the backoffice — but there’s a noticeable delay (around 2 - 5 minutes) between completing the Microsoft sign-in and actually being logged into Umbraco.

This delay wasn’t happening in the v13 version, and I’m trying to figure out what’s causing it in v16.

What I’m doing:

  • I’m using AddMicrosoftAccount for auth.

  • Auto-linking is enabled (but only for a list of allowed users pulled from config).

  • Manual linking is disabled.

  • options.SaveTokens = true is set.

  • Login does eventually work — there’s just a long pause before Umbraco loads.

ExternalLoginAuthentication.cs

 public static class ExternalLoginAuthentication
 {
     public static IUmbracoBuilder ConfigureAuthentication(this IUmbracoBuilder builder)
     {
         string? microsoftTenantId = Settings.GetStringCongfigSetting("AuthenticationConfiguration:microsoftTenantId");
         string? microsoftClientId = Settings.GetStringCongfigSetting("AuthenticationConfiguration:microsoftClientId");
         string? microsoftClientSecret = Settings.GetStringCongfigSetting("AuthenticationConfiguration:authenticationMicrosoftClientSecret");

         builder.Services.ConfigureOptions<ExternalLoginProviderOptions>();

         builder.AddBackOfficeExternalLogins(logins =>
         {
             logins.AddBackOfficeLogin(
                 backOfficeAuthenticationBuilder =>
                 {
                     backOfficeAuthenticationBuilder.AddMicrosoftAccount(
            
                   BackOfficeAuthenticationBuilder.SchemeForBackOffice(ExternalLoginProviderOptions.SchemeName)!,
                         options =>
                         {
                            options.AuthorizationEndpoint = $"https://login.microsoftonline.com/{microsoftTenantId}/oauth2/v2.0/authorize";
                             options.TokenEndpoint = $"https://login.microsoftonline.com/{microsoftTenantId}/oauth2/v2.0/token";
                           
                             options.CallbackPath = "/umbraco-signin-microsoft";
                             options.ClientId = microsoftClientId ?? "";
                             options.ClientSecret = microsoftClientSecret ?? "";
                             options.SaveTokens = true;
                         });
                 });
         });
         return builder;
     }
 }

ExternalLoginProviderOptions.cs

public class ExternalLoginProviderOptions: IConfigureNamedOptions < BackOfficeExternalLoginProviderOptions > {
  private readonly IConfiguration _config;

  public ExternalLoginProviderOptions(IConfiguration config) {
    _config = config;
  }

  public const string SchemeName = "Microsoft";
  public void Configure(BackOfficeExternalLoginProviderOptions options) {
    var users = _config.GetSection("AllowedUsers").Get < List < string >> ();

    options.AutoLinkOptions = new ExternalSignInAutoLinkOptions(
    autoLinkExternalAccount: true, defaultUserGroups: new[] {
      "editor"
    },
    defaultCulture: null, allowManualLinking: false) {
      OnAutoLinking = (autoLinkUser, loginInfo) =>{
        autoLinkUser.IsApproved = users ? .Contains(autoLinkUser.Email ? ?string.Empty) ? ?false;
      },
      OnExternalLogin = (user, loginInfo) =>{
        return users ? .Contains(user.Email ? ?string.Empty) ? ?false;
      }
    };

    options.DenyLocalLogin = true;
  }
  public void Configure(string ? name, BackOfficeExternalLoginProviderOptions options) {
    if (name != Constants.Security.BackOfficeExternalAuthenticationTypePrefix + SchemeName) {
      return;
    }

    Configure(options);
  }
}         

\ExternalLoginProviders\umbraco-package.json

{
  "type": "authProvider",
  "alias": "My.AuthProvider.Generic",
  "name": "My Auth Provider",
  "forProviderName": "Umbraco.Microsoft",
  "meta": {
    "label": "Login",
    "defaultView": {
      "icon": "icon-cloud"
    },
    "behavior": {
      "autoRedirect": true
    },
    "linking": {
      "allowManualLinking": false
    }
  }
}

What I’m seeing in the logs:

Here’s a snippet of what shows up during the login delay:

AuthenticationScheme: "Identity.Application" was not authenticated.
AuthenticationScheme: "UmbracoExternalCookie" was not authenticated.
The external login authentication failed. No user Principal or authentication items was resolved.
Executing ChallengeResult with authentication schemes (["Umbraco.Microsoft"]).
AuthenticationScheme: "Umbraco.Microsoft" was challenged.
...
AuthenticationScheme: "UmbracoExternalCookie" signed in.
AuthenticationScheme: "UmbracoBackOffice" signed in.

So there are a bunch of failed attempts with Identity.Application, and some failed UmbracoExternalCookie logins, before things finally succeed. The long delay seems to match this period of retries/challenges.

What I’m trying to figure out:

  • Has anyone else run into long delays like this when using external login in Umbraco 16?

  • Any idea why the UmbracoExternalCookie or Identity.Application schemes would fail repeatedly before eventually signing in?

  • Could options.SaveTokens = true be affecting this?

  • Any tips on how to better debug what’s going on between the callback and the successful backoffice login?

I took a deeper look into what might be causing the delay after signing in with Microsoft on Umbraco 16, and I think I’ve narrowed it down.

It looks like the issue may be related to the ContentFinderByUrlAlias - specifically how it handles the /umbraco-signin-microsoft callback path. What I’m seeing is that Umbraco is iterating through every content node trying to resolve that path as a content URL alias. Since the site has a few thousand nodes, this results in a noticeable delay (sometimes 2–5 minutes) before the login process finishes and the backoffice loads.

Hey Kevin, welcome to the forum!

This behaviour sounds strange indeed.

If you add your callback path to the reserved URLs in app settings does the problem go away?

"ReservedUrls": "~/.well-known, /umbraco-signin-microsoft",

Without that setting I’d expect this to fail, rather than iterate all the nodes. This seems like a bug. I willl see if I can replicate the problem

@JasonElkin

Thanks — this worked well!

I did find that bypassing Umbraco’s routing would resolve the issue:

app.MapWhen(
    ctx => ctx.Request.Path.Equals("/umbraco-signin-microsoft", StringComparison.OrdinalIgnoreCase),
    branch =>
    {
        branch.UseAuthentication();
        branch.Run(_ => Task.CompletedTask); // do nothing – auth handler will already have redirected
    });

But the solution you suggested (adding the callback path to ReservedUrls) is cleaner and definitely the better long-term fix. Appreciate the help!

1 Like

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.