Custom IProfileService: IdentityServer Enter IdentityServer Admin AccessDenied
Describe the bug
Completely code initialization data, admin login,Try to enter IdentityServer Admin from IdentityServer
To Reproduce
Added custom IProfileService, then StartupHelpers:.AddProfileService<ProfileService>(), then start the project, Try to enter IdentityServer Admin from IdentityServer
version: Templates::2.0.1
ProfileService:
public class ProfileService : IProfileService
{
public ProfileService()
{
}
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
context.AddRequestedClaims(context.Subject.Claims);
await Task.CompletedTask;
}
public async Task IsActiveAsync(IsActiveContext context)
{
context.IsActive = context.IsActive;
await Task.CompletedTask;
}
}
Relevant parts of the log file
[13:39:06 INF] Request starting HTTP/2 GET https://localhost:44303/ - -
[13:39:06 VRB] All hosts are allowed.
[13:39:06 DBG] The host 'localhost' is excluded. Skipping HSTS header.
[13:39:06 DBG] The request path / does not match a supported file type
[13:39:06 DBG] 1 candidate(s) found for the request path '/'
[13:39:06 DBG] Endpoint 'Skoruba.IdentityServer4.Admin.UI.Areas.AdminUI.Controllers.HomeController.Index (Skoruba.IdentityServer4.Admin.UI)' with route pattern '/{controller=Home}/{action=Index}/{id?}' is valid for the request path '/'
[13:39:06 DBG] Request matched endpoint 'Skoruba.IdentityServer4.Admin.UI.Areas.AdminUI.Controllers.HomeController.Index (Skoruba.IdentityServer4.Admin.UI)'
[13:39:06 VRB] Performing unprotect operation to key {7b665705-1f67-460f-9586-cd2731e6f13c} with purposes ('Skoruba.IdentityServer4', 'Microsoft.AspNetCore.Authentication.Cookies.CookieAuthenticationMiddleware', 'Cookies', 'v2').
[13:39:06 DBG] AuthenticationScheme: Cookies was successfully authenticated.
[13:39:06 INF] Authorization failed. These requirements were not met:
RolesAuthorizationRequirement:User.IsInRole must be true for one of the following roles: (MyRole)
[13:39:06 INF] AuthenticationScheme: Cookies was forbidden.
[13:39:06 VRB] Connection id "0HM8BJ89DL6ML" sending HEADERS frame for stream ID 7 with length 71 and flags END_STREAM, END_HEADERS
[13:39:06 INF] Request finished HTTP/2 GET https://localhost:44303/ - - - 302 0 - 38.8856ms
[13:39:06 VRB] Connection id "0HM8BJ89DL6ML" received HEADERS frame for stream ID 9 with length 4775 and flags END_STREAM, END_HEADERS, PRIORITY
[13:39:06 INF] Request starting HTTP/2 GET https://localhost:44303/Account/AccessDenied?ReturnUrl=%2F - -
[13:39:06 VRB] All hosts are allowed.
After comparing the jwt token of the correct and incorrect requests, it is found that the claim: role and user are missing
You can check the default profile service here: https://github.com/IdentityServer/IdentityServer4/blob/main/src/AspNetIdentity/src/ProfileService.cs
After I added ProfileService, My own API is protected, but Admin Site is not working anymore. Can you add ProfileService to your project, so we can continue to add our own claims. ` public class ProfileService<TUser> : IProfileService where TUser : class { private readonly UserManager<TUser> _userManager; private readonly ILogger<ProfileService<TUser>> _logger; AdminIdentityDbContext _dbContext; public ProfileService(UserManager<TUser> userManager, ILogger<ProfileService<TUser>> logger, AdminIdentityDbContext dbContext) { _userManager = userManager;
_logger = logger;
_dbContext = dbContext;
}
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
IdentityUser mUser = (await _userManager.GetUserAsync(context.Subject)) as IdentityUser;
TicketHolderSecurity security=_dbContext.TicketHolderSecurities.Where(x => x.UserId == mUser.UserName).FirstOrDefault();
if(security!=null)
{
context.IssuedClaims.Add(new Claim("IsTicketHolder", "true"));
context.IssuedClaims.Add(new Claim("TicketHolderId", security.TicketHolderId.ToString()));
context.IssuedClaims.Add(new Claim("PhoneNumber", mUser.PhoneNumber));
}
context.AddRequestedClaims(context.Subject.Claims);
await Task.CompletedTask;
}
public async Task IsActiveAsync(IsActiveContext context)
{
context.IsActive = context.IsActive;
await Task.CompletedTask;
}
}
`
It is working after I restarted Azure Website. This issue can be closed now.