LoginSignup
0
0

More than 1 year has passed since last update.

作成中 Blazor Server アプリに Basic 認証機能を追加する

Last updated at Posted at 2023-05-10

To implement authentication in a .NET Blazor server web app under the specified conditions (Safari browser, deployed in IIS with Basic Authentication enabled), you can follow these steps:

  1. Configure IIS for Basic Authentication:

    • Open Internet Information Services (IIS) Manager.
    • Select your application in the Sites tree on the left.
    • Double-click the "Authentication" feature.
    • Disable Windows Authentication and any other authentication methods except Basic Authentication.
    • Ensure Basic Authentication is enabled.
  2. Open the Startup.cs file in your Blazor server project.

  3. In the ConfigureServices method, add the following code to enable authentication:

using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.DependencyInjection;

public void ConfigureServices(IServiceCollection services)
{
    services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
        .AddCookie(options =>
        {
            options.Cookie.HttpOnly = true;
            options.ExpireTimeSpan = TimeSpan.FromMinutes(60); // Set the expiration time as desired
            options.SlidingExpiration = true;
        });

    services.AddAuthorization(options =>
    {
        options.DefaultPolicy = new AuthorizationPolicyBuilder()
            .RequireAuthenticatedUser()
            .Build();
    });

    services.AddRazorPages();
    services.AddServerSideBlazor();
}
  1. In the Configure method, add the following code to configure the pipeline:
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
    // ...

    app.UseAuthentication();
    app.UseAuthorization();

    app.UseStaticFiles();

    app.UseRouting();

    app.UseEndpoints(endpoints =>
    {
        endpoints.MapRazorPages();
        endpoints.MapBlazorHub();
        endpoints.MapFallbackToPage("/_Host");
    });

    // ...
}
  1. Add authentication support to a Blazor component/page:
    For example, let's protect a component called MyProtectedComponent:
  • In the MyProtectedComponent.razor file, add the following code at the top:
@attribute [Authorize]
@page "/protectedpage"

<h3>Protected Page</h3>

<p>This page requires authentication to access.</p>
  • This Authorize attribute will require the user to be authenticated to access MyProtectedComponent.
  1. Test the authentication:
    Deploy your Blazor app to IIS and access it from Safari. When accessing the protected MyProtectedComponent, the app should prompt for basic authentication credentials. Upon successful authentication, the user should be able to access the protected component.

Note: It's important to configure the authentication and authorization settings based on your specific requirements and security considerations. The example provided above demonstrates a basic implementation using Basic Authentication and protecting a specific component/page.

Add authorization for users who are in a specific security group in AD

You can add the feature of authorization for users who are in a specific security group in Active Directory (AD) to your Blazor server app while still using Basic authentication. Here's how you can implement this:

  1. Configure your Blazor app for AD authentication:

    • Follow the steps mentioned earlier to enable Basic authentication in your app as described in the previous responses.
  2. Add the necessary packages:

    • Install the System.DirectoryServices.AccountManagement NuGet package in your project. This package provides the required APIs to work with AD.
  3. Update the ConfigureServices method in the Startup.cs file:

    • Import the required namespaces:

      using System.DirectoryServices.AccountManagement;
      
    • Update the ConfigureServices method as follows:

      public void ConfigureServices(IServiceCollection services)
      {
          services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
              .AddCookie(options =>
              {
                  options.Cookie.HttpOnly = true;
                  options.ExpireTimeSpan = TimeSpan.FromMinutes(60); // Set the expiration time as desired
                  options.SlidingExpiration = true;
              });
      
          services.AddAuthorization(options =>
          {
              options.DefaultPolicy = new AuthorizationPolicyBuilder()
                  .RequireAuthenticatedUser()
                  .RequireRole("YourSecurityGroup") // Replace with the name of your specific security group in AD
                  .Build();
          });
      
          services.AddRazorPages();
          services.AddServerSideBlazor();
      }
      
    • In the RequireRole method, specify the name of the security group in AD that you want to restrict access to. Replace "YourSecurityGroup" with the actual name of your security group.

  4. Test the authorization:

    • Deploy your Blazor app to IIS with Basic authentication enabled.
    • When users access the app and provide their credentials through Basic authentication, the app will authenticate them.
    • Additionally, the app will check if the authenticated user belongs to the specified security group in AD (the group name you provided in the RequireRole method).
    • Only users who are both authenticated and in the specified security group will be authorized to access the protected pages/components.

With these steps, you can enforce authorization for only users who are in a specific security group in AD, while still using Basic authentication for authentication.

Retrieve authorized user's name

To retrieve the authorized user's information, such as surname and given name, and display it in your Blazor server app in Japanese (Chinese characters), you can utilize the System.DirectoryServices.AccountManagement namespace and the UserPrincipal class. Here's how you can modify your code to achieve this:

  1. Update the ConfigureServices method in the Startup.cs file:

    • Import the required namespaces:

      using System.DirectoryServices.AccountManagement;
      using System.Threading.Tasks;
      
    • Update the ConfigureServices method as follows:

      public void ConfigureServices(IServiceCollection services)
      {
          services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
              .AddCookie(options =>
              {
                  options.Cookie.HttpOnly = true;
                  options.ExpireTimeSpan = TimeSpan.FromMinutes(60); // Set the expiration time as desired
                  options.SlidingExpiration = true;
                  options.Events = new CookieAuthenticationEvents
                  {
                      OnSigningIn = async context =>
                      {
                          // Retrieve the user's AD information
                          var userPrincipal = await GetUserPrincipalAsync(context.Principal.Identity.Name);
                          if (userPrincipal != null)
                          {
                              // Set the user's surname and given name as claims
                              context.Principal.Identities.First().AddClaim(new Claim("Surname", userPrincipal.Surname));
                              context.Principal.Identities.First().AddClaim(new Claim("GivenName", userPrincipal.GivenName));
                          }
                      }
                  };
              });
      
          services.AddAuthorization(options =>
          {
              options.DefaultPolicy = new AuthorizationPolicyBuilder()
                  .RequireAuthenticatedUser()
                  .RequireRole("YourSecurityGroup") // Replace with the name of your specific security group in AD
                  .Build();
          });
      
          services.AddRazorPages();
          services.AddServerSideBlazor();
      }
      
    • In the code above, we have added an OnSigningIn event handler to the CookieAuthenticationOptions. This event is triggered when a user signs in successfully.

    • Inside the event handler, the GetUserPrincipalAsync method is called to retrieve the user's AD information.

    • If the user information is obtained successfully, it is added as claims to the user's principal object.

  2. Implement the GetUserPrincipalAsync method:

    • Add the following method to your Startup.cs file:

      private async Task<UserPrincipal> GetUserPrincipalAsync(string username)
      {
          using (var context = new PrincipalContext(ContextType.Domain))
          {
              var userPrincipal = await Task.Run(() => UserPrincipal.FindByIdentity(context, IdentityType.SamAccountName, username));
              return userPrincipal;
          }
      }
      
    • This method uses the UserPrincipal class to retrieve the user's AD information based on the provided username (SAM Account Name).

  3. Access the user's information in your Blazor component or page:

    • In the Blazor component or page where you want to display the user's information, you can inject the AuthenticationStateProvider service and retrieve the claims. For example:

      @inject AuthenticationStateProvider AuthenticationStateProvider
      
      <p>Welcome, @DisplayName</p>
      
      @code {
          private string DisplayName { get; set; }
      
          protected override async Task OnInitializedAsync()
          {
              var authenticationState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
              var user = authenticationState.User;
      
              DisplayName = user.FindFirstValue("Surname") + " " + user.FindFirstValue("GivenName");
          }
      }
      
    • In the example above, the AuthenticationStateProvider service is injected, and the user's claims for surname and given name are retrieved using the user.FindFirstValue method and then displayed in the component.

Cascade the retrieved user info

By following these steps, you can retrieve the authorized user's information from AD, such as surname and given name, and display it in your Blazor server app using Basic authentication. The retrieved information will be in Japanese (Chinese characters) since AD supports multilingual attributes.

Yes, it is possible to include the code snippet in the default MainLayout.razor file and use the retrieved surname and given name as cascading parameters in other Razor files. Here's an example:

In the MainLayout.razor file:

@inherits LayoutComponentBase
@inject AuthenticationStateProvider AuthenticationStateProvider

<CascadingValue Value="userName" Name="UserName">
    @Body
</CascadingValue>
@code {
    private string userName;

    protected override async Task OnInitializedAsync()
    {
        var authenticationState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
        if (authenticationState != null && authenticationState.User.Identity.IsAuthenticated)
        { 
            var user = authenticationState.User;
            var surname = user.FindFirstValue("Surname");
            var givenName = user.FindFirstValue("GivenName");
            userName = $"{surname} {givenName}";     
        }
    }
}

In this example, the MainLayout.razor component injects the UserService and AuthenticationStateProvider. During the initialization (OnInitializedAsync method), the user's surname and given name are retrieved from the authentication state and stored in the UserService properties (Surname and GivenName).

The Surname and GivenName values are then cascaded down to child components using the CascadingValue component. Child components can access these values as cascading parameters.

In other Razor components/pages where you want to use the cascaded surname and given name, you can define the cascading parameters like this:

@code {
    [CascadingParameter(Name = "userName")]
    public string userName { get; set; }
}

Now, within these components/pages, you can directly access the Surname and GivenName properties, which will hold the cascaded values from the MainLayout component.

Note: Make sure to inject the UserService in the MainLayout.razor file and define the Surname and GivenName properties as public properties in the UserService class for them to be accessible as cascading values.

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0