EF CORE - AUTHORIZE PRODUCT CRUD OPERATIONS
ENTITY FRAMEWORK CORE (EF CORE) — PART 4: AUTHORIZE PRODUCT CRUD OPERATIONS
PART 3 added registration, login, logout and a protected Members page. This tutorial allows everyone to browse Products while requiring authentication to create, edit or delete a Product.
1. Define the authorization rules
| Product page | Route | Guest | Authenticated user |
|---|---|---|---|
| Index | /Products | Allowed | Allowed |
| Details | /Products/Details?id=1 | Allowed | Allowed |
| Create | /Products/Create | Login required | Allowed |
| Edit | /Products/Edit?id=1 | Login required | Allowed |
| Delete | /Products/Delete?id=1 | Login required | Allowed |
Hiding buttons improves the interface, but it is not security. Each modifying PageModel must also enforce authorization on the server.
2. Confirm Identity is working
cd ~/dotnetprojects/dotnetef
dotnet build
sqlite3 Data/identity.db ".tables"
Start the application and confirm that Register, Login and Logout from PART 3 work before continuing:
dotnet run
Stop it with Ctrl+C before editing the files.
3. Protect the Create PageModel
Open Pages/Products/Create.cshtml.cs. Add this using directive:
using Microsoft.AspNetCore.Authorization;
Add [Authorize] immediately above the generated class:
namespace dotnetef.Pages.Products;
[Authorize]
public class CreateModel : PageModel
{
// Keep the existing generated code here.
}
The attribute protects both the GET request that displays the form and the POST request that inserts the Product.
4. Protect the Edit PageModel
Open Pages/Products/Edit.cshtml.cs and add:
using Microsoft.AspNetCore.Authorization;
Then add the authorization attribute:
namespace dotnetef.Pages.Products;
[Authorize]
public class EditModel : PageModel
{
// Keep the existing generated code here.
}
This prevents guests from displaying or submitting the Edit form.
5. Protect the Delete PageModel
Open Pages/Products/Delete.cshtml.cs and add:
using Microsoft.AspNetCore.Authorization;
Then protect the class:
namespace dotnetef.Pages.Products;
[Authorize]
public class DeleteModel : PageModel
{
// Keep the existing generated code here.
}
The confirmation page and its deletion handler now require login.
6. Leave Index and Details public
Do not add [Authorize] to these files:
Pages/Products/Index.cshtml.cs
Pages/Products/Details.cshtml.cs
They remain public because Razor Pages allows anonymous access unless authorization is explicitly required.
7. Hide the Create link from guests
Open Pages/Products/Index.cshtml. Locate the generated Create link and wrap it in an authentication check:
@if (User.Identity?.IsAuthenticated == true)
{
<p>
<a asp-page="Create">Create New</a>
</p>
}
Logged-out visitors can still read the Product list, but they will not see a link to a page they cannot use.
8. Keep Details public and hide Edit and Delete
In the action column of Pages/Products/Index.cshtml, replace the generated links with:
<a asp-page="./Details"
asp-route-id="@item.Id">Details</a>
@if (User.Identity?.IsAuthenticated == true)
{
<span> | </span>
<a asp-page="./Edit"
asp-route-id="@item.Id">Edit</a>
<span> | </span>
<a asp-page="./Delete"
asp-route-id="@item.Id">Delete</a>
}
Details remains visible to everyone. Edit and Delete appear only after login.
9. Hide the Edit link on the Details page
Open Pages/Products/Details.cshtml. Keep the Back to List link public and display Edit conditionally:
<div>
@if (User.Identity?.IsAuthenticated == true)
{
<a asp-page="./Edit"
asp-route-id="@Model.Product.Id">Edit</a>
<span> | </span>
}
<a asp-page="./Index">Back to List</a>
</div>
10. Optionally show the Members link only after login
PART 3 deliberately showed Members to guests to demonstrate redirection. The navigation can now be made cleaner. In Pages/Shared/_Layout.cshtml, wrap the Members item:
@if (User.Identity?.IsAuthenticated == true)
{
<li class="nav-item">
<a class="nav-link text-dark"
asp-page="/Members">Members</a>
</li>
}
11. Build and run
dotnet build
dotnet run
Correct any build error before testing in the browser.
12. Test as a guest
Log out and test the following:
| Test | Expected result |
|---|---|
Open /Products | Product list appears |
| Open a Details link | Product details appear |
| Inspect the Product list | Create, Edit and Delete links are hidden |
Type /Products/Create | Redirected to Login |
Type /Products/Edit?id=1 | Redirected to Login |
Type /Products/Delete?id=1 | Redirected to Login |
Typing protected URLs manually confirms that security does not depend on hidden links.
13. Test as an authenticated user
- Click Login.
- Enter the account created in PART 3.
- Open
/Products. - Confirm that Create, Edit and Delete links are now visible.
- Create a Product.
- Edit that Product.
- Delete that Product.
14. Understand the two protection layers
| Layer | Code | Purpose |
|---|---|---|
| User interface | User.Identity?.IsAuthenticated | Hides unavailable actions from guests |
| Server authorization | [Authorize] | Rejects unauthorized requests even when a URL is entered manually |
The server-side layer is essential. A visitor can alter URLs or send an HTTP request without using the application's links.
15. Alternative: protect pages by convention
For a larger application, individual attributes can be replaced by authorization conventions in Program.cs:
builder.Services.AddRazorPages(options =>
{
options.Conventions.AuthorizePage(
"/Products/Create"
);
options.Conventions.AuthorizePage(
"/Products/Edit"
);
options.Conventions.AuthorizePage(
"/Products/Delete"
);
});
Use either the [Authorize] attributes from this tutorial or these conventions. Both are shown to explain the alternatives; duplicating them is unnecessary.
16. Common problems
| Problem | Remedy |
|---|---|
AuthorizeAttribute cannot be found | Add using Microsoft.AspNetCore.Authorization; |
| Create, Edit or Delete still opens for guests | Place [Authorize] immediately above the correct PageModel class and rebuild |
| Links remain visible after logout | Wrap the links with User.Identity?.IsAuthenticated == true |
| All Product pages require login | Remove folder-wide authorization or add protection only to Create, Edit and Delete |
| Login succeeds but returns to the wrong page | Use the Identity-generated Login URL with its ReturnUrl parameter |
| Product actions return 404 | Use the generated Razor Page names and pass asp-route-id |
What has been achieved?
- Guests can browse the Product list and Product details.
- Create, Edit and Delete require authentication.
- Modification links are hidden from logged-out visitors.
- Direct requests to protected URLs are rejected.
- The difference between interface visibility and server security is clear.
PART 4 complete: Product reading remains public, while Product modification is restricted to authenticated users.
Official references
- Microsoft Learn: Simple authorization
- Microsoft Learn: Razor Pages authorization conventions
- Microsoft Learn: ASP.NET Core Identity
Next: ENTITY FRAMEWORK CORE (EF CORE) — PART 5 associates each Product with the authenticated user so users can modify only their own records.