0

I have two projects one client-side in MVC and the second a Web API project, both are in .Net 6.

Web API side
I want to Authenticate users coming to the client side. I know that to add authentication to Web API most recommended way is a JWT token. So I added the below code to my Web API program.cs class to use JWT authentication.

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
    options.RequireHttpsMetadata = false;
    options.SaveToken = true;
    options.TokenValidationParameters = new TokenValidationParameters()
    {
        ValidateIssuer = true,
        ValidateAudience = true,
        ValidAudience = builder.Configuration["Jwt:Audience"],
        ValidIssuer = builder.Configuration["Jwt:Issuer"],
        IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(builder.Configuration["Jwt:Key"]))
    };
});    

Next, I added a login method as below in the Web API that simply generates the JWT token and returns the token. Not adding GenerateToken() code to keep things simple

[HttpGet]
[Route("login")]
public JsonResult Login()
{
    var token = TokenHelper.GenerateToken();

    return new JsonResult(new { token = token });
}    

Client-side
On the client-side, I have configured cookie authentication which checks if the user is not authenticated, it will redirect the user to the login page on the client-side

builder.Services.AddAuthentication(CookieAuthenticationDefaults.AuthenticationScheme)
   .AddCookie(options =>
    {
        options.ExpireTimeSpan = TimeSpan.FromMinutes(20);
        options.SlidingExpiration = true;
        options.AccessDeniedPath = "/Error/Forbidden/";
        options.LoginPath = "/home/login/";
    });    

On the login page, I ask the user to enter their username and password and then call the login endpoint in the Web API project that issues a token. I successfully get the token.

using (var client = new HttpClient())
{
      client.BaseAddress = new Uri("https://localhost:7157/");

      HttpResponseMessage response = await client.GetAsync("WeatherForecast/login");

      if (response.IsSuccessStatusCode)
      {
         var token= await response.Content.ReadFromJsonAsync<TokenModel>();
      }
      else
      {
         Console.WriteLine("Internal server Error");
      }
}

Now, this is the point where I am struggling. I want to sign in user using this token on the client-side something like generate a cookie using token or use HttpContext.SignInAsync to sign in the user. I have the token but not sure what is the best practice to log in the user or how to use that token.

Muhammad Ali
  • 83
  • 2
  • 9

1 Answers1

2

If you want cookie authentication(as you setted in your MVC project),you could use ReadToken() method to read the claims inside the token, and generate the ClaimsIdentity which is required in HttpContext.SignInAsync()method

                var jsonToken = new JwtSecurityTokenHandler().ReadToken(token) as JwtSecurityToken;
                var username = jsonToken.Claims.FirstOrDefault(m => m.Type == ClaimTypes.Name).Value;
                 .............
                 //add other logic
                if (username==user.Name)
                {
                    var claims = new Claim[]
                    {
                    new Claim(ClaimTypes.Name, user.Name),
                     };
                    var claimsIdentity = new ClaimsIdentity(claims);
                    await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, new ClaimsPrincipal(claimsIdentity));
                }

if you want JWT Authentication in your MVC project,you could set as below :

services.AddAuthentication(options =>
            {
                
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
            })
            
            .AddJwtBearer(options =>
             {
                 options.TokenValidationParameters = new TokenValidationParameters
                 {
                     ......
                 };
                 options.Events = new JwtBearerEvents
                 {

                     OnMessageReceived = context =>
                     {
                         var accessToken = context.Request.Cookies["token"];
                         
                         if (!string.IsNullOrEmpty(accessToken))
                         {
                             context.Token = accessToken;
                         }

                         return Task.CompletedTask;
                     }
                 };

add the token in your login controller:

Response.Cookies.Append("token", token);
Ruikai Feng
  • 6,823
  • 1
  • 2
  • 11
  • So if i use that token returned from Web API to sign in user and put an [Authorize] attribute on client side method and try to access that method, will the .NET framework check whether the user is signed In or not? – Muhammad Ali Jun 22 '22 at 14:53
  • Yes,you could read the document related:https://learn.microsoft.com/en-us/aspnet/core/security/authentication/?view=aspnetcore-6.0#authenticate – Ruikai Feng Jun 23 '22 at 01:25