How to send back a bearer token after Login in a HTTP Request

Jose Daniel Navarro Brito 61 Reputation points
2023-09-17T08:15:19.8633333+00:00

Good day all:

It seems trivial and there a lot of examples out there but I haven't found a clear piece of code for such a simple issue.

I have an external WEB API which sends a bearer token after the user authenticate

     public async Task<IActionResult> Login([FromBody] LoginViewModel model)          {             var result = await _identityService.LoginAsync(model);             if (!string.IsNullOrEmpty(result?.Token))             {                 return Ok(result);             }             return Unauthorized();         }

The above works perfectly and the end point ( an ASP.NET CORE Web application) receives the token after the user authenticate via the code below.

  public class LoginController : Controller
    {
        private readonly IHttpClientFactory _httpClientFactory;


        public LoginController(IHttpClientFactory httpClientFactory)
        {
            _httpClientFactory = httpClientFactory;
        }
        public IActionResult Index()
        {
            return View();
        }

        [HttpPost]
        public async Task<ActionResult<string>> Login([FromForm] LoginViewModel model)
        {
            var httpClient = _httpClientFactory.CreateClient("HousingWebAPI");           
            var body = new StringContent(JsonConvert.SerializeObject(model), Encoding.UTF8, "application/json");
            using (var posting  = await httpClient.PostAsync("Login/login", body))
            {              
                posting.EnsureSuccessStatusCode();
                var content = await posting.Content.ReadAsStringAsync();                
                return Ok(content);
            }
            return NotFound();
        }

    }
}
{"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiSm9zZSIsImp0aSI6IjA2NTU1NjZkLWJmOTctNDFiMi1hMzE5LTNmZjEwMDk5YWU2YSIsImV4cCI6MTY5NDk0ODI1MCwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDoiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OiJ9.usGppL6QpE7qMeyki1eB503n4nwIJ-xxxWMCMy6dX5o","expiration":"2023-09-17T10:57:30Z"}


The problem:

  1. after a successful authentication, the token should be store in order to send it in the requests( otherwise they should authenticate every time isn't it ?). This is my first questions How I safely store my token ...there are a lot options there : Cookies, database,e tc but I haven't seen a clear example that suits my coding.
  2. Now ...let say that I want to send my stored token in the request below. it;s said that I should send it using the  httpClient.DefaultRequestHeaders.Authorization , but I don't have an idea how to do it in the code below.

I know what to do but I don't know how to achieve it. There a lot of examples but sometimes too much inofrmation confuses.

  [HttpPost]

        public async Task<ActionResult<string>> PostData([FromForm] DataTableAjaxPostModel model)
        {
            using var client = new HttpClient();
            client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
            var body = new StringContent(JsonConvert.SerializeObject(model), Encoding.UTF8, "application/json");
                  
            var response = await client.PostAsync("https://localhost:7193/HousingWebAPI/GetData", body);
            if (response.IsSuccessStatusCode)
            {
                var content = await response.Content.ReadAsStringAsync();
                return Ok(content);
            }
            return NotFound();
        }
ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,612 questions
ASP.NET
ASP.NET
A set of technologies in the .NET Framework for building web applications and XML web services.
3,507 questions
ASP.NET API
ASP.NET API
ASP.NET: A set of technologies in the .NET Framework for building web applications and XML web services.API: A software intermediary that allows two applications to interact with each other.
343 questions
0 comments No comments
{count} votes

4 answers

Sort by: Most helpful
  1. SurferOnWww 3,201 Reputation points
    2023-09-18T01:03:39.29+00:00
    1. after a successful authentication, the token should be store in order to send it in the requests.

    How about using the "sessionStorage" as described in the following Microsoft document?

    Secure a Web API with Individual Accounts and Local Login in ASP.NET Web API 2.2

    ( otherwise they should authenticate every time isn't it ?)

    That's what it is. You have to send the token every time. There is no other way.

    1. Now ...let say that I want to send my stored token in the request below.

    Please refer to the above document. A sample code is provided.

    0 comments No comments

  2. Qing Guo - MSFT 896 Reputation points Microsoft Vendor
    2023-09-18T04:08:18.4866667+00:00

    Hi @Jose Daniel Navarro Brito ,

    The above works perfectly and the end point ( an ASP.NET CORE Web application) receives the token after the user authenticate via the code below.

    I want to send my stored token in the request below

    You can try to use Tempdata to pass your token form your LoginController Login to your PostData method

    like:

           [HttpPost]
            public async Task<ActionResult<string>> Login([FromForm] LoginViewModel model)
            {
                var httpClient = _httpClientFactory.CreateClient("HousingWebAPI");           
                var body = new StringContent(JsonConvert.SerializeObject(model), Encoding.UTF8, "application/json");
                using (var posting  = await httpClient.PostAsync("Login/login", body))
                {              
                    posting.EnsureSuccessStatusCode();
                    var content = await posting.Content.ReadAsStringAsync();
                    TempData["token"]= content;  //  use TempData to pass the token          
                    return Ok(content);
                }
                return NotFound();
            }
    
    
    

    Then send the token in the request below using the  httpClient.DefaultRequestHeaders.Authorization:

      [HttpPost]
    
      public async Task<ActionResult<string>> PostData([FromForm] DataTableAjaxPostModel model)
      {
          string token = (string)TempData["token"];
          using var client = new HttpClient();
          client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
          client.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
          var body = new StringContent(JsonConvert.SerializeObject(model), Encoding.UTF8, "application/json");
    
          var response = await client.PostAsync("https://localhost:7193/HousingWebAPI/GetData", body);
          if (response.IsSuccessStatusCode)
          {
              var content = await response.Content.ReadAsStringAsync();
              return Ok(content);
          }
          return NotFound();
      }
    

    {"token":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJodHRwOi8vc2NoZW1hcy54bWxzb2FwLm9yZy93cy8yMDA1LzA1L2lkZW50aXR5L2NsYWltcy9uYW1lIjoiSm9zZSIsImp0aSI6IjA2NTU1NjZkLWJmOTctNDFiMi1hMzE5LTNmZjEwMDk5YWU2YSIsImV4cCI6MTY5NDk0ODI1MCwiaXNzIjoiaHR0cDovL2xvY2FsaG9zdDoiLCJhdWQiOiJodHRwOi8vbG9jYWxob3N0OiJ9.usGppL6QpE7qMeyki1eB503n4nwIJ-xxxWMCMy6dX5o","expiration":"2023-09-17T10:57:30Z"}

    Note we need to remove the "token" , because we only need add "Bearer eyjh..."into the hearder not "Bearer ""token":"eyjh.." . So in your _identityService.LoginAsync(model) you need to return result.token , not result.

    If the answer is the right solution, please click "Accept Answer" and kindly upvote it. If you have extra questions about this answer, please click "Comment".

    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.

    Best regards,

    Qing Guo

    0 comments No comments

  3. Bruce (SqlWork.com) 66,706 Reputation points
    2023-09-18T16:02:45.37+00:00

    you could follow the ms identity approach. after token login set a login cookie with the user id and claims used by the app. they then store the access token in a cache keyed by userid. the cache could be in-memory, redis cache, or a database depending on the caching manager.

    https://learn.microsoft.com/en-us/aspnet/core/performance/caching/memory?view=aspnetcore-7.0

    0 comments No comments

  4. Jose Daniel Navarro Brito 61 Reputation points
    2023-09-18T23:15:26.6166667+00:00

    Hi Quin:

    As you said,My Web API Post method returns the result with the token word ( see below).

    [HttpPost("login")]         
    public async Task<IActionResult> Login([FromBody] LoginViewModel model)          
    {             var result = await _identityService.LoginAsync(model);            
    if (!string.IsNullOrEmpty(result?.Token))             
    {                 return Ok(result);             
    }             return Unauthorized();         }
    
    
    

    Now. The LoginAsync function comes from the code below.

     public async Task<LoginResponseViewModel> LoginAsync(LoginViewModel loginViewModel)
            {
                var user = await _userManager.FindByNameAsync(loginViewModel.Username);
                if (user != null && await _userManager.CheckPasswordAsync(user, loginViewModel.Password))
                {
                    var userRoles = await _userManager.GetRolesAsync(user);
    
                    var authClaims = new List<Claim>
                    {
                        new Claim(ClaimTypes.Name, user.UserName),
                        new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
                    };
    
                    foreach (var userRole in userRoles)
                    {
                        authClaims.Add(new Claim(ClaimTypes.Role, userRole));
                    }
    
                    var token = GetToken(authClaims);
    
                    return new LoginResponseViewModel
                    {
                        Token = new JwtSecurityTokenHandler().WriteToken(token),
                        Expiration = token.ValidTo
                    };
                }
                return new LoginResponseViewModel { };
            }
    

    The LoginResponseView model class is defined below. This is where the token property is coming from.

    public class LoginResponseViewModel
        {
            public string Token { get; set; }
            public DateTime Expiration { get; set; }
        }
    

    and the GetToken function comes from this

     private JwtSecurityToken GetToken(List<Claim> authClaims)
            {
                var authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_jWTAppSettings.Secret));
    
                var token = new JwtSecurityToken(
                    issuer: _jWTAppSettings.ValidIssuer,
                    audience: _jWTAppSettings.ValidAudience,
                    expires: DateTime.Now.AddHours(3),
                    claims: authClaims,
                    signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256)
                    );
    
                return token;
            }
    
    
    

    How get rid of the token ?

    Thanking you in advance.


Your answer

Answers can be marked as Accepted Answers by the question author, which helps users to know the answer solved the author's problem.