Search code examples
asp.net-mvcasp.net-coreauthentication

How to Handle Custom Password-less Authentication with JWT Token?


Idea:

My Login Page is like this:

enter image description here

Users can Authenticate via a JWT token given from a trusted system. Username is an Audience defined in Token so i can validate that the token issued for that user.

Problem:

i have a razor asp.net core 8.0 app and added JwtBearer in program.cs with default validation parameters:

builder.Services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
    .AddJwtBearer();

i want to know how do i properly handle Login in HttpContext.SignInAsync() ? how can i add Validated token to Bearer's Authorization header?


Solution

  • After obtaining the token, you can use HttpClient to set the request header and add the JWT token to the default request header of HttpClient for authentication in subsequent HTTP requests. client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken);

    For verification do you need to use the relevant authentication in the "trusted system" you mentioned, or do you need to create your own? If you use system(like API) to verify, you can initiate a post request and carry the token for verification.If you want to customize verification, you can use the same method. Post the token and username to a verification-related method to perform custom-related token authentication. If successful, you can continue to the next step of cookie verification,If it fails, relevant error information will be returned.

    var client = _httpClientFactory.CreateClient();
    
     client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", jwtToken);
     // create httpRequestMessage
     var httpRequestMessage = new HttpRequestMessage()
     {
         Method = HttpMethod.Post,
         RequestUri = new Uri("https://localhost:xxxx/api/token/verify"),
         Content = new StringContent(JsonSerializer.Serialize(loginViewModel), Encoding.UTF8, "application/json")
     };
    // use client to send httpRequestMessage to api and we get a json response back
    
    var httpResponseMessage = await client.SendAsync(httpRequestMessage);
    

    After successful verification,can create a user information object ClaimsIdentity​, which can represent the method used for authentication, and then use the user identity information created in the previous step to create a user principal object

    Finally, use the HttpContext.SignInAsync method to log in the user. Method will create a persistent authentication ticket (Cookie) and send it to the client. The SignInAsync method can accept three parameters:

    The first parameter is the authentication scheme name, which is used to identify the authentication method used.

    The second parameter is the user principal, indicating the currently logged in user.

    The third parameter is the authentication attribute, used to configure expiration time, etc.

    var userIdentity = new ClaimsIdentity(new[]
    
    {
    
        new Claim(ClaimTypes.Email, loginViewModel.Username),
    
        new Claim(ClaimTypes.AuthenticationMethod, "MyCustom"),
    
    }, "MyCustom");
    
    var user = new ClaimsPrincipal(userIdentity);
    
    await HttpContext.SignInAsync("MyCustom", user, new AuthenticationProperties
    
    {
    
        ExpiresUtc = DateTime.UtcNow.AddMinutes(20),
    
        IsPersistent = false, // You can change this based on your requirements
    
        AllowRefresh = false
    
    });
    
    // Log successful login
    
    return RedirectToAction("Index", "Home");