Open Closed

Toolbar custom component and Authorization #7675


User avatar
1
roberto.fiocchi created
  • ABP Framework version: v8.2.1
  • UI Type: Blazor WASM
  • Database System: EF Core (SQL Server)
  • Tiered (for MVC) or Auth Server Separated (for Angular):
  • Exception message and full stack trace:
  • Steps to reproduce the issue:

Good morning,

I have a Blazor WASM project where I inserted a custom component in the toolbar, following this guide from the doc: https://abp.io/docs/latest/framework/ui/blazor/toolbars#example-add-a-notification-icon

The content of my custom component must be visible only after logging in and with a specific permission, because I need to make API calls when initializing the component, so I need to manage authentication and authorization. To do this I managed everything using the tag "AuthorizeView" (with Policy parameter as explained in the doc) and in the .razor.cs using the "CurrentUser.IsAuthenticated" and the "AuthorizationService.IsGrantedAsync...." inside the "OnInitializedAsync" method. My component code is as follows:

@using AbpSolution1.Books
@using AbpSolution1.Permissions
@using Microsoft.AspNetCore.Authorization
@inherits Volo.Abp.AspNetCore.Components.AbpComponentBase
@inject IBooksAppService BooksAppService

@* https://abp.io/docs/latest/framework/ui/blazor/authorization *@
<AuthorizeView Policy="@AbpSolution1Permissions.Books.Default">
    <Authorized>
        @if (IsAnyBook)
        {
            <div class="bg-success w-100 d-flex justify-content-center align-items-center h-100">
                <b class="text-dark" style="font-size: 20px;">
                    Books available
                </b>
            </div>
        }
        else
        {
            <div class="bg-warning w-100 d-flex justify-content-center align-items-center h-100">
                <b class="text-dark" style="font-size: 20px;">
                    No Books
                </b>
            </div>
        }
    </Authorized>
    <NotAuthorized>
        <div class="bg-danger w-100 d-flex justify-content-center align-items-center h-100">
            <b class="text-dark" style="font-size: 20px;">
                Not Authorized
            </b>
        </div>
    </NotAuthorized>
</AuthorizeView>

@code {

    private bool IsAnyBook { get; set; } = false;

    private async Task LoadBooks()
    {
        try
        {
            GetBooksInput input = new GetBooksInput();
            var books = await BooksAppService.GetListAsync(input);
            IsAnyBook = books.Items.Any();
        }
        catch(Exception ex)
        {
            await HandleErrorAsync(ex);
            Console.WriteLine(ex.Message);
        }
    }

    protected override async Task OnInitializedAsync()
    {
        await base.OnInitializedAsync();
        var isAutheticated = CurrentUser.IsAuthenticated;
        var isAuthorized = await AuthorizationService.IsGrantedAsync(AbpSolution1Permissions.Books.Default);

        if (isAutheticated && isAuthorized)
        {
            await LoadBooks();
        }
    }
}

However, when I log in and the component is rendered I get a 401 "Unauthorized" error, even if the logged in user has permission to make the call. It would appear that the call is made before obtaining the token.

How can I solve it? (if necessary we can attach the entire zipped project)

Thank you, best regards

Roberto


36 Answer(s)
  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Many thanks. 🙏

  • User Avatar
    0
    roberto.fiocchi created

    I published to Azure, but now I have a different behavior. https://abpsolution1.azurewebsites.net/

    When I log in it sees me as unauthorized and therefore does not call GetBooks for this reason now it does not go into error. Can you test it? Thanks

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    hi

    Try this

    @using AbpSolution1.Books
    @using AbpSolution1.Permissions
    @using Microsoft.AspNetCore.Authorization
    @using Volo.Abp.AspNetCore.Components.Web.Security
    @inherits Volo.Abp.AspNetCore.Components.AbpComponentBase
    @inject IBooksAppService BooksAppService
    @inject ApplicationConfigurationChangedService ApplicationConfigurationChangedService
    
    @if(IsAuthorized)
    {
        if (IsAnyBook)
        {
            <div class="bg-success w-100 d-flex justify-content-center align-items-center h-100">
                <b class="text-dark">
                    Books available
                </b>
            </div>
        }
        else
        {
            <div class="bg-warning w-100 d-flex justify-content-center align-items-center h-100">
                <b class="text-dark">
                    No Books
                </b>
            </div>
        }
    }
    else
    {
         <div class="bg-danger w-100 d-flex justify-content-center align-items-center h-100">
            <b class="text-dark">
                Not Authorized
            </b>
        </div>
    }
    
    @code {
    
        private bool IsAuthorized { get; set; } = false;
    
        private bool IsAnyBook { get; set; } = false;
    
        private async Task LoadBooks()
        {
            try
            {
                GetBooksInput input = new GetBooksInput();
                var books = await BooksAppService.GetListAsync(input);
                IsAnyBook = books.Items.Any();
            }
            catch(Exception ex)
            {
                await HandleErrorAsync(ex);
                Console.WriteLine(ex.Message);
            }
        }
    
        protected override async Task OnInitializedAsync()
        {
            await base.OnInitializedAsync();
    
            ApplicationConfigurationChangedService.Changed += ApplicationConfigurationChanged;
    
            await InitComponentAsync();
        }
    
        private async Task InitComponentAsync()
        {
            var isAutheticated = CurrentUser.IsAuthenticated;
            IsAuthorized = await AuthorizationService.IsGrantedAsync(AbpSolution1Permissions.Books.Default);
    
            if (isAutheticated && IsAuthorized)
            {
                await LoadBooks();
            }
        }
    
        private async void ApplicationConfigurationChanged()
        {
            await InitComponentAsync();
            await InvokeAsync(StateHasChanged);
        }
    
    }
    
    
  • User Avatar
    0
    roberto.fiocchi created

    I published to Azure. The component is displayed and after one second from login it changes its state.

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    ok, Does it slove your problem?

  • User Avatar
    0
    roberto.fiocchi created

    It's an acceptable workaround. If I have other problems I will open a new ticket. Thanks

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    : )

  • User Avatar
    0
    roberto.fiocchi created

    Sorry, one last question. Since it is done: ApplicationConfigurationChangedService.Changed += ApplicationConfigurationChanged;

    I should make a Dispose method with: ApplicationConfigurationChangedService.Changed -= ApplicationConfigurationChanged;

    What is the correct way to write the Dispose method of the component?

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    Yes, Inherit IDisposable and add Dispose method.

    public void Dispose()
    {
        ApplicationConfigurationChangedService.Changed -= ApplicationConfigurationChanged;
    }
    
  • User Avatar
    0
    roberto.fiocchi created

    Ok, thanks

  • User Avatar
    0
    maliming created
    Support Team Fullstack Developer

    : )

Made with ❤️ on ABP v9.1.0-preview. Updated on November 19, 2024, 10:33