map the roles in the JWToken

main
Paul Schneider 10 months ago
parent 442d8a4c39
commit 44dfb0021a
4 changed files with 88 additions and 12 deletions

@ -39,6 +39,7 @@ public static class Config
{ {
new IdentityResources.OpenId(), new IdentityResources.OpenId(),
new IdentityResources.Profile(), new IdentityResources.Profile(),
new IdentityResources.Email()
}; };
public static IEnumerable<ApiScope> ApiScopes => public static IEnumerable<ApiScope> ApiScopes =>
@ -79,7 +80,7 @@ public static class Config
AllowedScopes = { AllowedScopes = {
IdentityServerConstants.StandardScopes.OpenId, IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile, IdentityServerConstants.StandardScopes.Profile,
"scope2" } IdentityServerConstants.StandardScopes.Email }
}, },
}; };

@ -2,6 +2,7 @@ using System.Globalization;
using System.Security.Cryptography.X509Certificates; using System.Security.Cryptography.X509Certificates;
using Google.Apis.Util.Store; using Google.Apis.Util.Store;
using IdentityServer8; using IdentityServer8;
using IdentityServer8.Services;
using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.DataProtection;
@ -33,6 +34,7 @@ namespace Yavsc.Extensions;
internal static class HostingExtensions internal static class HostingExtensions
{ {
#region files config
public static IApplicationBuilder ConfigureFileServerApp(this IApplicationBuilder app, public static IApplicationBuilder ConfigureFileServerApp(this IApplicationBuilder app,
bool enableDirectoryBrowsing = false) bool enableDirectoryBrowsing = false)
{ {
@ -83,6 +85,9 @@ internal static class HostingExtensions
app.UseStaticFiles(); app.UseStaticFiles();
return app; return app;
} }
#endregion
public static void ConfigureWorkflow() public static void ConfigureWorkflow()
{ {
foreach (var a in System.AppDomain.CurrentDomain.GetAssemblies()) foreach (var a in System.AppDomain.CurrentDomain.GetAssemblies())
@ -163,6 +168,7 @@ internal static class HostingExtensions
services.Configure<PayPalSettings>(paypalSection); services.Configure<PayPalSettings>(paypalSection);
services.Configure<GoogleAuthSettings>(googleAuthSettings); services.Configure<GoogleAuthSettings>(googleAuthSettings);
services.AddRazorPages(); services.AddRazorPages();
services.AddSignalR(o => services.AddSignalR(o =>
{ {
@ -197,12 +203,15 @@ services
// see https://docs.duendesoftware.com/identityserver/v6/fundamentals/resources/ // see https://docs.duendesoftware.com/identityserver/v6/fundamentals/resources/
options.EmitStaticAudienceClaim = true; options.EmitStaticAudienceClaim = true;
options.EmitScopesAsSpaceDelimitedStringInJwt = true;
options.Endpoints.EnableUserInfoEndpoint = true;
}) })
.AddInMemoryIdentityResources(Config.IdentityResources) .AddInMemoryIdentityResources(Config.IdentityResources)
.AddInMemoryClients(Config.Clients) .AddInMemoryClients(Config.Clients)
.AddInMemoryApiScopes(Config.ApiScopes) .AddInMemoryApiScopes(Config.ApiScopes)
.AddAspNetIdentity<ApplicationUser>() .AddAspNetIdentity<ApplicationUser>()
; ;
services.AddScoped<IProfileService, ProfileService>();
if (builder.Environment.IsDevelopment()) if (builder.Environment.IsDevelopment())
{ {
@ -317,6 +326,7 @@ services
_ = services.AddTransient<IBillingService, BillingService>(); _ = services.AddTransient<IBillingService, BillingService>();
_ = services.AddTransient<IDataStore, FileDataStore>((sp) => new FileDataStore("googledatastore", false)); _ = services.AddTransient<IDataStore, FileDataStore>((sp) => new FileDataStore("googledatastore", false));
_ = services.AddTransient<ICalendarManager, CalendarManager>(); _ = services.AddTransient<ICalendarManager, CalendarManager>();
services.AddTransient<IProfileService, ProfileService>();
// TODO for SMS: services.AddTransient<ISmsSender, AuthMessageSender>(); // TODO for SMS: services.AddTransient<ISmsSender, AuthMessageSender>();
@ -333,9 +343,7 @@ services
{ {
options.AddPolicy("ApiScope", policy => options.AddPolicy("ApiScope", policy =>
{ {
policy policy.RequireAuthenticatedUser();
.RequireAuthenticatedUser()
.RequireClaim("scope", "scope2");
}); });
options.AddPolicy("AdministratorOnly", policy => options.AddPolicy("AdministratorOnly", policy =>
{ {
@ -343,14 +351,11 @@ services
}); });
options.AddPolicy("FrontOffice", policy => policy.RequireRole(Constants.FrontOfficeGroupName)); options.AddPolicy("FrontOffice", policy => policy.RequireRole(Constants.FrontOfficeGroupName));
options.AddPolicy("Bearer", new AuthorizationPolicyBuilder()
.AddAuthenticationSchemes("Bearer")
.RequireAuthenticatedUser().Build());
// options.AddPolicy("EmployeeId", policy => policy.RequireClaim("EmployeeId", "123", "456")); // options.AddPolicy("EmployeeId", policy => policy.RequireClaim("EmployeeId", "123", "456"));
// options.AddPolicy("BuildingEntry", policy => policy.Requirements.Add(new OfficeEntryRequirement())); // options.AddPolicy("BuildingEntry", policy => policy.Requirements.Add(new OfficeEntryRequirement()));
options.AddPolicy("Authenticated", policy => policy.RequireAuthenticatedUser()); options.AddPolicy("Authenticated", policy => policy.RequireAuthenticatedUser());
options.AddPolicy("IsTheAuthor", policy => options.AddPolicy("IsTheAuthor", policy => policy.Requirements.Add(new EditPermission()));
policy.Requirements.Add(new EditPermission()));
}); });
services.AddSingleton<IAuthorizationHandler, PermissionHandler>(); services.AddSingleton<IAuthorizationHandler, PermissionHandler>();

@ -0,0 +1,56 @@
using System.Security.Claims;
using IdentityModel;
using IdentityServer8.Models;
using IdentityServer8.Services;
using Microsoft.AspNetCore.Identity;
using Yavsc.Models;
namespace Yavsc.Services
{
public class ProfileService : IProfileService
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly RoleManager<IdentityRole> _roleManager;
public ProfileService(
UserManager<ApplicationUser> userManager,
RoleManager<IdentityRole> roleManager)
{
_userManager = userManager;
_roleManager = roleManager;
}
public async Task<List<Claim>> GetClaimsFromUserAsync(ApplicationUser user)
{
var claims = new List<Claim> {
new Claim(JwtClaimTypes.Subject,user.Id.ToString()),
new Claim(JwtClaimTypes.PreferredUserName,user.UserName)
};
var role = await _userManager.GetRolesAsync(user);
role.ToList().ForEach(f =>
{
claims.Add(new Claim(JwtClaimTypes.Role, f));
});
return claims;
}
public async Task GetProfileDataAsync(ProfileDataRequestContext context)
{
var subjectId = context.Subject.Claims.FirstOrDefault(c => c.Type == "sub").Value;
var user = await _userManager.FindByIdAsync(subjectId);
context.IssuedClaims = await GetClaimsFromUserAsync(user);
}
public async Task IsActiveAsync(IsActiveContext context)
{
var subjectId = context.Subject.Claims.FirstOrDefault(c => c.Type == "sub").Value;
var user = await _userManager.FindByIdAsync(subjectId);
context.IsActive = user != null;
}
}
}

@ -1,7 +1,9 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting; using Microsoft.Extensions.Hosting;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt; using System.IdentityModel.Tokens.Jwt;
public class Startup public class Startup
@ -25,10 +27,22 @@ using System.IdentityModel.Tokens.Jwt;
options.ClientId = "mvc"; options.ClientId = "mvc";
options.ClientSecret = "49C1A7E1-0C79-4A89-A3D6-A37998FB86B0"; options.ClientSecret = "49C1A7E1-0C79-4A89-A3D6-A37998FB86B0";
options.ResponseType = "code"; options.ResponseType = "code";
options.UsePkce = true;
options.Scope.Clear();
options.Scope.Add("openid");
options.Scope.Add("profile");
options.Scope.Add("email");
options.Scope.Add("scope2"); options.GetClaimsFromUserInfoEndpoint = true;
options.SaveTokens = true;
options.SaveTokens = true; options.ClaimActions.MapUniqueJsonKey("role", "role");
options.ClaimActions.MapUniqueJsonKey("roles", "role");
options.TokenValidationParameters = new TokenValidationParameters
{
NameClaimType = "name",
RoleClaimType = "role"
};
}); });
} }

Loading…