Skip to content

Conversation

@maliming
Copy link
Member

No description provided.

@duncansultan
Copy link

duncansultan commented Nov 4, 2025

@maliming
Your solution worked great for pagination.

I also have to make these changes to get login to work.

LinkLogin.cshtml.cs

using (CurrentTenant.Change(SourceLinkTenantId))
{
    var sourceUser = await UserManager.GetByIdAsync(SourceLinkUserId);
    using (CurrentPrincipalAccessor.Change(await SignInManager.CreateUserPrincipalAsync(sourceUser)))
    {
        // OPTIMIZATION: Use GetAllListAsync instead of IsLinkedAsync to avoid timeout with indirect links
        // GetAllListAsync uses batch retrieval (fixed in ABP PR #23929), while IsLinkedAsync uses slow iterative queries
        // This is the key performance improvement that prevents timeout issues
        var linkedUsers = await IdentityLinkUserAppService.GetAllListAsync();
        var isLinked = linkedUsers.Items.Any(x =>
            x.TargetUserId == TargetLinkUserId && x.TargetTenantId == TargetLinkTenantId);

        if (isLinked)
        {
        }
    }
}

CustomLinkLoginExtensionGrant.cs

/// <summary>
/// Custom link login extension grant for OpenIddict OAuth flows.
/// Extends ABP's default link login grant with optimized performance for linked account verification.
/// This override fixes timeout issues that occur with indirect linked accounts by using batch retrieval
/// instead of slow iterative database queries when validating account links.
/// </summary>
public class CustomLinkLoginExtensionGrant : LinkLoginExtensionGrant
{
   
      // ========== KEY OPTIMIZATION: Use batch retrieval instead of IsLinkedAsync ==========
      // ORIGINAL (slow): var isLinked = await identityLinkUserManager.IsLinkedAsync(...)
      // OPTIMIZED (fast): Use GetListAsync which uses batch retrieval from ABP PR #23929
      var linkedUsers = await identityLinkUserManager.GetListAsync(
          new IdentityLinkUserInfo(currentUser.GetId(), currentTenant.Id),
          includeIndirect: true);
      var isLinked = linkedUsers.Any(x =>
          (x.SourceUserId == linkUserId.Value && x.SourceTenantId == linkTenantId) ||
          (x.TargetUserId == linkUserId.Value && x.TargetTenantId == linkTenantId));
      // ================================================================================      
}

@maliming
Copy link
Member Author

maliming commented Nov 5, 2025

Thanks duncansultan

I will check your code. 👍

@maliming
Copy link
Member Author

maliming commented Nov 5, 2025

hi @duncansultan

After this PR, you will no longer need to change the LinkLogin and LinkLoginExtensionGrant values.

You can consider overriding the IdentityLinkUserManager based on this PR.

Thanks.

@maliming maliming marked this pull request as ready for review November 5, 2025 02:45
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants