0% found this document useful (0 votes)
3 views6 pages

MVC Auth Complete Lesson

The document explains authentication and authorization in ASP.NET Core using an airport lounge analogy. It details the setup of cookie-based authentication, the creation of user models and DTOs for data transfer, and the implementation of login, change password, and forgot password functionalities. Additionally, it emphasizes the importance of the [Authorize] attribute for securing controllers and managing user access.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
3 views6 pages

MVC Auth Complete Lesson

The document explains authentication and authorization in ASP.NET Core using an airport lounge analogy. It details the setup of cookie-based authentication, the creation of user models and DTOs for data transfer, and the implementation of login, change password, and forgot password functionalities. Additionally, it emphasizes the importance of the [Authorize] attribute for securing controllers and managing user access.
Copyright
© All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd

Lesson: Authentication, Authorization, DTOs & UI in

MVC

1. The Simple Analogy: The Exclusive Airport Lounge

To understand these two concepts, imagine visiting an exclusive airport lounge:

[ Airport Entrance ] ---> Authentication ---> Passport / ID Check ---> Issued Boarding Pass
|
v
[ VIP Lounge Door ] ---> Authorization ---> Scan Boarding Pass ---> Access Granted / Denied

• Authentication (Who are you?): You present your Passport at the check-in desk. The agent verifies your
face against your photo ID and hands you a Boarding Pass.
• Authorization (What are you allowed to do?): You walk up to the VIP Lounge. The guard scans your
Boarding Pass to check if it says First Class.

2. System Setup ( [Link] )

In [Link] Core, cookie-based authentication is built-in. We tell the system where to send users who don't
have a valid "Boarding Pass".

using [Link];

var builder = [Link](args);


[Link]();

// 1. Register Cookie Authentication


[Link]([Link])
.AddCookie(options =>
{
[Link] = "/Account/Login"; // Where to redirect if unauthenticated
[Link] = "/Account/Denied"; // Where to redirect if unauthorized
});

var app = [Link]();

[Link]();

// 2. Add Middleware (ORDER IS CRITICAL!)


[Link](); // "Who are you?" (Reads the Cookie)
[Link](); // "Are you allowed here?" (Checks [Authorize])

[Link](name: "default", pattern: "{controller=Home}/{action=Index}/{id?}");


[Link]();
3. Data Storage & DTOs (ViewModels)

We need a static class to store our users, and ViewModels (DTOs) to carry data securely between the UI
(HTML forms) and the Controller.

The Static In-Memory Database

public class UserModel


{
public string Id { get; set; } = [Link]().ToString();
public string Email { get; set; } = [Link];
public string Password { get; set; } = [Link];
public string FullName { get; set; } = [Link];
}

public static class InMemoryUserStore


{
public static List<UserModel> Users = new List<UserModel>
{
new UserModel { Email = "admin@[Link]", Password = "Password123!", FullName =
"System Admin" }
};
}

The ViewModels (DTOs)

using [Link];

public class LoginViewModel


{
[Required, EmailAddress]
public string Email { get; set; }

[Required, DataType([Link])]
public string Password { get; set; }
}

public class ChangePasswordViewModel


{
[Required, DataType([Link])]
public string CurrentPassword { get; set; }

[Required, DataType([Link])]
public string NewPassword { get; set; }
}

public class ForgotPasswordViewModel


{
[Required, EmailAddress]
public string Email { get; set; }
}
4. Enforcing Login: The [Authorize] Attribute

🛡️ The VIP Bouncer


Think of [Authorize] as a bouncer standing in front of a Controller. If a user doesn't have an active
login cookie, the bouncer catches the 401 Unauthorized error and redirects them to the LoginPath
defined in [Link] .

using [Link];
using [Link];

[Authorize] // Locks down the whole controller


public class HomeController : Controller
{
public IActionResult Index() { return View(); } // Locked

[AllowAnonymous] // Exception: Opens this specific door to the public


public IActionResult Contact() { return View(); } // Unlocked
}

5. The Core Flows: Controllers & UI (Views)

Let's look at how the DTOs, Controllers, and HTML UI work together.

Flow 1: Login
Controller Action: Validates the DTO and issues a Cookie.
[AllowAnonymous]
[HttpPost]
public async Task<IActionResult> Login(LoginViewModel model)
{
if (![Link]) return View(model);

var user = [Link](u => [Link] == [Link] && [Link]


== [Link]);

if (user == null)
{
[Link]("", "Invalid email or password.");
return View(model);
}

var claims = new List<Claim> {


new Claim([Link], [Link]),
new Claim([Link], [Link])
};

var identity = new ClaimsIdentity(claims,


[Link]);
await [Link]([Link], new
ClaimsPrincipal(identity));

return RedirectToAction("Index", "Home");


}

Razor View ( [Link] ): Binds the HTML form to the LoginViewModel .

@model LoginViewModel
<h2>Account Login</h2>

<form asp-action="Login" method="post">


<div asp-validation-summary="ModelOnly" class="text-danger"></div>

<div>
<label asp-for="Email"></label>
<input asp-for="Email" />
<span asp-validation-for="Email" class="text-danger"></span>
</div>

<div>
<label asp-for="Password"></label>
<input asp-for="Password" />
<span asp-validation-for="Password" class="text-danger"></span>
</div>

<button type="submit">Login</button>
</form>

Flow 2: Change Password


Controller Action: Requires an active session. Updates static memory.
[Authorize]
[HttpPost]
public IActionResult ChangePassword(ChangePasswordViewModel model)
{
if (![Link]) return View(model);

string? userEmail = [Link]([Link]);


var user = [Link](u => [Link] == userEmail);

if (user == null || [Link] != [Link])


{
[Link]("", "Current password is incorrect.");
return View(model);
}

[Link] = [Link];
[Link] = "Password successfully changed!";
return View();
}

Razor View ( [Link] ):

@model ChangePasswordViewModel
<h2>Change Password</h2>

@if ([Link] != null) {


<div style="color: green;">@[Link]</div>
}

<form asp-action="ChangePassword" method="post">


<div>
<label asp-for="CurrentPassword"></label>
<input asp-for="CurrentPassword" />
</div>
<div>
<label asp-for="NewPassword"></label>
<input asp-for="NewPassword" />
</div>
<button type="submit">Update Password</button>
</form>

Flow 3: Forgot Password


Controller Action: Finds the user and updates the list with a temp password.
[AllowAnonymous]
[HttpPost]
public IActionResult ForgotPassword(ForgotPasswordViewModel model)
{
if (![Link]) return View(model);

var user = [Link](u => [Link] == [Link]);


if (user != null)
{
string tempPassword = "Temp" + [Link](1000, 9999) + "!";
[Link] = tempPassword;
TempData["Notice"] = $"Password reset. Temporary Password: {tempPassword}";
}

return RedirectToAction("ForgotPassword");
}

Razor View ( [Link] ):

@model ForgotPasswordViewModel
<h2>Forgot Password</h2>

@if (TempData["Notice"] != null) {


<div style="color: blue;">@TempData["Notice"]</div>
}

<form asp-action="ForgotPassword" method="post">


<div>
<label asp-for="Email"></label>
<input asp-for="Email" />
</div>
<button type="submit">Reset Password</button>
</form>

You might also like