Working with authentication and identity in Blazor.

Authentication

Blazor uses the existing ASP.NET Core authentication mechanisms to establish the user’s identity. The exact mechanism depends on how the Blazor app is hosted, server-side or client-side.

Blazor client-side authentication

In Blazor client-side apps, authentication checks can be bypassed because all client-side code can be modified by users. The same is true for all client-side app technologies, including JavaScript SPA frameworks or native apps for any operating system.

Implementation of a custom AuthenticationStateProvider service for Blazor client-side apps is covered in the following sections.

Blazor server-side authentication

Blazor server-side apps operate over a real-time connection that’s created using SignalR. Authentication in SignalR-based apps is handled when the connection is established. Authentication can be based on a cookie or some other bearer token.

The Blazor server-side project template can set up authentication for you when the project is created.

Expose the authentication state as a cascading parameter

We can use the cascading parameters AuthenticationState provided by the <AuthorizeView> or the <CascadingAuthenticationState> to if the user is log in, this is perfect if we need to know if the user is logged in order to apply the correct component logic. In this example I use the cascading parameter in the NavBar, so that I can show some NavLink to authorize users only.

Authorization

Once the user is authenticated, the authorization rules are applied this will control what the user can do. Access is granted or denied based on whether:

  • A user is authenticated (signed in).
  • A user is in a role.
  • A user has a claim.
  • policy is satisfied.

For a more in deep on those concept here is a link to the official documentation.

AuthorizeView component

Now you don’t need to always declare the cascading parameter in order to know if the user is authorized, you can use AuthorizeView, it will selectively display UI depending on whether the user is authorized to see it. This approach works wonders when you want to show some data to logged in user but don’t need the user’s identity.

Here are some samples:

UnAuthorized:

Authorized:

You can notice that you can include arbitrary items like other interactive components. <Authorized> and <NotAuthorized> get routed based on the Authorization conditions, such ahs roles, or policies. By default, if conditions aren’t specified, the AuthorizeView will use the default policy and treats:

  • Authenticated (signed-in) users as authorized.
  • Unauthenticated (signed-out) users as unauthorized.

Role-Based and Policy-Based Authorization

If you ant to use Role-based and policy-based authorization is has easy has using the parameters, here are some examples:

Role-Based:

Policy-Based:

Claim-Based:

Claims-based authorization is a special case of policy-based authorization.

Content Displayed During Asynchronous Authentication

The primary scenario for this approach is in Blazor client-side apps that make a request to an external endpoint for authentication. Blazor allows for authentication state to be determined asynchronously. The AuthorizeView display no content by default, if you want to display a custom message you can use <authorizing> this will display only when the authentication state is being determined. This can be use in Server-Side apps but since the apps know the authentication state as soon as the state is established it will never be display.

[Authorize] attribute

Like [Inject] attribute [Authorize] can also be used with Razor Components.
Note: You may need to add @using Microsoft.AspNetCore.Authorization either to the component or to the _Imports.razor file in order for the component to compile.

The attribute support role-based and policy-based authorization:

Role-Based:

Policy-Based:

Here’s what the user will see:

Authorized user

Not authorized user

Customize Unauthorized Content With the Router Component

Blazor Router component allows the app to specify custom content if:

  • Content isn’t found.
  • The user fails an [Authorize] condition applied to the component. The [Authorize] attribute is covered in the [Authorize] attribute section.
  • Asynchronous authentication is in progress.

All this is in App.razor file of our project:

<CascadingAuthenticationState>
    <Router AppAssembly="typeof(Startup).Assembly">
        <NotFoundContent>
            <h1>Sorry</h1>
            <p>Sorry, there's nothing at this address.</p>
        </NotFoundContent>
        <NotAuthorizedContent>
            <h1>Sorry</h1>
            <p>You're not authorized to reach this page.</p>
            <p>You may need to log in as a different user.</p>
        </NotAuthorizedContent>
        <AuthorizingContent>
            <h1>Authentication in progress</h1>
            <p>Only visible while authentication is in progress.</p>
        </AuthorizingContent>
    </Router>
</CascadingAuthenticationState> 

Note: In ASP.NET Core 3.0 Preview 6, it’s not possible to specify custom NotAuthorizedContent or AuthorizingContent on the Router component with server-side Blazor (though it does work with client-side Blazor). This will be fixed in the Preview 7 release.

Notification About Authentication State Changes

If the app determines that the underlying authentication state data has changed (for example, because the user signed out or another user has changed their roles), a custom AuthenticationStateProvider can optionally invoke the method NotifyAuthenticationStateChanged on the AuthenticationStateProvider base class. This notifies consumers of the authentication state data (for example, AuthorizeView) to re-render using the new data.

Authorization in Blazor Client-Side Apps

In Blazor client-side apps, authorization checks can be bypassed because all client-side code can be modified by users. The same is true for all client-side app technologies, including JavaScript SPA frameworks or native apps for any operating system.

Note: Always perform authorization checks on the server within any API endpoints accessed by your client-side app.

Custom AuthenticationStateProvider Service

If your using Blazor Client-Side implementing a custom authentication state provider will be a must, Client-Side Blazor suffers from the “client-side curse” frameworks like Angular, React and Blazorclient-side have the downside of having the code on the user machine, this bring the potential that the user could modified the code and bypass the authentication, to prevent this is recommended that you call a API to check if the user is authenticated.

You can create a custom provider that implements and override the AuthenticationStateProvider GetAuthenticationStateAsync:

Once we create our own custom authentication state provider we add it to DI container:

In our example all our user’s username will be replace with ‘NativoUser’

Blazor give you the oportunity to integrate security ad authentication to your web application a seamless way. If you want to dig deeper on ahutentication and authorization I will leave you the link to Microsoft ASP.NET Core Identity documentation. Put your new learn skills to the test and try it yourself, if you experience any problems post it in the comments and I will try to help you. See ya on the next post, keep Blazing!