ASP.NET Core MVC is a popular framework for building web applications in .NET. It uses the well-known Model-View-Controller design pattern, which helps you achieve separation of concerns for your application UI. In this article, you will learn how to integrate authentication in an ASP.NET Core MVC application by using the Auth0 ASP.NET Core Authentication SDK.
The Sample Application
To focus adding authentication, you will use an existing ASP.NET Core MVC application, which will be described in a moment.
Prerequisites
Before starting, make sure you have the .NET 6 SDK installed on your machine. In fact, the application you are going to modify uses some features of C# 10. To get a quick overview of what's new with .NET 6, check out this article.
Also, this article will use the .NET CLI to build and run the application, but you can use Visual Studio 2022 if you prefer.
Get and run the sample application
You can get the sample application by running the following command in a terminal window:
git clone -b starter --single-branch https://github.com/auth0-blog/acme-aspnet-mvc.git
Once you download it, move to the acme-aspnet-mvc
folder and type the following command to launch the application:
dotnet watch
This command will run the sample application and wait for possible changes to the code. If you change the application code, it will be automatically rebuilt.
Note that some specific changes to your code, known as rude edits, may require restarting your application. Read this to learn more.
Now, point your browser to https://localhost:7095
. You should get the following page:
This is the home page of the fictional company ACME Corporation.
By clicking the Catalog link in the header, you can navigate their catalog, which will look as shown below:
Actually, the Buy now! button is not working. This page is just a placeholder for a page that users would expect to be protected. In other words, only authenticated users should access the catalog page. This is what you are going to implement in the next few sections.
Register with Auth0
Before making any changes, you must register the application with Auth0. You need an Auth0 account, of course. If you don't yet have it, you can sign up for a free one.
Once in the dashboard, move to the Applications section and follow these steps:
- Click on Create Application.
- Provide a friendly name for your application (for example, ACME Web App) and choose Regular Web Applications as the application type.
- Finally, click the Create button.
These steps make Auth0 aware of your ASP.NET Core MVC application and will allow you to control access.
After the application has been created, move to the Settings tab and take note of your Auth0 domain and your client id. Then, in the same form, assign the value https://localhost:7095/callback
to the Allowed Callback URLs field and the value https://localhost:7095/
to the Allowed Logout URLs field.
The first value tells Auth0 which URL to call back after the user authentication. The second value tells Auth0 which URL a user should be redirected to after their logout.
Click the Save Changes button to apply them.
Now, head back to the root folder of the sample application project, open the appsettings.json
configuration file, and replace its content with the following:
// appsettings.json
{
"Logging": {
"LogLevel": {
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
},
"AllowedHosts": "*",
"Auth0": {
"Domain": "YOUR_DOMAIN",
"ClientId": "YOUR_CLIENT_ID"
}
}
Replace the placeholders YOUR_DOMAIN
and YOUR_CLIENT_ID
with the respective values taken from the Auth0 dashboard.
Add Authentication
At this point, the basic settings for connecting your application to Auth0 are in place. To add authentication, you need to apply some changes to your application and use those settings. Let's go one step at a time.
Install the Auth0 SDK
As your first step, install the Auth0 ASP.NET Core Authentication SDK by running the following command in your terminal window:
dotnet add package Auth0.AspNetCore.Authentication
The Auth0 ASP.NET Core SDK lets you easily integrate OpenID Connect-based authentication in your app without dealing with all its low-level details.
If you want to learn a bit more, this blog post provides you with an overview of the Auth0 ASP.NET Core SDK.
Set up authentication
Now, let's modify the application code to support authentication. Open the Program.cs
file and change its content as follows:
// Program.cs
using Auth0.AspNetCore.Authentication; // 👈 new code
var builder = WebApplication.CreateBuilder(args);
// 👇 new code
builder.Services
.AddAuth0WebAppAuthentication(options => {
options.Domain = builder.Configuration["Auth0:Domain"];
options.ClientId = builder.Configuration["Auth0:ClientId"];
});
// 👆 new code
// Add services to the container.
builder.Services.AddControllersWithViews();
var app = builder.Build();
// Configure the HTTP request pipeline.
if (!app.Environment.IsDevelopment())
{
app.UseExceptionHandler("/Home/Error");
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseRouting();
app.UseAuthentication(); // 👈 new code
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
app.Run();
Following the highlighted code, you added a reference to the Auth0.AspNetCore.Authentication
namespace at the beginning of the file. Then you invoked the AddAuth0WebAppAuthentication()
method with the Auth0 domain and client id as arguments. Finally, you called the UseAuthentication()
method to enable the authentication middleware.
These changes lay the groundwork for supporting authentication via Auth0.
Implement login
To implement login, add a AccountController.cs
file to the Controllers
folder with the following content:
// Controllers/AccountController.cs
using Microsoft.AspNetCore.Authentication;
using Auth0.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
public class AccountController : Controller
{
public async Task Login(string returnUrl = "/")
{
var authenticationProperties = new LoginAuthenticationPropertiesBuilder()
.WithRedirectUri(returnUrl)
.Build();
await HttpContext.ChallengeAsync(Auth0Constants.AuthenticationScheme, authenticationProperties);
}
}
This class defines a controller meant to handle typical user account operations. In the code above, you implemented the login operation through the Login()
method. This method creates a set of authentication properties required for the login and triggers the authentication process via Auth0.
To enable this login operation, you need to change the UI. So, open the _Layout.cshtml
file under the Views/Shared
folder and update its content as follows:
// Views/Shared/_Layout.cshtml
<!DOCTYPE html>
<html lang="en">
<!-- ...existing code -->
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
// 👇 new code
@if (User.Identity.IsAuthenticated)
{
// 👆 new code
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link text-dark display-6" asp-area=""
asp-controller="Catalog"
asp-action="Index">Catalog</a>
</li>
</ul>
// 👇 new code
} else {
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link text-dark display-6" asp-area=""
asp-controller="Account"
asp-action="Login">Login</a>
</li>
</ul>
}
// 👆 new code
</div>
<!-- ...existing code -->
You modify the page's markup by adding a check on the User.Identity.IsAuthenticated
property. As you may have figured out, this property lets you know if the current user is authenticated or not. If the user is not authenticated, a Login link will be shown on the right side of the navigation bar.
Test login
Everything is ready. Go to your browser, and you should see the Login link as shown in the following picture:
When you click that link, you will be redirected to the Auth0 Universal Login page, as shown in the following screenshot:
The first time the user authenticates, they will be prompted with a page similar to the following:
This page is known as the consent screen, which informs the user that the sample application will access their user profile data. After accepting, you are redirected back to the sample application and should see the Catalog link appearing on the left side of the navigation bar:
Congratulations! You added authentication to your ASP.NET Core MVC application!
Leverage Auth0's authentication and authorization services in your .NET applications.
DOWNLOAD THE FREE EBOOKProtect Private Views
Although you have to authenticate to see the Catalog link in the navigation bar, the catalog view itself is not protected. You can verify this by accessing the https://localhost:7095/Catalog
address directly.
You need to restrict access to the catalog only to authenticated users.
Protect the catalog view
For this purpose, edit the CatalogController.cs
file under the Controllers
folder as shown below:
// Controllers/CatalogController.cs
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization; // 👈 new code
namespace acme.Controllers;
public class CatalogController : Controller {
private readonly ILogger<HomeController> _logger;
public CatalogController(ILogger<HomeController> logger)
{
_logger = logger;
}
[Authorize] // 👈 new code
public IActionResult Index()
{
return View();
}
}
You added a reference to the Microsoft.AspNetCore.Authorization
namespace, which provides you with the Authorize
attribute. You use this attribute by attaching it to the Index()
method of the controller. This simple change enables the authorization check on the catalog view so that only authenticated users can access it.
Implement logout
Another missing thing to make your application usable is logout. In fact, currently, when you log in to the application, you stay logged in until your session on Auth0 expires. You may want to allow your user to explicitly log out of the application. For this purpose, open the AccountController.cs
file in the Controllers
folder and add the code highlighted below:
// Controllers/AccountController.cs
using Microsoft.AspNetCore.Authentication;
using Auth0.AspNetCore.Authentication;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Authorization; // 👈 new code
using Microsoft.AspNetCore.Authentication.Cookies; // 👈 new code
public class AccountController : Controller
{
// ...existing code...
// 👇 new code
[Authorize]
public async Task Logout()
{
var authenticationProperties = new LogoutAuthenticationPropertiesBuilder()
.WithRedirectUri(Url.Action("Index", "Home"))
.Build();
await HttpContext.SignOutAsync(Auth0Constants.AuthenticationScheme, authenticationProperties);
await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
}
// 👆 new code
}
You added the references to the Microsoft.AspNetCore.Authorization
and Microsoft.AspNetCore.Authentication.Cookies
namespaces and defined a new method for the AccountController
class: Logout()
. This method creates a set of required properties and triggers the logout process to destroy both the Auth0 session and the local session.
The next step is to make the logout link available to the user. So, update the content of the _Layout.cshtml
file under Views/Shared
folder as follows:
// Views/Shared/_Layout.cshtml
<!DOCTYPE html>
<html lang="en">
<!-- ...existing code -->
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
@if (User.Identity.IsAuthenticated)
{
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link text-dark display-6" asp-area=""
asp-controller="Catalog"
asp-action="Index">Catalog</a>
</li>
</ul>
// 👇 new code
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link text-dark display-6" asp-area=""
asp-controller="Account"
asp-action="Logout">Logout</a>
</li>
</ul>
// 👆 new code
} else {
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link text-dark display-6" asp-area=""
asp-controller="Account"
asp-action="Login">Login</a>
</li>
</ul>
}
</div>
<!-- ...existing code -->
You just added the logout link on the right side of the navigation bar when the user is authenticated. That link points to the Logout()
method of the AccountController
class.
Test the application
It's time to test this new version of the application. First of all, remove all cookies from your browser or use an incognito window. This is needed because you haven't had a chance to log out so far.
Now, after you log in again, the home page should look as follows:
When you click the Logout link, you will be disconnected from Auth0 and see the usual home page with only the Login link.
Add a Profile Page
Let's try to go one step further and add a page showing some data about the user.
Specify your scopes
As said before, the Auth0 ASP.NET Core Authentication SDK uses OpenID Connect (OIDC) to authenticate your users. OIDC provides your application with an ID token containing some basic data about the user. From a technical point of view, this user data is available because the SDK requests the openid
and profile
scopes by default. You don't see this because the SDK takes care of the whole authentication process and manages the ID token. So, by default, you have the user's name and possibly their picture. If you also want the user's email in their profile, you have to specify the scopes explicitly.
Open the Program.cs
file and apply the following change:
// Program.cs
// ...existing code...
var builder = WebApplication.CreateBuilder(args);
builder.Services
.AddAuth0WebAppAuthentication(options => {
options.Domain = builder.Configuration["Auth0:Domain"];
options.ClientId = builder.Configuration["Auth0:ClientId"];
options.Scope = "openid profile email"; // 👈 new code
});
// ...existing code...
You assigned a string to the Scope
option containing the default scopes mentioned before (openid
and profile
) and the email
scope.
This causes the email to be added to the user profile.
Create the profile model
To show the user profile, let's start by creating a model. Add a UserProfileViewModel.cs
file to the Model
folder with the following content:
// Model/UserProfileViewModel.cs
namespace acme.ViewModels;
public class UserProfileViewModel
{
public string EmailAddress { get; set; }
public string Name { get; set; }
public string ProfileImage { get; set; }
}
This code simply defines a class with the three elements of the user profile: the name, the email address, and the user's picture.
Create the profile view
To define the associated view, create an Account
folder in the Views
folder. Then add the Profile.cshtml
file to the Views/Account
folder with the following content:
@* Views/Account/Profile.cshtml *@
@model acme.ViewModels.UserProfileViewModel
@{
ViewData["Title"] = "User Profile";
}
<div class="row">
<div class="col-md-12">
<div class="row">
<h2>@ViewData["Title"].</h2>
<div class="col-md-2">
<img src="@Model.ProfileImage"
alt="" class="img-rounded img-responsive" />
</div>
<div class="col-md-4">
<h3>@Model.Name</h3>
<p>
<i class="glyphicon glyphicon-envelope"></i> @Model.EmailAddress
</p>
</div>
</div>
</div>
</div>
This markup shows the three properties of the user model.
Create the profile controller
Let's complete the profile by creating the profile controller. Add the following method to the AccountController
class:
// Controllers/AccountController.cs
// ...existing code...
using System.Security.Claims; // 👈 new code
using acme.ViewModels; // 👈 new code
public class AccountController : Controller
{
// ...existing code...
// 👇 new code
[Authorize]
public IActionResult Profile()
{
return View(new UserProfileViewModel()
{
Name = User.Identity.Name,
EmailAddress = User.FindFirst(c => c.Type == ClaimTypes.Email)?.Value,
ProfileImage = User.FindFirst(c => c.Type == "picture")?.Value
});
}
// 👆 new code
}
You add the references to the System.Security.Claims
and acme.ViewModels
namespaces and define the Profile()
method. This method returns a view based on the user profile model, whose property values are extracted by the currently logged User
object. Notice that also the Profile()
method is marked with the Authorized
attribute.
Link the profile page
Finally, let's make the profile page available to the user. Open the _Layout.cshtml
file under the Views/Shared
folder and update its content as follows:
// Views/Shared/_Layout.cshtml
<!DOCTYPE html>
<html lang="en">
<!-- ...existing code -->
<div class="navbar-collapse collapse d-sm-inline-flex justify-content-between">
@if (User.Identity.IsAuthenticated)
{
<ul class="navbar-nav">
<li class="nav-item">
<a class="nav-link text-dark display-6" asp-area=""
asp-controller="Catalog"
asp-action="Index">Catalog</a>
</li>
</ul>
<ul class="navbar-nav ms-auto">
// 👇 new code
<li class="nav-item">
<a class="nav-link text-dark display-6"
asp-controller="Account"
asp-action="Profile">Hello @User.Identity.Name!</a>
</li>
// 👆 new code
<li class="nav-item">
<a class="nav-link text-dark display-6" asp-area=""
asp-controller="Account"
asp-action="Logout">Logout</a>
</li>
</ul>
} else {
<ul class="navbar-nav ms-auto">
<li class="nav-item">
<a class="nav-link text-dark display-6" asp-area=""
asp-controller="Account"
asp-action="Login">Login</a>
</li>
</ul>
}
</div>
<!-- ...existing code -->
You add the link to the profile view next to the logout link. That link will show a welcome message with the user name. Also, it will be shown only when the user is authenticated.
A new Auth0-powered .NET app in less than a minute?
Try out our templates
Test the user profile
Go back to your browser and authenticate again. As a first difference, you will notice that you will see the consent screen again. Why? Didn't you previously accept?
Actually, this time, your application is requesting a new piece of information about you: the email. If you compare this screen with the previous one, you will notice this subtle difference.
After you accept that screen, your new home page will look as follows:
You can see the welcome message next to the logout link. If you click the welcome message, the user profile will be shown as in the following picture:
Summary
Throughout this article, you learned how to integrate authentication in an ASP.NET Core MVC application via Auth0. You've seen how the Auth0 ASP.NET Core Authentication SDK handles OpenID Connect for you under the hood, preventing you from dealing with the technical details. You also learned how to protect the private views of your application and how to implement logout. Finally, you were able to get the user's data to create a user profile page.
You can find the complete code of the ASP.NET Core MVC project in this GitHub repository.