Membuat Boilerplate Aplikasi Web Dengan Menggunakan ASP.NET Core - Bagian 2

16 Mei 2024

Tutorial ini terdiri dari lima bagian.

Authorization adalah proses untuk melakukan cek hak akses user untuk menentukan apakah user bisa mengakses bagian-bagian yang ada pada aplikasi. Contoh yang sering biasanya teman-teman temui adalah user yang mempunyai role seperi Admin dan User. Kedua role ini memiliki akses yang berbeda. Lazimnya, role Admin mempunyai hak akses yang lebih tinggi daripada role User, misalnya menambahkan atau menghapus user.

Pada tutorial ini, kita menambahkan proses authorization kepada user pada boilerplate. Kemudian kita akan melakukan cek kepada user dengan dua role yaitu Admin dan User.

Boilerplate: Authorization

Pertama, kita buat terlebih dahulu fitur untuk mengelola seluruh user yang ada di aplikasi ini yaitu UserManagement dengan role Admin dan User. User dengan role Admin mempunyai akses untuk menambah, menghapus, atau memodifikasi data-data seluruh user di aplikasi serta akses ke halaman-halaman UserManagement, sedangkan role User hanya bisa mengakses data user tersebut tanpa bisa mengakses data user lain dan tidak bisa melihat halaman-halaman UserManagement.

Langkah selanjutnya adalah membuat halaman-halaman UserManagement.

Buat folder Pages/UserManagement kemudian buat file-file ini di dalam folder baru tersebut.

  • Create.cshtml
  • Create.cshtml.cs
  • Delete.cshtml
  • Delete.cshtml.cs
  • Details.cshtml
  • Details.cshtml.cs
  • Edit.cshtml.cs
  • Edit.cshtml.cs
  • Index.cshtml
  • Index.cshtml.cs

Kita akan gunakan Index.cshtml dan Index.cshtml.cs untuk rute UserManagement sedangkan halaman-halaman lain akan kita update nanti. Buka Index.cshtml.cs dan tambahkan kode berikut.

using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc.RazorPages;

namespace BoilerplateWebApp.Pages;

[Authorize(Roles = "Admin")] // Penambahan info protected page sesuai role
public class UserManagementModel : PageModel
{
    private readonly ILogger<UserManagementModel> _logger;

    public UserManagementModel(ILogger<UserManagementModel> logger)
    {
        _logger = logger;
    }

    public void OnGet()
    {
    }
}

File ini merupakan Page Model yang digunakan pada Index.cshtml. Authorization user dengan role Admin sudah ditambahkan sehingga UserManagementModel hanya bisa diakses oleh user dengan role Admin. User dengan role lain akan gagal untuk mengakses halaman ini.

Selanjutnya, tambahkan kode ini pada file Index.cshtml.

@page
@model UserManagementModel
@{
    ViewData["Title"] = "User Management";
}

<h1>User Management</h1>

<p>List User</p>

File ini akan ditampilkan di frontend.

Setelah itu, buka Program.cs dan tambahkan role services AddRoles<IdentityUser>().

using Microsoft.AspNetCore.Identity;
using Microsoft.EntityFrameworkCore;
using BoilerplateWebApp.Data;

var builder = WebApplication.CreateBuilder(args);

// Add services to the container.
var connectionString = builder.Configuration.GetConnectionString("DefaultConnection") ?? throw new InvalidOperationException("Connection string 'DefaultConnection' not found.");
builder.Services.AddDbContext<ApplicationDbContext>(options =>
    options.UseSqlite(connectionString));
builder.Services.AddDatabaseDeveloperPageExceptionFilter();

builder.Services.AddDefaultIdentity<IdentityUser>(options => options.SignIn.RequireConfirmedAccount = true)
    .AddRoles<IdentityUser>() // menambahkan role services
    .AddEntityFrameworkStores<ApplicationDbContext>();
builder.Services.AddRazorPages();

var app = builder.Build();

// Penambahan default admin user
using (var scope = app.Services.CreateScope())
{
    var services = scope.ServiceProvider;
    await SeedData.Initialize(services);
}

if (app.Environment.IsDevelopment())
{
    app.UseMigrationsEndPoint();
}
...

// kode lanjutan di Program.cs

Langkah selanjutnya adalah membuat seed pada database kita untuk menambahkan default user dengan role Admin.

Buat file SeedData.cs di folder Data dan update file menjadi seperti ini.

using Microsoft.AspNetCore.Identity;

namespace BoilerplateWebApp.Data;

public static class SeedData
{
    public static async Task Initialize(IServiceProvider serviceProvider)
    {
        var roleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();
        var userManager = serviceProvider.GetRequiredService<UserManager<IdentityUser>>();

        string[] roles = { "Admin", "User" };

        foreach (var role in roles)
        {
            if (!await roleManager.RoleExistsAsync(role))
            {
                await roleManager.CreateAsync(new IdentityRole(role));
            }
        }

        var adminUser = new IdentityUser
        {
            UserName = "[email protected]",
            Email = "[email protected]",
            EmailConfirmed = true
        };

        var user = await userManager.FindByEmailAsync(adminUser.Email);
        if (user == null)
        {
            var result = await userManager.CreateAsync(adminUser, "Admin@123");
            if (result.Succeeded)
            {
                await userManager.AddToRoleAsync(adminUser, "Admin");
            }
        }
    }
}

File ini berfungsi untuk membuat role Admin dan User serta satu user dengan role Admin yaitu [email protected] pada database. Role dan user dibuat dengan menggunakan beberapa class dari Microsoft.AspNetCore.Identity seperti IdentityRole dan IdentityUser.

Apabila user yang akan dibuat serta role belum eksis, maka seed akan dibuat berdasarkan informasi yang ada di file ini.

Okay mari kita jalankan aplikasi ini untuk tes fungsi Authorization yang ada. Jalankan dengan perintah dotnet run. Selanjutnya login dengan email [email protected] dan password Admin@123. Setelah itu, teman-teman bisa mengunjungi rute UserManagement dan akan melihat tampilan pada halaman UserManagement sesuai file Pages/UserManagement/Index.cshtml.

Access Granted

Kemudian teman-teman bisa mencoba register user baru dan juga melakukan klik pada tautan confirm email. User ini nantinya secara default memang tidak akan memiliki role Admin. Lalu teman-teman bisa mengunjungi rute UserManagement lagi. Maka akan ada informasi Access Denied. Hal ini sesuai dengan skenario Authorization yang kita buat tadi.

Access Denied

Selanjutnya, kita perlu memodifikasi proses registrasi user. Proses registrasi user saat ini tidak dilengkapi dengan penambahan informasi role pada user. Skenario ini harus kita ubah seperti berikut agar aplikasi web ini lebih aman.

  • Ketika registrasi, default role untuk user adalah User.
  • Hanya admin yang bisa mengubah role dari tiap user, misalnya mengubah role dari User menjadi Admin.

Buka file Areas/Identity/Pages/Account/Register.cshtml.cs. Kita tambahkan AddToRoleAsync dengan role User saat pembuatan user di proses registrasi pada method OnPostAsync sehingga menjadi seperti berikut.

...

public async Task<IActionResult> OnPostAsync(string returnUrl = null)
    {
        returnUrl ??= Url.Content("~/");
        ExternalLogins = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
        if (ModelState.IsValid)
        {
            var user = CreateUser();

            await _userStore.SetUserNameAsync(user, Input.Email, CancellationToken.None);
            await _emailStore.SetEmailAsync(user, Input.Email, CancellationToken.None);
            var result = await _userManager.CreateAsync(user, Input.Password);
            await _userManager.AddToRoleAsync(user, "User"); // Menambahkan default role saat user registrasi

            if (result.Succeeded)
            {
                _logger.LogInformation("User created a new account with password.");

                var userId = await _userManager.GetUserIdAsync(user);
                var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
                code = WebEncoders.Base64UrlEncode(Encoding.UTF8.GetBytes(code));
                var callbackUrl = Url.Page(
                    "/Account/ConfirmEmail",
                    pageHandler: null,
                    values: new { area = "Identity", userId = userId, code = code, returnUrl = returnUrl },
                    protocol: Request.Scheme);

                await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
                    $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");

                if (_userManager.Options.SignIn.RequireConfirmedAccount)
                {
                    return RedirectToPage("RegisterConfirmation", new { email = Input.Email, returnUrl = returnUrl });
                }
                else
                {
                    await _signInManager.SignInAsync(user, isPersistent: false);
                    return LocalRedirect(returnUrl);
                }
            }
            foreach (var error in result.Errors)
            {
                ModelState.AddModelError(string.Empty, error.Description);
            }
        }

        // If we got this far, something failed, redisplay form
        return Page();
    }

...

Setelah mengubah file ini, user akan mempunyai role User pada proses registrasi.

Langkah selanjutnya adalah membuat menu User Management di navbar yang hanya muncul oleh user dengan role Admin.

Buka file Pages/Shared/_Layout.cshtml dan tambahkan menu UserManagement.

...

<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
    <ul class="navbar-nav flex-grow-1">
        <li class="nav-item">
            <a class="nav-link text-dark" asp-area="" asp-page="/Index">Home</a>
        </li>
        <li class="nav-item">
            <a class="nav-link text-dark" asp-area="" asp-page="/Privacy">Privacy</a>
        </li>
        @{
            // Penambahan Menu User Management
        }
        @if (User.IsInRole("Admin"))
        {
            <li class="nav-item">
                <a class="nav-link text-dark" asp-area="" asp-page="/UserManagement/Index">User Management</a>
            </li>
        }
    </ul>
    <partial name="_LoginPartial" />
</div>

...

Kemudian jalankan aplikasi web kembali. Ketika teman-teman login melalui user dengan role Admin maka akan terlihat menu User Management di navbar. User dengan role selain Admin tidak akan bisa melihat menu ini.

User Management Menu

Proses authorization sudah berjalan dengan baik pada boilerplate ini. Kawan-kawan bisa menambahkan role lain sesuai dengan kebutuhan aplikasi yang dibuat. Pada bagian selanjutnya, kita akan menambahkan fitur user management untuk aplikasi ini.

Happy Coding!

Source Code Tutorial - Github DevKage
Suka konten ini? ❤️ Dukung DevKage melalui Saweria.