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"
}
}