How to add Bearer token to a request in ASP.NET CORE

amin khosravi 21 Reputation points
2022-03-06T07:15:42.717+00:00

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);
    }

Here is Startup.cs file

public class Startup
    {
        public Startup(IConfiguration configuration)
        {
            Configuration = configuration;
        }

        public IConfiguration Configuration { get; }

        // This method gets called by the runtime. Use this method to add services to the container.
        public void ConfigureServices(IServiceCollection services)
        {
            services.AddDbContext<ApplicationDbContext>(o => o.UseSqlServer(Configuration
                .GetConnectionString("DefaultConnection")));
            services.AddScoped<IPlayerRepository, PlayerRepository>();
            services.AddScoped<IUserRepository, UserRepository>();
            services.AddAutoMapper(typeof(UserMapping));

            services.AddControllers();
            services.AddSwaggerGen(c =>
            {
                c.SwaggerDoc("v1", new OpenApiInfo { Title = "MyWebAPIProject", Version = "v1" });
            });
            services.AddAuthentication(options =>
            {

                options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
                options.DefaultSignInScheme = JwtBearerDefaults.AuthenticationScheme;

            }).AddJwtBearer(options =>
            {

                options.TokenValidationParameters = new TokenValidationParameters
                {
                    ValidateIssuerSigningKey = true,
                    IssuerSigningKey = new SymmetricSecurityKey(System.Text.Encoding.ASCII.GetBytes(
                        Configuration.GetSection("AppSettings:Token").Value)),
                    ValidateLifetime = true,
                    ValidateAudience = false,
                    ValidateIssuer = false

                };

            });
        }

        // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
        public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
        {
            if (env.IsDevelopment())
            {
                app.UseDeveloperExceptionPage();
                app.UseSwagger();
                app.UseSwaggerUI(c => c.SwaggerEndpoint("/swagger/v1/swagger.json", "MyWebAPIProject v1"));
            }

            app.UseHttpsRedirection();

            app.UseRouting();
            app.UseAuthentication();

            app.UseAuthorization();

            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
    }

appsettings file

{
  "AppSettings": {
    "Token" : "This is a token from JsonWebToken"

  },
  "Logging": {
    "LogLevel": {
      "Default": "Information",
      "Microsoft": "Warning",
      "Microsoft.Hosting.Lifetime": "Information"
    }
  },
  "AllowedHosts": "*",
  "ConnectionStrings": {
    "DefaultConnection": "server=HEISENBERG-PC;database=WEBAPIMVCProject;trusted_connection=true"

  }
}
ASP.NET Core
ASP.NET Core
A set of technologies in the .NET Framework for building web applications and XML web services.
4,246 questions
C#
C#
An object-oriented and type-safe programming language that has its roots in the C family of languages and includes support for component-oriented programming.
10,402 questions
{count} votes

2 answers

Sort by: Most helpful
  1. Rijwan Ansari 746 Reputation points MVP
    2022-03-06T17:12:23.817+00:00

    Hi

    Token is a string value, therefore, you don't need to deserialize it again. This is simply a token string which can directly send with request for authentication.

    You can update your function, and check

    public async Task<IActionResult> GetAllPlayers()
             {
                 string token = null;
                 var strToken = HttpContext.Session.GetString("JwToken");
                 if (string.IsNullOrWhiteSpace(strToken))
                 {
                     token = await CreateToken();
                 }
                 else
                 {
                     token = strToken;
                 }
                 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);
                 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);
             }
    

    Check this for reference: https://www.c-sharpcorner.com/article/jwt-json-web-token-authentication-in-asp-net-core/

    1 person found this answer helpful.

  2. AgaveJoe 26,246 Reputation points
    2022-03-06T23:04:17.737+00:00

    Working example similar to your approach.

    AuthenticateModel login = new AuthenticateModel
    {
        username = "test",
        password = "test"
    };
    
    TokenModel? token;
    
    HttpResponseMessage response = await client.PostAsJsonAsync("https://localhost:7134/Users/authenticate", login);
    using (var contentStream = await response.Content.ReadAsStreamAsync())
    {
        token = await JsonSerializer.DeserializeAsync<TokenModel>(contentStream);
    }
    
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("bearer",  token?.token);
    var RawData = await client.GetStringAsync("https://localhost:7134/Users");
    
    Console.WriteLine(RawData);
    
    0 comments No comments