Cookie Auth for Web and JWT Auth for API — Hybrid model for C# MVC .NET core 7
Authentication is a critical aspect of web application development, ensuring that users can securely access different parts of the application based on their identity. There are various authentication methods available, each with its own strengths and weaknesses. One such approach is the hybrid authentication model, which combines the benefits of Cookie Authentication for web applications and JWT (JSON Web Token) Authentication for APIs in C# ASP.NET Core 7.
In this blog post, we will explore the hybrid authentication model, diving into how it leverages Cookie Auth and JWT Auth to create a robust and flexible authentication system. By understanding this approach, developers can build web applications that strike a balance between session-based stateful behavior and stateless, scalable API calls.
Cookie Authentication is a traditional and widely-used method for securing web applications. It relies on HTTP cookies to store authentication information on the client-side, enabling session-based interactions. When a user logs in, the server issues an authentication cookie that is sent with each subsequent request, allowing the server to identify and authenticate the user.
The benefits of Cookie Authentication include built-in support for user sessions, easy session management, and a straightforward implementation for web applications. Moreover, cookies can be set to be secure and HTTP-only, mitigating certain security risks.
JWT Authentication is a stateless authentication method well-suited for APIs and microservices architectures. Instead of storing authentication information on the server, JWTs are self-contained tokens containing user claims and other metadata. These tokens are signed, allowing the server to verify their integrity and authenticate users without the need for a session.
JWT Authentication offers statelessness, making it scalable and ideal for distributed systems. It enables the sharing of authentication across multiple services, improving efficiency and interoperability.
The Hybrid Authentication Model: The hybrid authentication model brings together the strengths of both Cookie and JWT Authentication, allowing developers to utilize each method where it excels. In this approach, the web application uses Cookie Authentication to manage user sessions, allowing for seamless user experiences with session-based functionalities. On the other hand, the API employs JWT Authentication, enabling stateless API calls that scale effectively.
By leveraging the hybrid model, developers can implement an authentication system that handles both web application interactions and API communication efficiently. Web pages can be secured with Cookie Auth, providing stateful behavior and user sessions, while API calls can be authenticated with JWT Auth, promoting a stateless and scalable design.
In the following sections of this blog post, we will delve into the implementation details of both Cookie Authentication and JWT Authentication, and explore how to combine them effectively to achieve a powerful hybrid authentication model in C# ASP.NET Core applications. We will also address security considerations and best practices to ensure a robust and secure authentication system.
Below is a step-by-step guide on how to implement both authentication methods in a C# ASP.NET Core application.
dotnet new webapp -n MyWebApp
Install the packages from the Nuget manager or enter the below command in the package manager.
dotnet add package Microsoft.AspNetCore.Authentication.JwtBearer
dotnet add package Microsoft.AspNetCore.Authentication.Cookies
Configure Authentication in program.cs:
In the program.cs
file, configure the authentication services and middleware. In the ConfigureServices
method, add the authentication services:
byte[] key = Encoding.UTF8.GetBytes("This is a private secret key");
builder.Services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultSignInScheme = CookieAuthenticationDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddCookie(options =>
{
options.Cookie.Name = "MyProjectCookie";
options.ExpireTimeSpan = TimeSpan.FromMinutes(30); // Set your desired expiration time (e.g., 30 minutes)
options.SlidingExpiration = true;
}).AddJwtBearer(options =>
{
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = false,
ValidateAudience = false,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero,
};
});
After building the app, use the below code for authenticating the middleware.
var app = builder.Build();
app.UseAuthentication();
app.UseAuthorization();
app.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}");
app.MapRazorPages();
In the web application, you can follow the normal authentication process with the sign-in manager. This sign-in manager will allow you to interact with the default cookie auth system and allow you to login into the application.
var loginResult = _signInManager.PasswordSignInAsync(user, model.Password, false, false);
You can also use [Authorize] attribute to for auth process with the role management system.
In the web api, you can use all the method to for the data process. Here, you need to add Authorize & Authentication Schemes with the particular schemes.
[Authorize(AuthenticationSchemes = JwtBearerDefaults.AuthenticationScheme)]
public class MyProtectedController : Controller
{
[HttpGet]
public IActionResult Index()
{
return View();
}
}
By this way, you can authenticate with the JWT token. But, while sending it to the Web API system, you need to generate new token with the expiry date and can implement the refresh token as well.
JwtSecurityTokenHandler tokenHandler = new();
byte[] key = Encoding.UTF8.GetBytes("This is a private secret key");
SecurityTokenDescriptor tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.NameIdentifier, email),
new Claim(ClaimTypes.Role, userRole),
}),
Expires = DateTime.UtcNow.AddMinutes(30),
SigningCredentials = new(new SymmetricSecurityKey(key), SecurityAlgorithms.HmacSha256Signature)
};
SecurityToken token = tokenHandler.CreateToken(tokenDescriptor);
string jwtToken = tokenHandler.WriteToken(token);
With the above documentation, a hybrid model Cookie auth for web and JWT auth for Web API can be created. If required, the refresh token concept can also be included with the above code and can use it for different purposes.
References:
https://learn.microsoft.com/en-us/aspnet/core/fundamentals/?view=aspnetcore-7.0&tabs=windows