Missing umbracoExternalLogin Data After Migration in Umbraco 13

While migrating from Nested Content to Block List in Umbraco 13, I ran into an unexpected issue with the umbracoExternalLogin table.
Everything in the migration went smoothly until I noticed that the table was empty in my local database copy.

The Cause

When I copied the database locally and ran the migration, I didn’t configure any external login providers.
In my appsettings.json, this section was blank:

"AzureAd": {
  "TenantId": "",
  "ClientId": "",
  "ClientSecret": ""
}


Because no providers were registered, Umbraco automatically removed all external login records.
This happens due to a cleanup process in ExternalLoginRepository and BackOfficeExternalLoginProviders.

Here’s the relevant part:

public void DeleteUserLoginsForRemovedProviders(IEnumerable<string> currentLoginProviders)
{
    Sql<ISqlContext> sql = Sql()
        .Select<ExternalLoginDto>(x => x.Id)
        .From<ExternalLoginDto>()
        .Where<ExternalLoginDto>(x => !x.LoginProvider.StartsWith(Constants.Security.MemberExternalAuthenticationTypePrefix))
        .WhereNotIn<ExternalLoginDto>(x => x.LoginProvider, currentLoginProviders);

    var toDelete = Database.Query<ExternalLoginDto>(sql).Select(x => x.Id).ToList();
    DeleteExternalLogins(toDelete);
}


This is called from InvalidateSessionsIfExternalLoginProvidersChanged():

public void InvalidateSessionsIfExternalLoginProvidersChanged()
{
    var previousExternalLoginProvidersValue = _keyValueService.GetValue(ExternalLoginProvidersKey);
    var currentExternalLoginProvidersValue = string.Join("|", _externalLogins.Keys.OrderBy(key => key));

    if ((previousExternalLoginProvidersValue ?? string.Empty) != currentExternalLoginProvidersValue)
    {
        _logger.LogWarning("The configured external login providers have changed. Existing backoffice sessions using the removed providers will be invalidated and external login data removed.");

        _userService.InvalidateSessionsForRemovedProviders(_externalLogins.Keys);
        _externalLoginWithKeyService.DeleteUserLoginsForRemovedProviders(_externalLogins.Keys);

        _keyValueService.SetValue(ExternalLoginProvidersKey, currentExternalLoginProvidersValue);
    }
}


So when Umbraco detects a change (or no provider at all), it assumes the old ones were removed and clears out related entries in umbracoExternalLogin.

This behavior was introduced in PR #19273
 and included in release 13.0.4
.

How to Avoid This

If you’re doing a local migration or testing a copy of your production database, make sure to configure your external login credentials, even if they’re dummy values.

Example:

"AzureAd": {
  "TenantId": "dummy-tenant-id",
  "ClientId": "dummy-client-id",
  "ClientSecret": "dummy-secret"
}

This prevents Umbraco from thinking the provider has been removed and keeps your umbracoExternalLogin records intact.

Final Tip

When working on upgrades or local migrations:

Always double-check your external login settings and other settings, and do not clear any tables you want to keep.

Keep a backup of the original database and compare it if any issues arise.

A small configuration detail, but one that can save you a lot of head-scratching.