Skip to content

Commit

Permalink
Merge pull request #50 from npraskins/master
Browse files Browse the repository at this point in the history
Started switching from role based auth to claims based
  • Loading branch information
enkodellc authored Oct 13, 2019
2 parents 964c0c7 + 4c7651f commit c332342
Show file tree
Hide file tree
Showing 11 changed files with 67 additions and 19 deletions.
2 changes: 1 addition & 1 deletion src/BlazorBoilerplate.Client/Pages/Admin/Users.razor
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ else
{
//update the user object's role list with the new selection set
user.Roles = roleSelections.Where(x => x.Selected == true).Select(x => x.Name).ToList();

var apiResponse = await Http.PutJsonAsync<ApiResponseDto>("api/Account", user);
if (apiResponse.StatusCode == 200)
{
Expand Down
38 changes: 35 additions & 3 deletions src/BlazorBoilerplate.Server/Controllers/AccountController.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ namespace BlazorBoilerplate.Server.Controllers
{
[Route("api/[controller]")]
[ApiController]
[AllowAnonymous]

public class AccountController : ControllerBase
{
private static readonly UserInfoDto LoggedOutUser = new UserInfoDto { IsAuthenticated = false, Roles = new List<string>() };
Expand All @@ -33,6 +33,7 @@ public class AccountController : ControllerBase
private readonly IEmailService _emailService;
private readonly IConfiguration _configuration;
private readonly ApplicationDbContext _db;


public AccountController(UserManager<ApplicationUser> userManager, ApplicationDbContext db,
SignInManager<ApplicationUser> signInManager, ILogger<AccountController> logger,
Expand Down Expand Up @@ -93,6 +94,17 @@ public async Task<ApiResponse> Login(LoginDto parameters)
return new ApiResponse(401, "Login Failed");
}


// This is a policy test endpoint, feel free to delete it
[Authorize(Policies.IsAdmin)]
[HttpGet("amiadmin")]
public async Task<ApiResponse> Testing()
{
var claims = HttpContext.User.Claims.ToList();
var claimsResponse = claims.Distinct().Select(x=>(x.Type.ToString(), x.Value.ToString())).ToList();
return new ApiResponse(200, $"policy {Policies.IsAdmin} has allowed you through", claimsResponse);
}

[AllowAnonymous]
// POST: api/Account/Register
[HttpPost("Register")]
Expand Down Expand Up @@ -127,7 +139,9 @@ public async Task<ApiResponse> Register(RegisterDto parameters)
}

//Role - Here we tie the new user to the "User" role
await _userManager.AddToRoleAsync(user, "User");
await _userManager.AddToRoleAsync(user, "User");
await _userManager.AddClaimAsync(user, new Claim(Policies.IsUser, "")); // Replacing roles with claims, if IsUser is present we interpret it as the equivalent of having the User role


if (Convert.ToBoolean(_configuration["BlazorBoilerplate:RequireConfirmedEmail"] ?? "false"))
{
Expand Down Expand Up @@ -432,7 +446,11 @@ public async Task<ApiResponse> Create(RegisterDto parameters)
}

//Role - Here we tie the new user to the "User" role
await _userManager.AddToRoleAsync(user, "User");
await _userManager.AddToRoleAsync(user, "User");
await _userManager.AddClaimAsync(user, new Claim(Policies.IsUser, "")); // Replacing roles with claims, if IsUser is present we interpret it as the equivalent of having the User role




if (Convert.ToBoolean(_configuration["BlazorBoilerplate:RequireConfirmedEmail"] ?? "false"))
{
Expand Down Expand Up @@ -582,6 +600,7 @@ public async Task<ApiResponse> Get([FromQuery] int pageSize = 10, [FromQuery] in
public async Task<ApiResponse> ListRoles()
{
var roleList = _roleManager.Roles.Select(x => x.Name).ToList();

return new ApiResponse(200, "", roleList);
}

Expand Down Expand Up @@ -627,7 +646,14 @@ public async Task<ApiResponse> Update([FromBody] UserInfoDto userInfo)
rolesToAdd.Add(newUserRole);
}
}

await _userManager.AddToRolesAsync(appUser, rolesToAdd).ConfigureAwait(true);
//HACK to switch to claims auth
foreach (var role in rolesToAdd)
{
await _userManager.AddClaimAsync(appUser, new Claim($"Is{role}", "true")).ConfigureAwait(true);

}

foreach (var role in currentUserRoles)
{
Expand All @@ -637,6 +663,12 @@ public async Task<ApiResponse> Update([FromBody] UserInfoDto userInfo)
}
}
await _userManager.RemoveFromRolesAsync(appUser, rolesToRemove).ConfigureAwait(true);

//HACK to switch to claims auth
foreach (var role in rolesToRemove)
{
await _userManager.RemoveClaimAsync(appUser, new Claim($"Is{role}", "true")).ConfigureAwait(true);
}
}
catch
{
Expand Down
3 changes: 2 additions & 1 deletion src/BlazorBoilerplate.Server/Controllers/ApiLogController.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
using BlazorBoilerplate.Server.Middleware.Wrappers;
using BlazorBoilerplate.Server.Services;
using BlazorBoilerplate.Shared.AuthorizationDefinitions;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using System;
Expand Down Expand Up @@ -28,7 +29,7 @@ public async Task<ApiResponse> Get()

// GET: api/ApiLog/ApplicationUserId
[HttpGet("[action]")]
[Authorize(Roles = "SuperAdmin, Admin")]
[Authorize(Policies.IsAdmin)]
public async Task<ApiResponse> GetByApplicationUserId(string userId)
{
return await _apiLogService.GetByApplictionUserId(new Guid(userId));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace BlazorBoilerplate.Server.Controllers
[Route("api/[controller]")]
[Authorize]
[ApiController]
[AllowAnonymous]

public class EmailController : ControllerBase
{
// Logger instance
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ namespace BlazorBoilerplate.Server.Controllers
[Route("api/[controller]")]
// [Authorize(Roles = "Admin")]
[ApiController]
[AllowAnonymous]

public class SampleDataController : ControllerBase
{
// Logger instance
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ namespace BlazorBoilerplate.Server.Controllers
[Route("api/[controller]")]
[Authorize]
[ApiController]
[AllowAnonymous]
public class UserProfileController : ControllerBase
{
private readonly ILogger<UserProfileController> _logger;
Expand Down
9 changes: 9 additions & 0 deletions src/BlazorBoilerplate.Server/Data/DatabaseInitializer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -240,14 +240,23 @@ private async Task<ApplicationUser> CreateUserAsync(string userName, string pass
new Claim(JwtClaimTypes.Email, email),
new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean),
new Claim(JwtClaimTypes.PhoneNumber, phoneNumber)


}).Result;

//add claims version of roles
foreach (var role in roles.Distinct())
{
await _userManager.AddClaimAsync(applicationUser, new Claim($"Is{role}", "true"));
}

ApplicationUser user = await _userManager.FindByNameAsync(applicationUser.UserName);

try
{
result = await _userManager.AddToRolesAsync(user, roles.Distinct());
}

catch
{
await _userManager.DeleteAsync(user);
Expand Down
3 changes: 3 additions & 0 deletions src/BlazorBoilerplate.Server/Data/IdentityServerConfig.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
using System;
using System.Collections.Generic;
using BlazorBoilerplate.Server.Data.Core;
using BlazorBoilerplate.Shared.AuthorizationDefinitions;
using IdentityModel;
using IdentityServer4;
using IdentityServer4.Models;
Expand Down Expand Up @@ -38,6 +39,8 @@ public static IEnumerable<ApiResource> GetApiResources()
JwtClaimTypes.Email,
JwtClaimTypes.PhoneNumber,
JwtClaimTypes.Role,
Policies.IsUser,
Policies.IsAdmin,
ClaimConstants.Permission
}
}
Expand Down
6 changes: 3 additions & 3 deletions src/BlazorBoilerplate.Server/Properties/launchSettings.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,8 @@
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iisExpress": {
"applicationUrl": "http://localhost:53414/",
"sslPort": 0
"applicationUrl": "https://localhost:53414/",
"sslPort": 53414
}
},
"profiles": {
Expand All @@ -21,7 +21,7 @@
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "http://localhost:53416/"
"applicationUrl": "http://localhost:53416/;https://localhost:5001"
}
}
}
16 changes: 10 additions & 6 deletions src/BlazorBoilerplate.Server/Startup.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,12 +61,13 @@ public void ConfigureServices(IServiceCollection services)
});

services.AddIdentity<ApplicationUser, IdentityRole<Guid>>()
.AddRoles<IdentityRole<Guid>>()
// .AddRoles<IdentityRole<Guid>>()
.AddClaimsPrincipalFactory<AdditionalUserClaimsPrincipalFactory>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();

services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>,
AdditionalUserClaimsPrincipalFactory>();
//services.AddScoped<IUserClaimsPrincipalFactory<ApplicationUser>,
// AdditionalUserClaimsPrincipalFactory>();

// Adds IdentityServer
var identityServerBuilder = services.AddIdentityServer(options =>
Expand Down Expand Up @@ -171,7 +172,7 @@ public void ConfigureServices(IServiceCollection services)
identityServerBuilder.AddSigningCredential(cert);
}


services.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
Expand All @@ -180,6 +181,7 @@ public void ConfigureServices(IServiceCollection services)
options.RequireHttpsMetadata = _environment.IsProduction() ? true : false;
options.ApiName = IdentityServerConfig.ApiName;
});


services.Configure<ApiBehaviorOptions>(options => { options.SuppressModelStateInvalidFilter = true; });

Expand Down Expand Up @@ -322,19 +324,21 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
//app.UseStaticFiles();
app.UseClientSideBlazorFiles<Client.Startup>();

//app.UseHttpsRedirection();
app.UseHttpsRedirection();
app.UseRouting();
//app.UseAuthentication();
app.UseAuthorization();
app.UseIdentityServer();

app.UseAuthorization();

// NSwag
app.UseOpenApi();
app.UseSwaggerUi3();

app.UseEndpoints(endpoints =>
{
endpoints.MapDefaultControllerRoute();
endpoints.MapControllers();
// new SignalR endpoint routing setup
endpoints.MapHub<Hubs.ChatHub>("/chathub");
endpoints.MapFallbackToClientSideBlazor<Client.Startup>("index.html");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,15 +16,15 @@ public static AuthorizationPolicy IsAdminPolicy()
{
return new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.RequireRole("Administrator")
.RequireClaim("IsAdministrator")
.Build();
}

public static AuthorizationPolicy IsUserPolicy()
{
return new AuthorizationPolicyBuilder()
.RequireAuthenticatedUser()
.RequireRole("User")
.RequireClaim("IsUser")
.Build();
}

Expand Down

0 comments on commit c332342

Please sign in to comment.