Open Closed

Basic theme: "Back to my account" (impersonation) fails with OpenIddict ID2029 — can it use a POST request? #10712


User avatar
0
pareeks@gccontractor.org created

Problem: After impersonating a user, clicking "Back to my account" in the user dropdown navigates to /Account/BackToImpersonator and fails with:

Analysis: ABP's AccountBlazorUserMenuContributor adds the Account.BackToImpersonator menu item with a GET URL and attaches ImpersonationComponent (a JS-submitted POST <form>) via UseComponent(). The LeptonX theme renders that attached component, so the POST works — OpenIddictImpersonateInferEndpointType hands form-POST requests to BackToImpersonatorModel.OnPostAsync (cookie re-sign-in). But the Basic theme renders user-menu items as plain GET <a href> links and ignores the attached component. So the click issues a GET to /Account/BackToImpersonator, which the embedded OpenIddict server treats as an authorization request requiring a client_id → ID2029.

Question: Is there a supported/built-in option to make "Back to my account" menu item work under the Basic theme so it submits as POST to /Account/BackToImpersonator?

Markdown supported.
Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)

3 Answer(s)
  • User Avatar
    0
    AI-Bot created
    Support Team ABP Agent
    • There is no built-in switch/option in the Basic theme that changes the user-menu rendering so that the built-in “Back to my account” item (which is designed to work via an attached component that submits a POST form) is automatically honored. In the Basic theme, the user menu is rendered as plain links, so a click becomes a GET to /Account/BackToImpersonator, which can trigger the OpenIddict ID2029 behavior you observed.

    • The supported way to make this work in Basic theme is to override how that menu item is rendered (i.e., render a component / custom markup that submits a POST form) using ABP’s “menu item component” customization.

      • Concretely: remove/replace the default Account.BackToImpersonator item in your menu contributor and re-add it as a custom ApplicationMenuItem(...).UseComponent(...) that renders a small <form method="post" action="/Account/BackToImpersonator">...</form> and submits it on click (the same idea LeptonX uses via the attached ImpersonationComponent).
      • This keeps the server-side ABP/OpenIddict impersonation endpoints untouched and fixes the theme rendering mismatch.
    • If you don’t want a custom component, the only other reliable approach is to override the Basic theme’s user-menu component/template so it actually renders menuItem.Component (if provided) instead of always emitting <a href="...">.

    (Validated) https://abp.io/docs/latest/framework/ui/blazor/basic-theme


    This response was generated by AI. If it didn’t solve your problem, feel free to post a new answer — our support team will jump in to help you soon.

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    pareeks@gccontractor.org created

    Need more assistance. It did not work

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Hi,

    You're right, this is a Basic theme bug — its LoginDisplay renders every user-menu item as a plain <a href> and ignores the component attached via UseComponent(...), so the ImpersonationComponent (POST form) never gets rendered and the click hits OpenIddict as a GET → ID2029.

    Until the fix ships, you can replace the toolbar item with your own. Add MyLoginDisplay.razor to your Blazor project:

    @using Blazorise
    @using Microsoft.AspNetCore.Components.Authorization
    @using Microsoft.AspNetCore.Components.Routing
    @using Microsoft.Extensions.Localization
    @using global::Localization.Resources.AbpUi
    @using Volo.Abp.MultiTenancy
    @using Volo.Abp.UI.Navigation
    @using Volo.Abp.Users
    @implements IDisposable
    @inject IMenuManager MenuManager
    @inject ICurrentUser CurrentUser
    @inject ICurrentTenant CurrentTenant
    @inject IStringLocalizer<AbpUiResource> L
    @inject NavigationManager Navigation
    
    <AuthorizeView>
        <Authorized>
            <Dropdown EndAligned="true">
                <DropdownToggle Color="Color.Default">
                    @if (CurrentTenant.Name != null)
                    {
                        <span><i>@CurrentTenant.Name</i>\@CurrentUser.UserName</span>
                    }
                    else
                    {
                        <span>@CurrentUser.UserName</span>
                    }
                </DropdownToggle>
                <DropdownMenu>
                    @if (Menu != null)
                    {
                        @foreach (var menuItem in Menu.Items)
                        {
                            var componentType = menuItem.GetComponentTypeOrDefault();
                            if (componentType != null)
                            {
                                <DynamicComponent Type="@componentType" />
                            }
                            else
                            {
                                <a class="dropdown-item" href="@menuItem.Url?.TrimStart('/', '~')" target="@menuItem.Target">@menuItem.DisplayName</a>
                            }
                        }
                    }
                </DropdownMenu>
            </Dropdown>
        </Authorized>
        <NotAuthorized>
            <a class="nav-link" href="Account/Login">@L["Login"]</a>
        </NotAuthorized>
    </AuthorizeView>
    
    @code {
        private ApplicationMenu? Menu;
    
        protected override async Task OnInitializedAsync()
        {
            Menu = await MenuManager.GetAsync(StandardMenus.User);
            Navigation.LocationChanged += OnLocationChanged;
        }
    
        private void OnLocationChanged(object? sender, LocationChangedEventArgs e)
            => InvokeAsync(StateHasChanged);
    
        public void Dispose() => Navigation.LocationChanged -= OnLocationChanged;
    }
    

    Then a contributor to swap it in:

    using System.Threading.Tasks;
    using Volo.Abp.AspNetCore.Components.Server.BasicTheme.Themes.Basic;
    using Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars;
    
    public class CustomLoginDisplayContributor : IToolbarContributor
    {
        public Task ConfigureToolbarAsync(IToolbarConfigurationContext context)
        {
            if (context.Toolbar.Name == StandardToolbars.Main)
            {
                context.Toolbar.Items.RemoveAll(x => x.ComponentType == typeof(LoginDisplay));
                context.Toolbar.Items.Add(new ToolbarItem(typeof(MyLoginDisplay)));
            }
    
            return Task.CompletedTask;
        }
    }
    

    Register it in your Blazor module's ConfigureServices:

    Configure<Volo.Abp.AspNetCore.Components.Web.Theming.Toolbars.AbpToolbarOptions>(options =>
    {
        options.Contributors.Add(new CustomLoginDisplayContributor());
    });
    

    We'll fix Basic theme itself in v10.4.2 so the workaround isn't needed.

    Thanks

    Markdown supported.
    Copy, paste, or drag & drop images and files (max 100 MB per file, 100 MB total per post)
Boost Your Development
ABP Live Training
Packages
See Trainings
Mastering ABP Framework Book
The Official Guide
Mastering
ABP Framework
Learn More
Mastering ABP Framework Book
Made with ❤️ on ABP v10.8.0-preview. Updated on September 09, 2026, 11:56
1
ABP Assistant
🔐 You need to be logged in to use the chatbot. Please log in first.