I have an ASP.NET Core 5.0 API that uses JWT authentication.
All I want it to do, for now, is to read tokens in the button
@Html.ActionLink("Test","Oper","Home")
and it's [Authorize]
header and validate them against my criteria. I don't know what missed but it is always returning HTTP 401 code.
Test add this code
app.UseCors(x => x.AllowAnyHeader()
.AllowAnyMethod()
.WithOrigins("https://localhost:4200"));
Error:
System.InvalidOperationException: The CORS protocol does not allow specifying a wildcard (any) origin and credentials at the same time. Configure the CORS policy by listing individual origins if credentials needs to be supported.
The connection to the terminal's pty host process is unresponsive, the terminals may stop working
It's not an Angular project.
This is Startup.cs
:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.HttpsPolicy;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.FileProviders;
using System.IO;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using Microsoft.AspNetCore.Authentication.JwtBearer;
namespace JWTtokenMVC
{
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.AddControllersWithViews();
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy", builder => builder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader().AllowCredentials().Build());
});
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.IncludeErrorDetails = true;
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType ="http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name",
RoleClaimType ="http://schemas.microsoft.com/ws/2008/06/identity/claims/role",
ValidateIssuer = true,
ValidateAudience = false,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = Configuration["Jwt:Issuer"],
ValidAudience = Configuration["Jwt:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"])
)
};
});
}
// 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();
}
else
{
app.UseExceptionHandler("/Home/Error");
// The default HSTS value is 30 days. You may want to change this for production scenarios, see https://aka.ms/aspnetcore-hsts.
app.UseHsts();
}
app.UseHttpsRedirection();
app.UseStaticFiles();
app.UseStaticFiles(new StaticFileOptions
{
FileProvider = new PhysicalFileProvider(Path.Combine(Directory.GetCurrentDirectory(), "Test_modules")),
RequestPath = "/" + "Test_modules"
});
app.UseCookiePolicy();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseCors(x => x.AllowAnyHeader()
.AllowAnyMethod()
.WithOrigins("https://localhost:4200"));
app.UseEndpoints(endpoints =>
{
endpoints.MapControllerRoute(
name: "default",
pattern: "{controller=Home}/{action=Index}/{id?}");
});
}
}
}
This is HomeController.cs
- login get Jwt Token is OK:
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using JWTtokenMVC.Models;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using Microsoft.Extensions.Configuration;
using JWTtokenMVC.Models.Test;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
namespace JWTtokenMVC.Controllers
{
public class HomeController : Controller
{
private IConfiguration _config;
public HomeController(IConfiguration config)
{
_config = config;
}
public IActionResult Index()
{
return View();
}
public IActionResult Privacy()
{
return View();
}
[ResponseCache(Duration = 0, Location = ResponseCacheLocation.None, NoStore = true)]
public IActionResult Error()
{
return View(new ErrorViewModel { RequestId = Activity.Current?.Id ?? HttpContext.TraceIdentifier });
}
private string GenerateJSONWebToken(UserPaul userinfo)
{
var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:Key"]));
var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256);
var claims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub,userinfo.Username),
new Claim(JwtRegisteredClaimNames.Email,userinfo.Email),
new Claim(JwtRegisteredClaimNames.Jti,Guid.NewGuid().ToString()),
};
var token = new JwtSecurityToken(
issuer: _config["Jwt:Issuer"],
audience: _config["Jwt:Issuer"],
claims,
expires: DateTime.Now.AddMinutes(10),
signingCredentials: credentials
);
var encodetoken = new JwtSecurityTokenHandler().WriteToken(token);
var cookieOptions = new CookieOptions();
//cookieOptions.Expires = DateTimeOffset.UtcNow.AddHours(12);//you can set this to a suitable timeframe for your situation
cookieOptions.HttpOnly = true;
cookieOptions.Expires = DateTime.Now.AddMinutes(1);
//cookieOptions.Domain = Request.Host.Value;
cookieOptions.Path = "/";
Response.Cookies.Append("jwt", encodetoken, cookieOptions);
return encodetoken;
}
[HttpPost]
public IActionResult Login()
{
string AccountNumber="TestUser";
JWTtokenMVC.Models.TestContext userQuery = new JWTtokenMVC.Models.TestContext();
var query = userQuery.Testxxxx.Where(N => N.UserId ==AccountNumber).FirstOrDefault();
IActionResult response = Unauthorized();
if (query != null)
{
var tokenStr = GenerateJSONWebToken(query);
response = Ok(new { token = tokenStr });
}
return response;
}
[Authorize]
[HttpGet("Home/Oper")]
public IActionResult Oper()
{
var authenticationCookieName = "jwt";
var cookie = HttpContext.Request.Cookies[authenticationCookieName];
List<Test_SHOW> sHOWs = new List<Test_SHOW>();
JWTtokenMVC.Models.Test.TestContext userQuery= new JWTtokenMVC.Models.Test.TestContext();
var query = userQuery.Test.Select(T => new Test_SHOW
{
number= T.number,
name= T.name,
mail= T.mail
}).OrderBy(o => o.Iid);
sHOWs.AddRange(query);
return View("Views/Home/Oper.cshtml", sHOWs);
}
}
}
This is Test.cshtml
:
@{
ViewBag.Title = "Home Page";
}
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
@functions{
public string GetAntiXsrfRequestToken()
{
return Xsrf.GetAndStoreTokens(Context).RequestToken;
}
}
<input type="hidden" id="RequestVerificationToken"
name="RequestVerificationToken" value="@GetAntiXsrfRequestToken()">
<form method="post" asp-antiforgery="false">
<!--form -->
<div>
<span style="color:red">@ViewBag.Msg</span>
</div>
<div class="col-md-4 select-outline">
</div>
<button type="button" class="btn btn-light">@Html.ActionLink("Test","Oper","Home")</button>
<button type="button" class="btn btn-light">@Html.ActionLink("TestLogin","Login","Home")</button>
</form>
And finally this is Oper.cshtml
:
@using JWTtokenMVC.Models.Test
@model List<Test_SHOW>
@{
ViewBag.Title = "test";
}
<h2>Test List</h2>
<table class="table table-hover">
<tr>
<th>
number
</th>
<th>
name
</th>
<th>
mail
</th>
</tr>
@foreach (var item in Model)
{
<tr>
<td>
@Html.DisplayFor(modelItem => item.number)
</td>
<td>
<span class='text-danger'>@Html.DisplayFor(modelItem => item.name)</span>
</td>
<td>
<span class='text-danger'>@Html.DisplayFor(modelItem => item.mail)</span>
</td>
</tr>
}
</table>
Here is my appsettings.json
file:
{
"Logging": {
"LogLevel": {
"Default": "TestInformation",
"Microsoft": "TestWarning",
"Microsoft.Hosting.Lifetime": "TestInformation"
}
},
"AllowedHosts": "*",
"Jwt": {
"Key": "TestProdigy",
"Issuer": "Test.mail.com"
}
}