-2

I have an API secured by Bearer token to be consumed in a mvc project. I'm using ClientFactory to call the API in mvc. I get the generated token from WeatherForecast [HttpGet] method and use it to to access the Authorized PlayerController methods. It works fine in Postman, But when I try to access PlayerController in mvc, On running a debugger It shows Unauthorized response!

Here is the action to get and use the generated token in mvc project

        private async Task<JWTToken> CreateToken()
        {
            var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:42045/weatherforecast");
            var client = _clientFactory.CreateClient();
            HttpResponseMessage response = await client.SendAsync(request);
            var token = await response.Content.ReadAsStringAsync();
            HttpContext.Session.SetString("JwToken", token);
            return JsonConvert.DeserializeObject<JWTToken>(token);

        }
        public async Task<IActionResult> GetAllPlayers()
        {
            JWTToken token = null;
            var strToken = HttpContext.Session.GetString("JwToken");
            if (string.IsNullOrWhiteSpace(strToken))
            {
                token = await CreateToken();
            }
            else
            {
                token = JsonConvert.DeserializeObject<JWTToken>(strToken);
            }
            if (token == null || string.IsNullOrWhiteSpace(token.token) || token.expireAt <= DateTime.UtcNow)
            {
                token = await CreateToken();
            }
            List<Player> players = new List<Player>();
            var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost:42045/api/player");
            var client = _clientFactory.CreateClient();
            request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", token.token);
            HttpResponseMessage response = await client.SendAsync(request, HttpCompletionOption.ResponseHeadersRead);
            if (response.StatusCode == System.Net.HttpStatusCode.OK)
            {
                var apiString = await response.Content.ReadAsStringAsync();
                players = JsonConvert.DeserializeObject<List<Player>>(apiString);

            }
            return View(players);
        }

Here is CreateToken method in WeatherForecast controller

[HttpGet]
    

public ActionResult<string> Get()
    {
        var rng = new Random();
        var weathers = Enumerable.Range(1, 5).Select(index => new WeatherForecast
        {
            Date = DateTime.Now.AddDays(index),
            TemperatureC = rng.Next(-20, 55),
            Summary = Summaries[rng.Next(Summaries.Length)]
        });
        return Ok(new {
            expireAt = DateTime.UtcNow.AddMinutes(15), token = CreateToken()
        });
    }
    public string CreateToken()
    {
        var key = new SymmetricSecurityKey(System.Text.Encoding.ASCII.GetBytes(_configuration
            .GetSection("AppSettings:Token").Value));
        var creds = new SigningCredentials(key, SecurityAlgorithms.HmacSha256Signature);
        var token = new JwtSecurityToken(
            claims: new List<Claim>
            {
                new Claim("firstName", "Ahmad"),
                new Claim("lastName", "Zooghii")
            },
            signingCredentials: creds,
            expires: DateTime.UtcNow.AddMinutes(15)
            );
        return new JwtSecurityTokenHandler().WriteToken(token);
    }
ahamad zooghi
  • 67
  • 1
  • 8
  • 1
    You could use Fiddler to see the HTTP request details and compare them to what works in Postman if simply debugging doesn't make it obvious. There are implementation details in your code that would be necessary to know in order to answer the question. My guess is you are handling the token wrong and sending an incorrect value. – Crowcoder Mar 05 '22 at 17:29
  • @Crowcoder I just edited the post and added the method for creating token. I was wondering if there is any problem with this method – ahamad zooghi Mar 05 '22 at 18:08
  • Can you show at which point you know it goes bad in your code? For example, are you getting a *valid* token in your response? What is the token value before you make the api request; is it what you expect and valid? At the very least I would read/log the response content even if it's unsuccessful. Also, adding `IdentityModelEventSource.ShowPII = true; ` to the api might provide some more details. – ChiefTwoPencils Mar 05 '22 at 18:10
  • @ChiefTwoPencils Yeah it's valid. On running a debugger, the token value in mvc is correct. I used that token to access player controller in Postman and it worked! I put a break point just before if statement and on HttpResponseMessage and the header value in request is as expected – ahamad zooghi Mar 05 '22 at 18:16
  • Did you mean that you used the token generated by your app to call the api via postman worked well? So you think the issue should be the code you used to call the api? – Tiny Wang Mar 07 '22 at 06:34
  • @TinyWang On running a debugger, I used the generated token to access the Authorized actions and it works fine in postman. The problem is with consuming the endpoint in my mvc project – ahamad zooghi Mar 07 '22 at 09:06
  • So we can know the access token itself is correct right? Then the issue should come from the code you wrote to call the endpoint? – Tiny Wang Mar 07 '22 at 09:08
  • @TinyWang Yest the access token is correct because as I said I can access the Authorized controller on API in postman via that token – ahamad zooghi Mar 07 '22 at 09:40
  • @TinyWang Can I have your email address so you may want to take a look at the whole solution in case you have free time? – ahamad zooghi Mar 07 '22 at 09:52
  • I think you need to find the correct way to send Get request in asp.net core since your token is correct, so most of your code should be fine. – Tiny Wang Mar 07 '22 at 09:53
  • Could you pls check if you can send http request via your code or not? I assume that's the issue. By the way, does the url `http://localhost:42045/api/player` come from another project? If so, you may need to set Cors policy first. – Tiny Wang Mar 07 '22 at 10:04

1 Answers1

1

add services.AddHttpClient(); in startup.cs

And this code in controller:

private readonly IHttpClientFactory _httpClientFactory;

public HomeController(IHttpClientFactory httpClientFactory)
{
    _httpClientFactory = httpClientFactory;
}

public async Task<IActionResult> IndexAsync()
{
    var httpClient = _httpClientFactory.CreateClient();
    var token = "your_token";
    httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", token);
    HttpResponseMessage response = await httpClient.GetAsync("your_url");
    return View();
}

enter image description here

======================Cors policy========================

add below code in startup.cs -> ConfigureServices method

services.AddCors(options =>
{
    options.AddPolicy(name: "mypolicy",
                      builder =>
                      {
                          builder.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin();
                      });
});

add app.UseCors("mypolicy"); in startup.cs -> Configure method behind app.UseRouting(); line.

Tiny Wang
  • 10,423
  • 1
  • 11
  • 29
  • both of the projects are in the same solution. Sorry bro how to set Cors? in Web API project or mvc or both? – ahamad zooghi Mar 07 '22 at 10:37
  • Already done! I've done it before but I tried your sample code again and the response is the same! Unauthorized! I use that token in postman and it works fine! Wish I could send the whole solution to you, So you could take a look @TinyWang – ahamad zooghi Mar 07 '22 at 20:16
  • In your api project, startup.cs file->Configure method, add `app.UseCookiePolicy();app.UseCors(builder =>builder.AllowAnyOrigin().AllowAnyHeader().AllowAnyMethod());` to enable cors policy. And I do remembered some policy to get contact under the forum. Pls calm down sir, all the issues will be solved one day. And I recommend you that if enabled cors policy still doesn't work, you can create another controller in your MVC project and remove the authentication policy in your api project and call that api again with the new created controller, and if it worked, you switch to your own controller – Tiny Wang Mar 08 '22 at 01:34
  • Still failed! Here is the git address of my solution https://github.com/sia033007/MyWebAPIProject – ahamad zooghi Mar 08 '22 at 08:55
  • You [didn't add cors policy](https://github.com/sia033007/MyWebAPIProject/blob/fcf2aa9916b1bfac53b291f867fda6c160ab8a68/MyWebAPIProject/Startup.cs#L33) here... Your request sent from the MVC project to the API project will fail. – Tiny Wang Mar 09 '22 at 06:22
  • Yeah it's not in the repository, But I tried it in my local machine and didn't work again! – ahamad zooghi Mar 09 '22 at 07:39