ASP.NET Core Identity

Radzen Blazor Studio allows you to easily add security based on ASP.NET Core Identity to your Blazor application. A mandatory requirement is an existing database connection - MSSQL, Oracle, MySQL or Postgres.

How-to video

Add security

To add ASP.NET Core Identity security to your app:

  1. Click the Add security button just above file explorer. This starts the Add Security wizard.
  2. Pick ASP.NET Core Identity from the available options (it should be selected by default). Click Next.
  3. Pick an existing database connection in the Configure security wizard step (the first available should be already selected).
  4. Choose whether to allow password reset and user registration. Both options require an email server so you will be asked to enter the details.

Add ASP.NET Core Identity security to a Blazor application

Specify page access

When security is enabled Radzen Blazor Studio will allow you to specify which users can access a page. If a user doesn’t have access to certain page it will not appear in the application navigation. If the user enters that page URL manually in the browser they will see a generated unauthorized page.

By default pages created in Radzen Blazor Studio allow access to Everyone - both authenticated and anonymous users.

To specify who can access a page:

  1. Open the page in design mode.
  2. Make sure no component is selected (which is by default). If there is a selected component click in an empty space in the page designer.
  3. Pick Authenticated from the Access property editor to allow only authenticated users to view this page (users that have logged in).
  4. Optionally pick a role from the dropdown. Only members of that role would have access to that page.

Specify who can view a page

The code generated for this example is:

@attribute [Authorize(Roles="Administrator")]

To specify multiple roles via code separate them with a comma: @attribute [Authorize(Roles="Role1,Role2")].

If multiple roles are specified a member of either role can view the page.

Important: Do not remove the Anonymous access from the Login page. If you do that your users won’t be able to log in.

Development security

During development you can use a special account for testing. Log in with admin as both username and password. This account is available only during development (when the ASPNETCORE_ENVIRONMENT environment variable is set to Development). The test admin account belongs to all roles defined in the application and has full access as a result.

Important: After deployment the admin account is no longer available! Be sure to either allow user registration or create at least one user account during development.

Add roles

An authorized user can add roles from the Roles page accessible from the top-right application menu.

Add roles in a Blazor application

By default all authenticated users have access to the role management pages. Make sure you restrict the access to those pages before deploying to a production environment. Create an Administrator role and allow only member of this role to access the role management pages.

Add users

A Blazor application created by Radzen Blazor Stydio starts with no users apart from the development-only admin account mentioned above.

There are two ways to add users to an application

  1. Enable user registration while adding ASP.NET Core Identity security to your application.
  2. An authorized user can add users from the Users page accessible from the top-right application menu.

Add roles in a Blazor application

By default all authenticated users have access to the user management pages. Make sure you restrict the access to those pages before deploying to a production environment. Create an Administrator role and allow only member of this role to access the role management pages.

Secure controllers

Radzen Blazor Studio applications use various controllers to access data over HTTP - AccountController for login, registration, ApplicationUsersController and ApplicationRolesController to manage users and roles. Blazor WASM expose a database as a OData controller. By default only ApplicationRolesController and ApplicationUsersController disallow anonymous access.

To require authorized access you need to decorate the controllers with the Authorize attribute.

Allow authenticated users

To disable anonymous access and allow any logged-in user edit the controller code and add [Authorize] before the class declaration.

/* snip */
using Microsoft.AspNetCore.Authorization;

namespace [Namespace].Server.Controllers.[Database]
{
    [Authorize] // -> Allow any authenticated user. Disallow anonymous access.
    [Route("odata/Northwind/Orders")]
    public partial class OrdersController : ODataController
    {
      /* snip */
    }
}

Important: Do not add the Authorize attribute to the AccountController class as it will effectively disable login and registration.

Allow specific roles

To allow only certain roles specify the Roles property during decoration:

/* snip */
using Microsoft.AspNetCore.Authorization;
namespace [Namespace].Server.Controllers.[Database]
{
    [Authorize(Roles="Administrator,Sales")] // -> Allow only members of the Administrator or Sales role
    [Route("odata/Northwind/Orders")]
    public partial class OrdersController : ODataController
    {
      /* snip */
    }
}

Apply authorization globally

Instead of adding the Authorize attribute to every controller you can apply a global filter policy to all routes in the applications.

  1. Open Program.cs or Server\Program.cs (WASM).
  2. Import the following namespaces.
    using Microsoft.AspNetCore.Mvc;
    using Microsoft.AspNetCore.Authorization;
    
  3. Add this code just before var app = builder.Build();

    builder.Services.Configure<MvcOptions>(options =>
    {
        var policy = new AuthorizationPolicyBuilder()
            .AddAuthenticationSchemes(IdentityConstants.ApplicationScheme)
            .RequireAuthenticatedUser();
            .Build();
        options.Filters.Add(new [Namespace].Filters.ApplicationAuthorizeFilter(policy));
    });
    

The ApplicationAuthorizeFilter allows anonymous access only to AccountController and the Login page.

public class ApplicationAuthorizeFilter : AuthorizeFilter
{
    public ApplicationAuthorizeFilter(AuthorizationPolicy policy): base(policy)
    {
    }

    public override Task OnAuthorizationAsync(AuthorizationFilterContext context)
    {
        if (context.HttpContext.Request.Path.StartsWithSegments("/Account") || context.HttpContext.Request.Path.StartsWithSegments("/Login"))
        {
            return Task.CompletedTask;
        }

        return base.OnAuthorizationAsync(context);
    }
}

API

Radzen Blazor Studio generates a service called SecurityService and makes it available in all pages as the Security property. This service allows you to:

Get the current user

The User property is an instance of the ApplicationUser class.

var name = Security.User.Name;

Check if a user is a member of a role

The IsInRole method checks if the current user is a member of the specified role(s).

var isAdmin = Security.IsInRole("Administrator");
var isUserOrAdministartor = Security.IsInRole("Administrator", "User");

Check if the user is authenticated

The IsAuthenticated method checks if the current user is authenticated (has logged in).

var isAuthenticated = Security.IsAuthenticated();

Logout the current user

The Logout method redirects to the /Account/Logout action which logs the current user out and redirects to the login page.

Security.Logout();

Two-factor email authentication

Two-factor authentication provides an extra layer of security by sending a one-time code to the user email after login. The user must enter the code in order to complete the login.

Enable two-factor email authentication

You can enable two-factor email authentication from the Identity security settings. A working email server configuration is required.

Enable two-factor email authentication Two-factor email authentication

Important: Two-factor authentication is enabled per user during login and is persisted in the AspNetUsers table. This means that users who have logged in via two-factor authentication would still need it even if you later decide to turn that option off for your application. You can use the userManager.SetTwoFactorEnabledAsync() method to enable or disable two-factor authentication per user in AccountController.cs:

await userManager.SetTwoFactorEnabledAsync(user, true /* false */);

You can change the two-factor email contents by editing AccountController.cs.

Checklist

Before deploying your Blazor application that has ASP.NET Core Identity security enabled make sure that:

  1. You have created the required roles.
  2. You have either created some users or enabled user registration.
  3. You have allowed access to the user and role management pages only to a specific role.
  4. You have disabled anonymous access to sensitive controllers.

Troubleshooting

The user is always redirected to the login page in production

This could happen if:

  • Your production server does not have a SSL certificate installed or it is not valid (expired, misconfigured etc).
  • The application is accessed over http and your server isn’t configured to redirect automatically to https.

The login may still work as expected during development as it relies on the development SSL certificate installed by the .NET runtime or Visual Studio.

The user is always redirected to the login page in development

This would happen if there isn’t a valid development certificate installed. You may also see the following exception:

The ASP.NET Core developer certificate is not trusted

Follow the official Microsoft documentation for further instructions.

The login page is never displayed because of a redirect loop

This would happen if the Login page does not have anonymous access - the Access property must be set to Everyone and it should not contain code such as @attribute [Authorize].

The admin account is missing in production

The admin account is available during development only. Make sure you have created some users or enabled user registration before deploying your application.