CORS issue with one POST request but not another - vue.js

I've looked at a few other questions, and they aren't having quite the same problem I'm having. I have a server running at localhost:5001 and a Vue website running at localhost:8080. When I do a /inventory/login post request, I'm not getting any CORS issues, but when I do a /inventory/computers request, I'm getting the following
Access to XMLHttpRequest at 'https://localhost:5001/inventory/computers' from origin 'http://localhost:8080' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
What am I doing wrong? Here's the relevant code.
Startup.cs:
public void ConfigureServices(IServiceCollection services) {
var connection = Configuration.GetConnectionString("Inventory");
services.AddDbContextPool<InventoryContext>(options => options.UseSqlServer(connection));
services.AddControllers().AddNewtonsoftJson(options =>
options.SerializerSettings.ReferenceLoopHandling = Newtonsoft.Json.ReferenceLoopHandling.Ignore);
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme).AddJwtBearer(options => {
options.RequireHttpsMetadata = false;
options.SaveToken = true;
options.TokenValidationParameters = new TokenValidationParameters() {
ValidateIssuer = true,
ValidateAudience = true,
ValidAudience = Configuration["Jwt:Audience"],
ValidIssuer = Configuration["Jwt:Issuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:Key"]))
};
});
services.AddCors(options => {
options.AddPolicy("AllowSpecificOrigin", builder => {
builder.WithOrigins("localhost")
.AllowAnyOrigin()
.AllowAnyHeader()
.AllowAnyMethod();
});
});
}
// 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.UseHttpsRedirection();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseCors();
app.UseEndpoints(endpoints => {
endpoints.MapControllers();
});
}
}
LoginController:
[Route("inventory/[controller]")]
[ApiController]
[EnableCors("AllowSpecificOrigin")]
public class LoginController : ControllerBase {
public IConfiguration _configuration;
private readonly InventoryContext _context;
public LoginController(IConfiguration config, InventoryContext context) {
_configuration = config;
_context = context;
}
[HttpPost]
public async Task<IActionResult> Post(LoginRequest req) {
if (req != null && req.Username != null && req.Password != null) {
User user = await _context.Users.FirstOrDefaultAsync(u => u.Username == req.Username);
if (user == null || !Crypto.VerifyHashedPassword(user.HashedPassword, req.Password)) {
return BadRequest("Invalid username or password.");
}
var claims = new[] {
new Claim(JwtRegisteredClaimNames.Sub, _configuration["Jwt:Subject"]),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
new Claim(JwtRegisteredClaimNames.Iat, DateTime.UtcNow.ToString()),
new Claim("EmployeeID", user.EmployeeId.ToString()),
new Claim("Username", user.Username),
};
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]));
var signIn = new SigningCredentials(key, SecurityAlgorithms.HmacSha256);
var token = new JwtSecurityToken(_configuration["Jwt:Issuer"], _configuration["Jwt:Audience"], claims, expires: DateTime.UtcNow.AddDays(1), signingCredentials: signIn);
return Ok(new JwtSecurityTokenHandler().WriteToken(token));
}
else {
return BadRequest();
}
}
ComputerController:
[Authorize]
[Route("inventory/[controller]")]
[ApiController]
[EnableCors("AllowSpecificOrigin")]
public class ComputersController : ControllerBase {
private readonly InventoryContext _context;
public ComputersController(InventoryContext context) {
_context = context;
}
// POST: api/Computers
// To protect from overposting attacks, enable the specific properties you want to bind to, for
// more details, see https://go.microsoft.com/fwlink/?linkid=2123754.
[EnableCors("AllowSpecificOrigin")]
[HttpPost]
public async Task<ActionResult<Computer>> PostComputer(ComputerPostRequest req) {
Item item = new Item("Computer");
_context.Items.Add(item);
await _context.SaveChangesAsync();
Computer computer = new Computer(item.ItemId, req.SelectBankcardSerialNumber, req.ManufacturerSerialNumber, req.Model, req.Name, req.Value, req.EmployeeID, req.DateObtained);
_context.Computers.Add(computer);
if (!String.IsNullOrEmpty(req.Notes)) {
Note note = new Note(computer.ComputerId, req.Notes, DateTime.Now);
_context.Notes.Add(note);
}
await _context.SaveChangesAsync();
return CreatedAtAction("GetComputer", new { id = computer.ComputerId }, computer);
}
And the Vue code:
Login.vue
async login() {
if (this.isEmpty(this.username) || this.isEmpty(this.password)) {
this.incorrect = true;
console.log("Something's wrong");
return false;
}
try {
let res = await axios.post('https://localhost:5001/inventory/login', {
username: this.username,
password: this.password
});
this.$root.$authToken = "Bearer " + res.data;
} catch (error) {
console.log(error);
}
}
Computers.vue:
async upload() {
if (this.isEmpty(this.sbSerialNum) || this.isEmpty(this.mSerialNum) || this.isEmpty(this.compModel) || this.isEmpty(this.compName) ||
this.value === 0.0 || this.empID === 0 || this.isEmpty(this.dateObtained) || this.isEmpty(this.notes)) {
this.incorrect = true;
console.log("Something's wrong");
return false;
}
try {
const options = {
headers: {'Authorization': this.$root.$authToken}
};
let res = await axios.post('https://localhost:5001/inventory/computers', {
SelectBankcardSerialNumber: this.sbSerialNum,
ManufacturerSerialNumber: this.mSerialNum,
Name: this.compName,
Model: this.compModel,
Value: this.value,
EmployeeID: this.empID,
DateObtained: this.dateObtained,
Notes: this.notes
}, options);
this.computerAdded = res.data;
} catch (error) {
console.log(error);
}

You can try to move AddCors to the top of ConfigureServices method and just for the test pourposes I would use this
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(o => o.AddPolicy("AllowSpecificOrigin", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
}));
.....
}
only if it works, I would try to use specific origins.
You have to place UseCors between UseRouting and UseAutorization
app.UseRouting();
app.UseCors("AllowSpecificOrigin");
app.UseAuthorization();

Related

Postman post request error "The Route Data field is required" and " The HttpContext field is required."

post request
{
"FullName":"123",
"Password":"123"
}
Here is the postman error.
{
"type": "https://tools.ietf.org/html/rfc7231#section-6.5.1",
"title": "One or more validation errors occurred.",
"status": 400,
"traceId": "00-c6c66dedbd981c409a0b5011bfc83ca7-0c6499593cff6f4b-00",
"errors": {
"ControllerContext.RouteData": [
"The RouteData field is required."
],
"ControllerContext.HttpContext": [
"The HttpContext field is required."
]
}
}
'''
My project was crushed and I rewrite it. My Database is already the past one. And I made the migration and update the database. When I was trying to log in with exists user I can. But when I try to register using angular or postman it gives an error. I can not handle the problem and I searched then I got nothing to do.
here my register method:
public async Task<Object> PostUser(UserModel model)
{
var user = new User()
{
FullName = model.FullName,
};
try
{
var result = await _userManager.CreateAsync(user, model.Password);
return Ok(result);
}
catch (Exception ex)
{
throw ex;
}
}
Startup.cs
public void ConfigureServices(IServiceCollection services)
{
services.AddRazorPages();
services.AddCors(o => o.AddPolicy("AllowAnyCorsPolicy", builder =>
{
builder.AllowAnyOrigin()
.AllowAnyMethod()
.AllowAnyHeader();
}));
//D.injection
services.Configure<ApplicationSettings>(Configuration.GetSection("ApplicationSettings"));
services.AddDbContext<AuthenticationContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("IdentityConnection")));
services.AddIdentity<User, IdentityRole>().AddEntityFrameworkStores<AuthenticationContext>();
services.Configure<IdentityOptions>(options =>
{
options.Password.RequireDigit = false;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireLowercase = false;
options.Password.RequireUppercase = false;
options.Password.RequiredLength = 4;
});
//JWT Auth
var key = Encoding.UTF8.GetBytes(Configuration["ApplicationSettings:JWT_Secret"].ToString());
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = true;
x.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = 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();
}
else
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseRouting();
app.UseCors(builder =>
builder.WithOrigins(Configuration["ApplicationSettings:Client_URL"].ToString())
.AllowAnyHeader()
.AllowAnyMethod()
);
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapRazorPages();
endpoints.MapControllers();
});
}

.NET Authentication user via cookie and not via header Bearer

I am looking for a way to authenticate the user via a JWT cookie and not through the authorization header.
I have been looking around but couldn't find an answer I managed to work with.
Currently I am authenticating like this:
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(opt =>
{
opt.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = key,
ValidateIssuer = false,
ValidateAudience = false,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
opt.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var accessToken = context.Request.Query["access_token"];
var path = context.HttpContext.Request.Path;
if (!string.IsNullOrEmpty(accessToken) && (path.StartsWithSegments("/chat")))
{
context.Token = accessToken;
}
return Task.CompletedTask;
}
};
});
What is the equivalent to authenticating the same way but with a cookie called JWT for instance?
Here is a whole working demo you could follow:
Generate token:
[Route("api/[Controller]")]
[ApiController]
public class ValuesController : ControllerBase
{
private IConfiguration _config;
public ValuesController(IConfiguration config)
{
_config = config;
}
[Route("GenerateToken")]
public async Task<IActionResult> GenerateToken()
{
//add claims by yourself...
var claims = new List<Claim>
{
new Claim(ClaimTypes.Role, "Admin")
};
var token = new JwtSecurityToken(_config["Jwt:JwtIssuer"],
_config["Jwt:JwtIssuer"],
claims: claims,
expires: DateTime.Now.AddDays(5),
signingCredentials: new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_config["Jwt:JwtKey"])),
SecurityAlgorithms.HmacSha256));
var data = new JwtSecurityTokenHandler().WriteToken(token);
HttpContext.Response.Cookies.Append("access_token", data, new CookieOptions { HttpOnly = true });
return Ok(new { data });
}
}
Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
var tokenValidationParameters = new TokenValidationParameters()
{
ValidIssuer = Configuration["Jwt:JwtIssuer"],
ValidAudience = Configuration["Jwt:JwtIssuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(Configuration["Jwt:JwtKey"])),
ValidateIssuer = true,
ValidateAudience = true,
ValidateIssuerSigningKey = true,
};
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = tokenValidationParameters;
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
var token = context.HttpContext.Request.Cookies["access_token"];
if (!string.IsNullOrEmpty(token))
{
context.Token = token;
return Task.CompletedTask;
}
return Task.CompletedTask;
}
};
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
//...
app.UseRouting();
app.UseAuthentication(); //the middleware order must like here
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
appsettings.json:
{
"jwt": {
"JwtKey": "JWT_KEYsomethingyouwantwhichissecurewillworkk",
"JwtIssuer": "https://xxxxxx.com",
"JwtExpireDays": 15
}
}
After you hit the generate token method, you could set the cookie for the token. Then you can access the method which is declared by authorize attribute:
[ApiController]
[Route("[controller]")]
public class WeatherForecastController : ControllerBase
{
[Authorize] //be sure add this...
[HttpGet]
public string Get()
{
return "Got in";
}
}
Result:

Asp.Net core Authorization with Bearer token status Unauthorized 401 with Valid token

public class User: IdentityUser
{
// ... code here
}
[HttpPost]
[Route("Login")]
//POST: /api/User/Login
public async Task<IActionResult> Login(LoginModel model)
{
var user = await _UserManager.FindByEmailAsync(model.Email);
if (user != null && await _UserManager.CheckPasswordAsync(user, model.Password))
{
var tokenDescriptor = new SecurityTokenDescriptor
{
Subject = new ClaimsIdentity(
new Claim[]
{
new Claim("UserID", user.Id.ToString())
}),
Expires = DateTime.UtcNow.AddDays(5),
SigningCredentials = new SigningCredentials(new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_ApplicationSettings.JWT_Secret)), SecurityAlgorithms.HmacSha256Signature)
};
var tokenHandler = new JwtSecurityTokenHandler();
var securityToken = tokenHandler.CreateToken(tokenDescriptor);
var token = tokenHandler.WriteToken(securityToken);
return Ok(new { token });
}
else
{
return BadRequest(new { message = "Username or password is incorrect" });
}
}
}
[HttpGet]
[Authorize]
//GET: /api/UserProfile
public async Task<Object> GetUserProfile()
{
var t = User.Claims.Count();
string userId = User.Claims.First(c => c.Type == "UserID").Value;
var user = await _UserManager.FindByIdAsync(userId);
return new
{
user.FirstName,
user.LastName,
user.Email,
user.ProfileType
};
}
}
When I try to get the connected user with the returned token (using postman), I always get status 401 Unathorized.
Also, i found out that User.Claims.Count() is 0 ( i did this by commenting the in order to see what's wrong [Authorize]).
Does anyone know what the issue is?
Thanks!
EDIT: App configuration
public void ConfigureServices(IServiceCollection services)
{
//Inject AppSettings
services.Configure<ApplicationSettings>(Configuration.GetSection("ApplicationSettings"));
services.AddControllers();
services.AddDbContext<AuthentificationContext>(
options =>
{
options.UseMySql(Configuration.GetConnectionString("IdentityConnection"));
});
services.AddDefaultIdentity<User>()
.AddEntityFrameworkStores<AuthentificationContext>();
services.Configure<IdentityOptions>(options =>
{
options.Password.RequireDigit = false;
options.Password.RequireNonAlphanumeric = false;
options.Password.RequireLowercase = false;
options.Password.RequireUppercase = false;
options.Password.RequiredLength = 6;
options.User.RequireUniqueEmail = true;
}
);
services.AddCors();
//jwt authentification
var key = Encoding.UTF8.GetBytes(Configuration["ApplicationSettings:JWT_Secret"].ToString());
services.AddAuthentication(x =>
{
x.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
x.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(x =>
{
x.RequireHttpsMetadata = false;
x.SaveToken = false;
x.TokenValidationParameters = new Microsoft.IdentityModel.Tokens.TokenValidationParameters
{
ValidateIssuerSigningKey = true,
IssuerSigningKey = new SymmetricSecurityKey(key),
ValidateIssuer = false,
ValidateAudience = false,
ClockSkew = TimeSpan.Zero
};
});
services.Configure<CookiePolicyOptions>(options =>
{
services.AddHttpContextAccessor();
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
});
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
app.Use(async (ctx, next) =>
{
await next();
if (ctx.Response.StatusCode == 204)
{
ctx.Response.ContentLength = 0;
}
});
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseCors(options =>
options.WithOrigins(Configuration["ApplicationSettings:Client_URL"].ToString())
.AllowAnyMethod()
.AllowAnyHeader());
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.UseAuthentication();
}
}
You should pay attention to the middleware order that put app.UseAuthentication(); before app.UseAuthorization();
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();

With JWT token and policy set, I get unauthorized 401

I follow the tutorial link below.
https://fullstackmark.com/post/13/jwt-authentication-with-aspnet-core-2-web-api-angular-5-net-core-identity-and-facebook-login
I am trying to understand how it works and I want to use role-based authentication using this token. so I made another policy in the Startup.cs file as below.
And I tried to use it like [Authorize(Policy = "admin")] the controller but every time I try I get unauthenticated using postman.
What am I missing? how to make roles-based authentication based on the tutorial?
Configure
public void ConfigureServices(IServiceCollection services)
{
services.AddCors(options =>
{
options.AddPolicy("CorsPolicy",
builder => builder.WithOrigins("http://localhost:4200", "http://localhost:44318")
.AllowAnyMethod()
.AllowAnyHeader()
.AllowCredentials());
});
var jwtAppSettingOptions = Configuration.GetSection(nameof(JwtIssuerOptions));
// Configure JwtIssuerOptions
services.Configure<JwtIssuerOptions>(options =>
{
options.Issuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
options.Audience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)];
options.SigningCredentials = new SigningCredentials(_signingKey, SecurityAlgorithms.HmacSha256);
});
var tokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)],
ValidateAudience = true,
ValidAudience = jwtAppSettingOptions[nameof(JwtIssuerOptions.Audience)],
ValidateIssuerSigningKey = true,
IssuerSigningKey = _signingKey,
RequireExpirationTime = false,
ValidateLifetime = true,
ClockSkew = TimeSpan.Zero
};
services.AddAuthentication(options =>
{
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(configureOptions =>
{
configureOptions.ClaimsIssuer = jwtAppSettingOptions[nameof(JwtIssuerOptions.Issuer)];
configureOptions.TokenValidationParameters = tokenValidationParameters;
configureOptions.SaveToken = true;
});
// api user claim policy
services.AddAuthorization(options =>
{
options.AddPolicy("ApiUser", policy => policy.RequireClaim(Constants.Strings.JwtClaimIdentifiers.Rol, Constants.Strings.JwtClaims.ApiAccess));
});
services.AddAuthorization(options =>
options.AddPolicy("admin", policy => policy.RequireRole("admin"))
);
var builder = services.AddIdentityCore<AppUser>(o =>
{
// configure identity options
o.Password.RequireDigit = false;
o.Password.RequireLowercase = false;
o.Password.RequireUppercase = false;
o.Password.RequireNonAlphanumeric = false;
o.Password.RequiredLength = 6;
});
builder = new IdentityBuilder(builder.UserType, typeof(IdentityRole), builder.Services);
builder.AddEntityFrameworkStores<CDSPORTALContext>().AddDefaultTokenProviders().AddRoles<IdentityRole>();
//.AddRoles<IdentityRole>()
services.AddControllers();
services.AddAutoMapper(typeof(Startup));
services.AddSingleton<IJwtFactory, JwtFactory>();
services.TryAddTransient<IHttpContextAccessor, HttpContextAccessor>();
services.AddScoped<IRegionRepository, RegionRepository>();
services.AddScoped<IRegionService, RegionService>();
services.AddScoped<IEmailHelper, EmailHelper>();
}
// 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.UseCors("CorsPolicy");
app.UseExceptionHandler(
builder =>
{
builder.Run(
async context =>
{
context.Response.StatusCode = (int)HttpStatusCode.InternalServerError;
context.Response.Headers.Add("Access-Control-Allow-Origin", "*");
var error = context.Features.Get<IExceptionHandlerFeature>();
if (error != null)
{
context.Response.AddApplicationError(error.Error.Message);
await context.Response.WriteAsync(error.Error.Message).ConfigureAwait(false);
}
});
});
app.UseRouting();
app.UseStaticFiles();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
app.UseSpa(spa =>
{
spa.Options.SourcePath = "Client";
spa.UseAngularCliServer(npmScript: "start");
});
}
}
Auth Controller
// POST api/auth/login
[HttpPost("login")]
public async Task<IActionResult> Post([FromBody]CredentialsViewModel credentials)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var identity = await GetClaimsIdentity(credentials.UserName, credentials.Password);
if (identity == null)
{
//return null;
return BadRequest(Error.AddErrorToModelState("login_failure", "Invalid username or password.", ModelState));
}
var id = identity.Claims.Single(c => c.Type == "id").Value;
var user = await _userManager.FindByIdAsync(id);
IList<string> role = await _userManager.GetRolesAsync(user);
var jwt = await Tokens.GenerateJwt(identity, role[0], _jwtFactory, credentials.UserName, _jwtOptions, new JsonSerializerSettings { Formatting = Formatting.Indented });
return new OkObjectResult(jwt);
}
I tried with all method and none of them working
[Authorize(Policy = "ApiUser")]
[HttpGet("getPolicy")]
public string GetPolicy()
{
return "policyWorking";
}
[Authorize(Roles = "admin")]
[HttpGet("getAdmin")]
public string GetAdmin()
{
return "adminWorking";
}
[Authorize ]
[HttpGet("getAuthorize")]
public string GetAuthorize()
{
return "normal authorize Working";
}
Decoded Token
"jti": "840d507d-b2d0-454b-bd1f-007890d3e669",
"iat": 1587699300,
"rol": "api_access",
"id": "1ac370e2-f5e9-4404-b017-8a3c087e2196",
"nbf": 1587699299,
"exp": 1587706499
I forgot to add this to appsetting.
"JwtIssuerOptions": {
"Issuer": "webApi",
"Audience": "http://localhost:4200/"
}

The SignalR interferes with the another controller

As soon as I connect the SignalR to the application using Install-package Microsoft.AspNetCore.SignalR immediately stops working the POST method of one of the controllers. Without a signal, all works fine. Startup.cs:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<ApplicationDbContext>(options => options.UseMySql(configuration.GetConnectionString("DefaultConnection")));
var section = configuration.GetSection("AppSettings");
var settings = section.Get<AppSettings>();
services.Configure<AppSettings>(section);
var builder = services.AddIdentityCore<ApplicationUser>(user =>
{
user.Password.RequireDigit = true;
user.Password.RequireLowercase = false;
user.Password.RequireUppercase = false;
user.Password.RequireNonAlphanumeric = false;
user.Password.RequiredLength = 6;
});
builder = new IdentityBuilder(builder.UserType, typeof(IdentityRole), builder.Services);
builder.AddSignInManager<SignInManager<ApplicationUser>>();
builder.AddRoleValidator<RoleValidator<IdentityRole>>();
builder.AddRoleManager<RoleManager<IdentityRole>>();
builder.AddEntityFrameworkStores<ApplicationDbContext>();
builder.AddDefaultTokenProviders();
services.AddCors(options => options.AddPolicy("CorsPolicy", policy =>
{
policy
.AllowAnyMethod()
.AllowAnyHeader()
.AllowAnyOrigin()
.AllowCredentials();
}));
services.AddSignalR();
services.AddOData();
services.AddMvc();
services.AddAuthentication(JwtBearerDefaults.AuthenticationScheme)
.AddJwtBearer(options =>
{
options.TokenValidationParameters = new TokenValidationParameters
{
ValidateIssuer = true,
ValidateAudience = true,
ValidateLifetime = true,
ValidateIssuerSigningKey = true,
ValidIssuer = settings.issuer,
ValidAudience = settings.issuer,
IssuerSigningKey = JwtSecurityKey.Create(settings.key)
};
options.Events = new JwtBearerEvents
{
OnMessageReceived = context =>
{
if (context.Request.Path.Value.StartsWith("/chatHub") &&
context.Request.Query.TryGetValue("token", out StringValues token)
)
{
context.Token = token;
}
return Task.CompletedTask;
},
OnAuthenticationFailed = context =>
{
Console.WriteLine("OnAuthenticationFailed: " + context.Exception.Message);
return Task.CompletedTask;
},
OnTokenValidated = context =>
{
Console.WriteLine("OnTokenValidated: " + context.SecurityToken);
return Task.CompletedTask;
}
};
});
services.AddAuthorization(options =>
{
options.AddPolicy("user", policy => policy.RequireClaim("id"));
});
services.AddSingleton<ISendGridClient, SendGridClient>(serviceProvider =>
{
return new SendGridClient(settings.sendGridKey);
});
services.AddSingleton<ILogger>(serviceProvider =>
{
return loggerFactory.CreateLogger("logger");
});
services.AddSingleton<IEmailSender, EmailSender>();
services.AddSingleton<IUploader, Uploader>();
}
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseBrowserLink();
app.UseDeveloperExceptionPage();
app.UseDatabaseErrorPage();
}
else
{
app.UseExceptionHandler("/Error");
}
app.UseStaticFiles();
app.UseAuthentication();
app.UseCors("CorsPolicy");
app.UseSignalR(routes =>
{
routes.MapHub<SignalRHub>("/chatHub");
});
app.UseMvc(routebuilder =>
{
routebuilder.MapRoute(name: "DefaultApi", template: "api/{controller=Home}/{action=Index}/{id?}");
});
}
Controller:
[Authorize(Policy = "user")]
public class UserFilesController : Controller
{
[HttpPost]
public async Task<IActionResult> SaveAvatar(AvatarModel avatar)
{
// Some code here, here the call does not even come
}
}
Calling in JavaScript
$.ajax({
method: 'POST',
url: serviceUrl + 'api/userfiles/saveavatar',
data: data,
headers: getHeaders()
}).done(function (UploadResult) {
// some code here
});