AuthorizeView Roles doesn't recognize role even though the code does - asp.net

I'm trying to set up authorization with Blazor .net core 3.1 and the AuthorizeView Roles doesn't seem to recognize the role that is in the database. On the other hand, if I try to do it in code and I've set up a little message if it finds the role with the user, it finds the role and displays the ""User is a Valid User" message. I'm using this with AzureAd Microsoft authentication and AspNetCore identity package.
Here's the index page code
#page "/"
#using Microsoft.AspNetCore.Authorization;
#using Microsoft.AspNetCore.Identity;
#inject UserManager<IdentityUser> _UserManager
#inject RoleManager<IdentityRole> _RoleManager
#inject AuthenticationStateProvider AuthenticationStateProvider
#attribute [Authorize]
<span>#Message</span>
<AuthorizeView Roles="Users">
<Authorized>
<p>Youre In!</p>
</Authorized>
</AuthorizeView>
#code
{
[CascadingParameter]
private Task<AuthenticationState> authStateTask { get; set; }
string USER_ROLE = "Users";
string CurrentEmail;
string Message;
protected override async Task OnInitializedAsync()
{
var authState = await authStateTask;
var CurrentEmail = authState.User.Identity.Name;
if (CurrentEmail.Contains("#users.com") == true)
{
var user = await _UserManager.FindByNameAsync(CurrentEmail);
if (user == null)
{
var newUser = new IdentityUser { UserName = CurrentEmail, Email = CurrentEmail };
var createResult = await _UserManager.CreateAsync(newUser);
if (createResult.Succeeded)
{
var roleResult = await _UserManager.AddToRoleAsync(newUser, USER_ROLE);
if (roleResult.Succeeded)
{
Message = ("Good job");
}
}
}
else
{
var RoleResult = await _UserManager.IsInRoleAsync(user, USER_ROLE);
if(RoleResult == true)
{
Message = "User is a Valid User";
}
else
{
Message = "User is invalid";
}
}
}
}
}
Here are my services:
public void ConfigureServices(IServiceCollection services)
{
services.AddDbContext<AppDbContext>(options => options.UseSqlite("DataSource=db.db"));
services.AddDefaultIdentity<IdentityUser>()
.AddRoles<IdentityRole>()
.AddEntityFrameworkStores<AppDbContext>();
services.AddAuthentication(AzureADDefaults.AuthenticationScheme)
.AddAzureAD(options => Configuration.Bind("AzureAd", options));
services.AddControllersWithViews(options =>
{
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
options.Filters.Add(new AuthorizeFilter(policy));
});
services.AddScoped<AuthenticationStateProvider, ServerAuthenticationStateProvider>();
services.AddRazorPages();
services.AddServerSideBlazor();
services.AddSingleton<WeatherForecastService>();
}

Related

Custom AuthenticationStateProvider in blazor project doesn't work on server side

Hi all!
I'm trying to make my custom auth mode in Blazor WebAssembly App (this is where studio creates 3 projects - client, server, shared). Idea is avoid IS4 auth and make my oun "internal" user for test purposes and understand the work of auth mech as well. I'm doing it by creating my custom AuthenticationStateProvider? like it shown in official docs. This is my AuthenticationStateProvider class:
public class CustomAuthStateProvider : AuthenticationStateProvider
{
private bool _isLoggedIn = true;
//this is a parameter defininng whether user logged in or not
//changed by reflection
public bool IsLoggedIn
{
get
{
return _isLoggedIn;
}
set
{
_isLoggedIn = value;
NotifyAuthenticationStateChanged(GetAuthenticationStateAsync());
}
}
private static CustomAuthStateProvider _myInstance = null;
public Serilog.ILogger _logger { get; set; }
public override Task<AuthenticationState> GetAuthenticationStateAsync()
{
ClaimsIdentity identity;
Task<AuthenticationState> rez;
if (IsLoggedIn)
{
identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, "User01"),
}, "Fake authentication type");
}
else
{
identity = new ClaimsIdentity();
}
var user = new ClaimsPrincipal(identity);
rez = Task.FromResult(new AuthenticationState(user));
return rez;
}
public static CustomAuthStateProvider GetMyInstance(Serilog.ILogger logger = null, string mySide = "")
{
//implementing singleton
if (_myInstance == null)
{
_myInstance = new CustomAuthStateProvider();
_myInstance._logger = logger;
}
return _myInstance;
}
}
This is how i plug it on client side (program.cs)
builder.Services.AddSingleton<AuthenticationStateProvider>(x => CustomAuthStateProvider.GetMyInstance(Log.Logger, "Client"));
This is how i plug it on server side (startup.cs)
services.AddSingleton<AuthenticationStateProvider, CustomAuthStateProvider>();
Problem:
it works fine on client side, that means i can login, logout and use AutorizeView and similar tags. But It doesnt' t work on server side, that means HttpContext.User doesn't see any user authenticated and i cant use [Authorize] and similar attributes. What i'm doing wrong? How HttpContext.User is connected to AuthenticationStateProvider in asp.net core project?
Thanks ;-)
Here's a very simple Test AuthenticationStateProvider I hashed up recently for a Server Side project.
using Microsoft.AspNetCore.Components.Authorization;
using System.Security.Claims;
using System.Threading.Tasks;
namespace Blazor.Auth.Test
{
public class TestAuthenticationStateProvider : AuthenticationStateProvider
{
public TestUserType UserType { get; private set; } = TestUserType.None;
private ClaimsPrincipal Admin
{
get
{
var identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Sid, "985fdabb-5e4e-4637-b53a-d331a3158680"),
new Claim(ClaimTypes.Name, "Administrator"),
new Claim(ClaimTypes.Role, "Admin")
}, "Test authentication type");
return new ClaimsPrincipal(identity);
}
}
private ClaimsPrincipal User
{
get
{
var identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Sid, "024672e0-250a-46fc-bd35-1902974cf9e1"),
new Claim(ClaimTypes.Name, "Normal User"),
new Claim(ClaimTypes.Role, "User")
}, "Test authentication type");
return new ClaimsPrincipal(identity);
}
}
private ClaimsPrincipal Visitor
{
get
{
var identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Sid, "3ef75379-69d6-4f8b-ab5f-857c32775571"),
new Claim(ClaimTypes.Name, "Visitor"),
new Claim(ClaimTypes.Role, "Visitor")
}, "Test authentication type");
return new ClaimsPrincipal(identity);
}
}
private ClaimsPrincipal Anonymous
{
get
{
var identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Sid, "0ade1e94-b50e-46cc-b5f1-319a96a6d92f"),
new Claim(ClaimTypes.Name, "Anonymous"),
new Claim(ClaimTypes.Role, "Anonymous")
}, null);
return new ClaimsPrincipal(identity);
}
}
public override Task<AuthenticationState> GetAuthenticationStateAsync()
{
var task = this.UserType switch
{
TestUserType.Admin => Task.FromResult(new AuthenticationState(this.Admin)),
TestUserType.User => Task.FromResult(new AuthenticationState(this.User)),
TestUserType.None => Task.FromResult(new AuthenticationState(this.Anonymous)),
_ => Task.FromResult(new AuthenticationState(this.Visitor))
};
return task;
}
public Task<AuthenticationState> ChangeUser(TestUserType userType)
{
this.UserType = userType;
var task = this.GetAuthenticationStateAsync();
this.NotifyAuthenticationStateChanged(task);
return task;
}
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace Blazor.Auth.Test
{
public enum TestUserType
{
None,
Visitor,
User,
Admin
}
}
Startup regstration:
services.AddScoped<AuthenticationStateProvider, TestAuthenticationStateProvider>();
Simple Component I add to NavMenu to switch users.
<AuthorizeView>
<Authorized>
<div class="m-1 p-1 text-white">
#user.Identity.Name
</div>
</Authorized>
<NotAuthorized>
<div class="m-1 p-1 text-white">
Not Logged In
</div>
</NotAuthorized>
</AuthorizeView>
<div class="m-1 p-3">
<select class="form-control" #onchange="ChangeUser">
#foreach (var value in Enum.GetNames(typeof(TestUserType)))
{
<option value="#value">#value</option>
}
</select>
</div>
#code {
[CascadingParameter] public Task<AuthenticationState> AuthTask { get; set; }
[Inject] private AuthenticationStateProvider AuthState { get; set; }
private System.Security.Claims.ClaimsPrincipal user;
protected async override Task OnInitializedAsync()
{
var authState = await AuthTask;
this.user = authState.User;
}
private async Task ChangeUser(ChangeEventArgs e)
{
var en = Enum.Parse<TestUserType>(e.Value.ToString());
var authState = await ((TestAuthenticationStateProvider)AuthState).ChangeUser(en);
this.user = authState.User;
}
}

Get current windows user in Blazor Server

I want to get the name of the current Windows user for my Blazor Server project.
I tried it via HttpContext, which is unreliable, according to this github issue.
Then I went with the MS documentation, without success.
Still returned null for User
At this point I'm wondering if it's my incompetence or something with my whole idea of using Blazor Server for this.
This is pretty much all the code:
#page "/"
#using System.Security.Claims
#using Microsoft.AspNetCore.Components.Authorization
#inject AuthenticationStateProvider AuthenticationStateProvider
<h3>ClaimsPrincipal Data</h3>
<button #onclick="GetClaimsPrincipalData">Get ClaimsPrincipal Data</button>
<p>#_authMessage</p>
#if (_claims.Count() > 0)
{
<ul>
#foreach (var claim in _claims)
{
<li>#claim.Type: #claim.Value</li>
}
</ul>
}
<p>#_surnameMessage</p>
#code {
private string _authMessage;
private string _surnameMessage;
private IEnumerable<Claim> _claims = Enumerable.Empty<Claim>();
private async Task GetClaimsPrincipalData()
{
var authState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
var user = authState.User;
if (user.Identity.IsAuthenticated)
{
_authMessage = $"{user.Identity.Name} is authenticated.";
_claims = user.Claims;
_surnameMessage =
$"Surname: {user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value}";
}
else
{
_authMessage = "The user is NOT authenticated.";
}
}
There is also the part from the docu with the user.Identity.Name, but since I dont even get the claims, as of now, I am lost with what to do.
Edit 1:
Startup.cs
public class CustomAuthStateProvider : AuthenticationStateProvider
{
public override Task<AuthenticationState> GetAuthenticationStateAsync()
{
var identity = new ClaimsIdentity(new[]
{
new Claim(ClaimTypes.Name, "mrfibuli"),
}, "Fake authentication type");
var user = new ClaimsPrincipal(identity);
return Task.FromResult(new AuthenticationState(user));
}
}
In your .razor file:
<AuthorizeView>
Hello, #context.User.Identity?.Name!
</AuthorizeView>
Or in your code-behind:
[Inject]
AuthenticationStateProvider? AuthenticationStateProvider { get; set; }
public string? CurrentUserName { get; set; }
protected override async Task OnInitializedAsync()
{
if (AuthenticationStateProvider is not null)
{
var authenticationState = await AuthenticationStateProvider.GetAuthenticationStateAsync();
CurrentUserName = authenticationState.User.Identity?.Name;
}
}

Net Core 3.1 API with Identity Server 4 custom password validation

I'm building an API using identity server and I need to use an existing database. The users password are stored with a custom hash password.
I use FindClientByIdAsync to validate user and password, but as the password is encrypted in a non-standard algorithm I get invalid_client error message. If I change in execution time (with breakpoint) the value of password for an unencrypted value the authentication works.
It's possible change the client_secret validation for FindClientByIdAsync?
Custom ClientStore class
public class ClientStore : IClientStore
{
private readonly IMyUserRepository myUserRepository;
public ClientStore(IMyUserRepository myUserRepository)
{
this.myUserRepository = myUserRepository;
}
public static IEnumerable<IdentityResource> GetIdentityResources()
{
return new List<IdentityResource>
{
new IdentityResources.OpenId()
};
}
public static IEnumerable<ApiResource> GetApiResources()
{
return new List<ApiResource>
{
new ApiResource("My_API", "My API")
};
}
public async Task<Client> FindClientByIdAsync(string client)
{
var user = await myUserRepository.GetUserByEmailAsync(client);
if (user == null)
return null;
return new Client()
{
ClientId = client,
AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials,
ClientSecrets =
{
new Secret(user.Password.Sha256()) //if I change to unencrypted works, but the value in database is hashed
},
AllowedScopes = { "GOLACO_API", IdentityServerConstants.StandardScopes.OpenId }
};
}
}
Identity server configuration in Startup class
services.AddIdentityServer(options =>
{
options.Events.RaiseSuccessEvents = true;
options.Events.RaiseFailureEvents = true;
options.Events.RaiseErrorEvents = true;
})
.AddSigningCredential(GetSigningCredential()) // here I just read the private.key file
.AddInMemoryIdentityResources(ClientStore.GetIdentityResources())
.AddInMemoryApiResources(ClientStore.GetApiResources())
.AddClientStore<ClientStore>();
services.AddAuthentication("Bearer")
.AddIdentityServerAuthentication(options =>
{
options.Authority = configuration["Configuration"];
options.ApiName = "My_API";
options.RequireHttpsMetadata = false;
});
services.AddAuthentication()
.AddFacebook("Facebook", options =>
{
options.AppId = "1234";
options.AppSecret = "1234567890";
});
var policy = new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.Build();
You have to implement IResourceOwnerPasswordValidator as Damien showed in his blog
public class CustomResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator
{
private readonly IUserRepository _userRepository;
public CustomResourceOwnerPasswordValidator(IUserRepository userRepository)
{
_userRepository = userRepository;
}
public Task ValidateAsync(ResourceOwnerPasswordValidationContext context)
{
if (_userRepository.ValidateCredentials(context.UserName, context.Password))
{
var user = _userRepository.FindByUsername(context.UserName);
context.Result = new GrantValidationResult(user.SubjectId, OidcConstants.AuthenticationMethods.Password);
}
return Task.FromResult(0);
}
}
And add builder.AddResourceOwnerValidator<CustomResourceOwnerPasswordValidator>(); in the startup file.

Authentication and LoginPath for different areas in ASP.NET Core 2

ASP.NET Core 2
Help me to configure AddAuthentication for two routes: users (user accounts) and admin area.
For example, if user doesn't signed in and trying to enter /Account/Orders/ he'll be redirected to /Account/SignIn/.
But if someone trying access /Admin/Orders/ must be redireted to /Admin/Signin/
Have not found ay solution ATM.
Solved!
In admin area (controllers) we using Authorize attr. arg.: [Authorize(AuthenticationSchemes = "backend")] and that is.
BTW we are able to make any tuning by accessing HttpContext in AddCookie's options and events.
Configuration:
services
.AddAuthentication(o =>
{
o.DefaultAuthenticateScheme = CookieAuthenticationDefaults.AuthenticationScheme;
})
.AddCookie(CookieAuthenticationDefaults.AuthenticationScheme, o =>
{
o.LoginPath = new PathString("/account/login/");
})
.AddCookie("backend", o =>
{
o.LoginPath = new PathString("/admin/account/login/");
});
#Alex's answer got me 90% of the way there.
In .Net 6, I'm using this https://learn.microsoft.com/en-us/aspnet/core/security/authentication/cookie?view=aspnetcore-6.0 approach to use Cookies without using the Username setup in identity.
Program.cs
var authentication = services.AddAuthentication(o =>
{
o.DefaultScheme = AuthenticationSchemes.FrontEnd;
});
authentication.AddCookie(AuthenticationSchemes.FrontEnd, o =>
{
o.LoginPath = CookieAuthenticationDefaults.LoginPath;
});
authentication.AddCookie(AuthenticationSchemes.BackEnd, o =>
{
o.LoginPath = new PathString("/admin/login/");
o.AccessDeniedPath = new PathString("/admin/accessdenied");
});
AppAuthenticationSchemes.cs
public class AuthenticationSchemes
{
public const string FrontEnd = "Frontend";
public const string BackEnd = "Backend";
public const string Either = FrontEnd + "," + BackEnd;
}
AccountController.cs
[AllowAnonymous]
public class AccountController : Controller
{
private readonly FrontEndSecurityManager _frontEndSecurityManager;
public AccountController(FrontEndSecurityManager frontEndSecurityManager)
{
_frontEndSecurityManager = frontEndSecurityManager;
}
[HttpPost(Name = "Login")]
public async Task<ActionResult> Login(LoginViewModel loginModel)
{
if (string.IsNullOrEmpty(loginModel.Username) ||
string.IsNullOrEmpty(loginModel.Password))
{
ModelState.AddModelError("form", "Please enter Username and Password");
return RedirectToAction("Login", "Account");
}
var loginResult = await _frontEndSecurityManager.ValidateCredentials(loginModel.Username, loginModel.Password);
if (!loginResult.IsSuccess)
{
this.AddFlash(FlashMessageType.Danger, "UserName or Password is incorrect");
return RedirectToAction("Login", "Account");
}
var identity = await _frontEndSecurityManager.CreateIdentityAsync(loginModel.Username, loginResult);
await _frontEndSecurityManager.SignInAsync(identity, HttpContext);
return RedirectToAction("Menu", "App");
}
}
FrontEndSecurityManager.cs
public class FrontEndSecurityManager
{
private readonly SignInApi _api;
private readonly AuthenticationOptions _authenticationOptions;
public FrontEndSecurityManager(SignInApi api, IOptions<AuthenticationOptions> authenticationOptions)
{
_api = api;
_authenticationOptions = authenticationOptions.Value;
}
public async Task SignInAsync(ClaimsIdentity identity, HttpContext httpContext)
{
var authProperties = new AuthenticationProperties
{
AllowRefresh = true,
ExpiresUtc = DateTimeOffset.UtcNow.AddMinutes(30),
IsPersistent = true,
IssuedUtc = DateTimeOffset.UtcNow
};
await httpContext.SignOutAsync(AuthenticationSchemes.BackEnd);
await httpContext.SignInAsync(AuthenticationSchemes.FrontEnd, new ClaimsPrincipal(identity), authProperties);
}
public async Task<LoginResult> ValidateCredentials(string username, string password)
{
if (_authenticationOptions.DemoUserEnabled)
{
if (string.Equals(username, "demo", StringComparison.InvariantCultureIgnoreCase))
{
var result = new LoginResult(StandardResults.SuccessResult, "")
{
Employee_Name = "Demo User",
Employee_Email = "DemoGuy#gmail.com",
Employee_Initials = "DG",
Employee_Type = "Regular",
Role1 = true,
Role2 = true,
Role3 = false
};
return result;
}
}
var apiRequest = new LoginRequest() { Username = username, Password = password };
var loginResult = await _api.LoginAsync(apiRequest);
if (loginResult.Success)
{
return loginResult.Data;
}
else
{
return LoginResult.Failure();
}
}
public async Task<ClaimsIdentity> CreateIdentityAsync(string username, LoginResult loginResult)
{
var claims = new List<Claim>
{
new Claim(ClaimTypes.Name, username),
new Claim(ClaimTypes.Role, AppRoles.User),
new Claim(ClaimTypes.Email, loginResult.Employee_Email, ClaimValueTypes.Email),
new Claim(ClaimTypes.GivenName, loginResult.GivenName),
new Claim(ClaimTypes.Surname, loginResult.Surname),
new Claim(AppClaimTypes.EmployeeType, loginResult.Employee_Type),
new Claim(AppClaimTypes.EmployeeInitials, loginResult.Employee_Initials),
new Claim(AppClaimTypes.Location, loginResult.Location.ToString(), ClaimValueTypes.Integer),
};
if (loginResult.Use_Checkin)
{
claims.Add(new Claim(ClaimTypes.Role, AppRoles.Checkin));
}
if (loginResult.Use_Pickup)
{
claims.Add(new Claim(ClaimTypes.Role, AppRoles.Pickup));
}
var identity = new ClaimsIdentity(claims, AuthenticationSchemes.FrontEnd);
return identity;
}
public void SignOutAsync(HttpContext httpContext)
{
httpContext.SignOutAsync(AuthenticationSchemes.FrontEnd);
}
}
From here, you could easily extrapolate how you want the back-end authentication controller to work. Essentially something like
await HttpContext.SignOutAsync(AuthenticationSchemes.FrontEnd);await HttpContext.SignInAsync(AuthenticationSchemes.BackEnd, new ClaimsPrincipal(identity), authProperties);
An example of using each policy would be
[Authorize(AuthenticationSchemes = AuthenticationSchemes.BackEnd)]
public IActionResult Secure()
{
return View("Secure");
}
or
[Authorize] // scheme not explicit, so Pr DefaultScheme = AuthenticationSchemes.FrontEnd is used
[Route("[controller]")]
public class OutgoingController : Controller
{
}

Net Core 2.0 API setting up authorization and authentication

I have a .net core application that I have upgraded from 1.1 to 2.0.
The problem I am having is working out how to set up both authentication and authorization.
I am getting this exception when I am trying to hit an api endpoint...
2017-08-15 15:28:12.2191|13|Microsoft.AspNetCore.Server.Kestrel|ERROR|
Connection id "0HL73T7CAJGBE", Request id "0HL73T7CAJGBE:00000001": An
unhandled exception was thrown by the application. No
authenticationScheme was specified, and there was no
DefaultChallengeScheme found.
My controller has this attribute on it...
[Authorize(Policy = "Viewer3AuthPolicy")]
My startup.cs has this method to try and set everything up...
public void ConfigureServices(IServiceCollection services)
{
SetCorsPolicy(services);
services.AddMvc();
services.AddAuthentication(o =>
{
o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
});
SetAuthorisationPolicy(services);
services.AddAuthorization(options =>
{
options.DefaultPolicy = new AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme).RequireAuthenticatedUser().Build();
options.AddPolicy("Viewer3AuthPolicy",
policy => policy.RequireClaim(Constants.AuthPolicyClaimsName, Constants.AuthPolicyClaimsValue));
});
}
In my Configuremethod I am calling...
app.UseAuthentication();
I am thinking that I must have some ordering wrong or am making the wrong calls in the setup.
Does anyone have any ideas?
Solution with _userManager.AddClaimsAsync. Here is the simplified version of changes I made under ConfigureServices:
services.AddAuthorization(options => {
options.AddPolicy("CRM", policy => { policy.RequireClaim("department", "Sales", "Customer Service", "Marketing", "Advertising", "MIS"); });
});
AccountController constructor:
private readonly UserManager<ApplicationUser> _userManager;
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly IEmailSender _emailSender;
private readonly ILogger _logger;
private readonly MyDB_Context _context;
public AccountController(
MyDB_Context context,
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager,
IEmailSender emailSender,
ILogger<AccountController> logger)
{
_context = context;
_userManager = userManager;
_signInManager = signInManager;
_emailSender = emailSender;
_logger = logger;
}
Under LogIn:
(var vUser is my own class with properties Name, department, SingIn, etc...). The sample below uses combination of custom user table mytable (to read from claim types and their values) and AspNetUserClaims table (to add claims):
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Login(LoginViewModel model, string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid) {
var vUser = _context.mytable.SingleOrDefault(m => m.Email.ToUpper() == model.Email.ToUpper());
const string Issuer = "https://www.mycompany.com/";
var user = _userManager.Users.Where(u => u.Email == model.Email).FirstOrDefault();
ApplicationUser applicationUser = await _userManager.FindByNameAsync(user.UserName);
IList<Claim> allClaims = await _userManager.GetClaimsAsync(applicationUser); // get all the user claims
// Add claim if missing
if (allClaims.Where(c => c.Type == "department" && c.Value == vUser.department).ToList().Count == 0) {
await _userManager.AddClaimAsync(user, new Claim("department", vUser.department, ClaimValueTypes.String, Issuer));
}
// Remove all other claim values for "department" type
var dept = allClaims.Where(c => c.Type == "department" && c.Value != vUser.department);
foreach(var claim in dept) {
await _userManager.RemoveClaimAsync(user, new Claim("department", claim.Value, ClaimValueTypes.String, Issuer));
}
vUser.SignIn = DateTime.Now; _context.Update(vUser); await _context.SaveChangesAsync();
// This doesn't count login failures towards account lockout
// To enable password failures to trigger account lockout, set lockoutOnFailure: true
var result = await _signInManager.PasswordSignInAsync(vUser.Name, model.Password, model.RememberMe, lockoutOnFailure: false);
//var result = await _signInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, lockoutOnFailure: false);
if (result.Succeeded) {
_logger.LogInformation("User logged in.");
return RedirectToLocal(returnUrl);
}
if (result.RequiresTwoFactor) {
return RedirectToAction(nameof(LoginWith2fa), new { returnUrl, model.RememberMe });
}
if (result.IsLockedOut) {
_logger.LogWarning("User account locked out.");
return RedirectToAction(nameof(Lockout));
} else {
ModelState.AddModelError(string.Empty, "Invalid login attempt.");
return View(model);
}
}
// If we got this far, something failed, redisplay form
return View(model);
}
This is what I have in my controller:
[Authorize(Policy = "CRM")]
public class CRMController : Controller
Adding
AddJwtBearer(options => { options.RequireHttpsMetadata = false; ... });"
did the trick for me.
[dotnet core 2.0]

Resources