101 Security: Authentication. Server Side. - chempkovsky/CS82ANGULAR GitHub Wiki
- Database context
- appsettings json file
- Program file of PhBkWebApp app
- Account controller Dto
- Account controller
Security has two aspects: Authentication and Authorization
- There is no special t4 script to generate code for the Security Database context, because we will use the
IdentityDbContext
implementation of Microsoft. - Reminder: We have already added the reference to the Microsoft.AspNetCore.Identity.EntityFrameworkCore package.
- Create
AspNetReg
-folder in thePhBkContext.csproj
-project - Add
AspNetRegistrationDbContext
-class toAspNetReg
-folder of thePhBkContext.csproj
-project - Modify the file as follows:
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;
namespace PhBkContext.AspNetReg
{
public class AspNetRegistrationDbContext : IdentityDbContext<IdentityUser>
{
public AspNetRegistrationDbContext(DbContextOptions<AspNetRegistrationDbContext> options) : base(options)
{
Database.EnsureCreated();
}
protected override void OnModelCreating(ModelBuilder builder)
{
base.OnModelCreating(builder);
}
}
}
- Add
AspNetRegConnection
-item in theConnectionStrings
-secion of theappsettings.json
- file - Add
JWT
-section to theappsettings.json
- file
"ConnectionStrings": {
"PhBkConnection": "Data Source=SVR2016SQL2017;Initial Catalog=PhBkDbDef;Persist Security Info=True;User ID=sa;Password=your_password_here",
"AuthConnection": "Data Source=SVR2016SQL2017;Initial Catalog=PhBkDbAuth;Persist Security Info=True;User ID=sa;Password=your_password_here",
"AspNetRegConnection": "Data Source=SVR2016SQL2017;Initial Catalog=PhBkAspNet;Persist Security Info=True;User ID=sa;Password=your_password_here"
},
"JWT": {
"ValidAudience": "PhBkAudience",
"ValidIssuer": "PhBkIssuer",
"Secret": "JWTAuthenticationHIGHsecuredPasswordVVVp1OH7Xzyr"
}
- Reminder: We have already added the reference to the Microsoft.AspNetCore.Identity.EntityFrameworkCore package.
- Reminder: We have already added the reference to the Microsoft.AspNetCore.Authentication.JwtBearer package.
- Open
Program.cs
-file of thePhBkWebApp
-project- Add configurations for
AspNetRegistrationDbContext
-context - Add configurations for AspNetIdentity
- Add configurations for
...
using Microsoft.AspNetCore.Identity;
using PhBkContext.AspNetReg;
...
var builder = WebApplication.CreateBuilder(args);
...
ConfigurationManager configuration = builder.Configuration;
...
#region authentification
builder.Services.AddDbContext<AspNetRegistrationDbContext>(options =>
options.UseSqlServer(configuration.GetConnectionString("AspNetRegConnection")));
builder.Services.AddIdentity<IdentityUser, IdentityRole>()
.AddEntityFrameworkStores<AspNetRegistrationDbContext>().AddDefaultTokenProviders();
builder.Services.AddAuthentication(options => {
options.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
options.DefaultScheme = JwtBearerDefaults.AuthenticationScheme;
}).AddJwtBearer(options => {
options.SaveToken = true;
options.RequireHttpsMetadata = true;
options.TokenValidationParameters = new TokenValidationParameters() {
ValidateIssuer = true,
ValidateAudience = true,
ValidAudience = configuration["JWT:ValidAudience"],
ValidIssuer = configuration["JWT:ValidIssuer"],
IssuerSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(configuration["JWT:Secret"]))
};
});
builder.Services.AddHttpContextAccessor();
#endregion
...
var app = builder.Build();
- In the file
Program.cs
-file of thePhBkWebApp
-project insert the following code below thevar app = builder.Build();
-line
var app = builder.Build();
...
#region authentification
app.UseAuthentication();
#endregion
app.UseAuthorization();
- read Middleware order article as reminder.
- We need to define data structures which
Account controller
sends to clients and receives from the clients - Create
AspNetReg
-folder in the PhBkViews.csproj-project
- right click
AspNetReg
-folder of thePhBkViews.csproj
-project- select
JavaScript Wizard
-menu item
- select
Click to show the picture
- click
Next
-button on the first page
- Select
PhbkContext
-project andPhbkDbContext
-context and clickNext
-button
Click to show the picture
- Select
==Context==
and clickNext
-button
Click to show the picture
- Click
Batch processing
-button-
Batch Actions
-dialog will be shown
-
Click to show the picture
- select
00370-AspNetRegistration.json
- batch script and click start- four files will be created
- close dialog and close the Wizard
Click to show the picture
- Now we need the WebApi controller which implements login, register user, change password
- right click
Controllers
-folder of thePhBkControllers.csproj
-project- select
JavaScript Wizard
-menu item
- select
Click to show the picture
- click
Next
-button on the first page
- Select
PhbkContext
-project andPhbkDbContext
-context and clickNext
-button
Click to show the picture
- Select
==Context==
and clickNext
-button
Click to show the picture
- Click
Batch processing
-button
Click to show the picture
- select
00380-AspNetAccountController.json
- batch script and click start- four files will be created
- close dialog and close the Wizard
Click to show the picture
- It's for
Demo
only. - open the
Controllers/accountcontroller.cs
-file of thePhBkControllers.csproj
-project- Add the following method into the body of the class
- current method adds two users
-
[email protected]
with a password[email protected]
andAdminRole
-role -
[email protected]
with a password[email protected]
andGuestRole
-role
-
private async Task CreateAdminAndGuest()
{
IdentityUser adminUser = await _userManager.FindByNameAsync("[email protected]");
if (adminUser != null) return;
adminUser = new() {
Email = "[email protected]",
SecurityStamp = Guid.NewGuid().ToString(),
UserName = "[email protected]"
};
IdentityResult result = await _userManager.CreateAsync(adminUser, "[email protected]");
if (!result.Succeeded) return;
if (!await _roleManager.RoleExistsAsync("AdminRole")) await _roleManager.CreateAsync(new IdentityRole("AdminRole"));
if (!await _roleManager.RoleExistsAsync("GuestRole")) await _roleManager.CreateAsync(new IdentityRole("GuestRole"));
if (await _roleManager.RoleExistsAsync("AdminRole"))
{
await _userManager.AddToRoleAsync(adminUser, "AdminRole");
}
IdentityUser guestUser = await _userManager.FindByNameAsync("[email protected]");
if (guestUser != null) return;
guestUser = new() {
Email = "[email protected]",
SecurityStamp = Guid.NewGuid().ToString(),
UserName = "[email protected]"
};
result = await _userManager.CreateAsync(guestUser, "[email protected]");
if (!result.Succeeded) return;
if (await _roleManager.RoleExistsAsync("GuestRole"))
{
await _userManager.AddToRoleAsync(guestUser, "GuestRole");
}
}
- modify
Register
-method of the controller- Add
await CreateAdminAndGuest();
-line as a first line of method. (It's for Demo)
- Add
[HttpPost]
[Route("api/[controller]/register")]
public async Task<IActionResult> Register([FromBody] registerbindingmodel model)
{
await CreateAdminAndGuest();
...
}