Search code examples
c#authorizationblazorblazor-webassembly

Blazor wasm - where to check user privileges


Using a Blazor Web-Assembly web app with asp.net server, I would like to filter what forms/input a user can see/change/use. I.e. an anonymous or logged in user without privileges may not view or modify a select form (combobox). The page shows information about a specific area (the same page is used for different areas but uses input in the url to specify area). If the user has no privileges only a basic view should be allowed. If the user is from the area (area claim value) and has an "elevated" role a more advanced view is shown. It works fine if all I want to check is the user Role is for example "Admin":

<AuthorizeView Roles="Admin">
    <Authorized>
        <div class="input-group">
            <div class="input-group-prepend">
                <span class="input-group-text">Secret choise:</span>
            </div>
            <select @bind="Choise">
                <option value=A>A</option>
                <option value=B>B</option>
            </select>
        </div>
    </Authorized>
</AuthorizeView>

But the combination of Role and "area" claim compared to variable values seems to require more code... using razor.cs code to call the server:

private async Task CheckUserViewPriveligesViaServer()
{
    var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
    var user = authState.User;

    if (user.Identity.IsAuthenticated)
    {
        var claims = user.Claims;
        var userID = user.FindFirst(c => c.Type == "sub")?.Value;
        UserSiteDTO userSiteDTO = new UserArea() { AreaID = _area.ID, UserID = userID };
        try
        {
            var canUserViewSensitiveInformation = await UsersReposotory.IsUserElevatedAndFromArea(userSiteDTO); // calls asp.net server
            if (canUserViewSensitiveInformation)
            {
                _viewPriveliges = ViewPriveliges.AreaAdmin;
            }
            else
            {
                _viewPriveliges = ViewPriveliges.None;
            }
        }
        catch (Exception)
        {

            _viewPriveliges = ViewPriveliges.None;
            Console.WriteLine("Unable to get user priveliges");
        }
    }
    else
    {
        _viewPriveliges = ViewPriveliges.None;
    }
}

and on the server:

[HttpPost("isUserElevatedAndFromArea")]
public async Task<ActionResult<bool>> IsUserElevatedAndFromArea(UserSiteDTO userDTO)
{
    if (string.IsNullOrWhiteSpace(userDTO.AreaID) 
        || string.IsNullOrWhiteSpace(userDTO.UserID))
    {
        return false;
    }
    var user = await _userManager.FindByIdAsync(userDTO.UserID);
    var claims = await _userManager.GetClaimsAsync(user);
    var areaOk = false;
    var adminOk = false;
    foreach (var c in claims)
    {
        if (c.Type == "AreaID")
        {
            if (!string.IsNullOrWhiteSpace(c.Value) && c.Value == userDTO.AreaID )
            {
                areaOk = true;
            }
        }
        if (c.Type == "AreaAdmin")
        {
            if (!string.IsNullOrWhiteSpace(c.Value) || c.Value == "Yes")
            {
                adminOk = true;
            }
        }
    }
    return areaOk && adminOk;
}

coupled with an if statement in the razor code:

@if (_viewPriveliges == ViewPriveliges.AreaAdmin)
{
    <div class="input-group">
        <div class="input-group-prepend">
            <span class="input-group-text">Secret choise:</span>
        </div>
        <select @bind="Choise">
            <option value=A>A</option>
            <option value=B>B</option>
        </select>
    </div>
}

The other option would be to "bake" the server code into the razor.cs code to run the checks in webassembly.

So, my question is if it is "ok" safety wise to check this information in the code (webassembly in the browser) for the page or if this should be done by calling the server through a http get/post call??


Solution

  • No its not safe in a browser. Browser should only see what the client has privileges for. Also the hardware of a client is really unknown so the performance ability to do sorting and filtering of data is questionable.