Skip to content

Commit

Permalink
Squashed commit of the following:
Browse files Browse the repository at this point in the history
commit 0994dd3
Author: DustSwiffer <[email protected]>
Date:   Sat Jul 20 00:38:36 2024 +0200

    implementation of microsoft identity
  • Loading branch information
DustSwiffer committed Jul 19, 2024
1 parent 995e1c3 commit 8f9030c
Show file tree
Hide file tree
Showing 24 changed files with 1,535 additions and 44 deletions.
53 changes: 53 additions & 0 deletions AdvancedAPI.Business/Services/AuthenticationService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using AdvancedAPI.Data.Repositories.Interfaces;
using AdvancedAPI.Data.ViewModels.Authentication;
using Business.Services.Interfaces;
using Microsoft.AspNetCore.Identity;
using Microsoft.IdentityModel.Tokens;

namespace Business.Services;

/// <inheritdoc />
public class AuthenticationService : IAuthenticationService
{
private readonly IIdentityRepository _identityRepository;
private readonly IConfiguration _configuration;

/// <summary>
/// Constructor.
/// </summary>
public AuthenticationService(IIdentityRepository identityRepository, IConfiguration configuration)
{
_identityRepository = identityRepository;
_configuration = configuration;
}

/// <inheritdoc />
public async Task<JwtSecurityToken?> Login(LoginRequestModel requestModel, CancellationToken ct = default)
{
IdentityUser? user = await _identityRepository.GetUser(requestModel.Username);
if (user != null && await _identityRepository.CheckPassword(user, requestModel.Password))
{
Claim[] authClaims = new[]
{
new Claim(JwtRegisteredClaimNames.Sub, user.UserName),
new Claim(JwtRegisteredClaimNames.Jti, Guid.NewGuid().ToString()),
};

SymmetricSecurityKey authSigningKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(_configuration["Jwt:Key"]));

JwtSecurityToken token = new JwtSecurityToken(
issuer: _configuration["Jwt:Issuer"],
audience: _configuration["Jwt:Audience"],
expires: DateTime.Now.AddHours(3),
claims: authClaims,
signingCredentials: new SigningCredentials(authSigningKey, SecurityAlgorithms.HmacSha256));

return token;
}

return null;
}
}
15 changes: 15 additions & 0 deletions AdvancedAPI.Business/Services/Interfaces/IAuthenticationService.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System.IdentityModel.Tokens.Jwt;
using AdvancedAPI.Data.ViewModels.Authentication;

namespace Business.Services.Interfaces;

/// <summary>
/// Authentication service.
/// </summary>
public interface IAuthenticationService
{
/// <summary>
/// Logs in the user and returns a token.
/// </summary>
public Task<JwtSecurityToken?> Login(LoginRequestModel requestModel, CancellationToken ct = default);
}
6 changes: 6 additions & 0 deletions AdvancedAPI.Data/AdvancedAPI.Data.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,13 @@
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="6.0.32" />
<PackageReference Include="Microsoft.AspNetCore.Identity.EntityFrameworkCore" Version="6.0.32" />
<PackageReference Include="Microsoft.EntityFrameworkCore" Version="6.0.32" />
<PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="6.0.32">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.EntityFrameworkCore.SqlServer" Version="6.0.32" />
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1"/>
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
Expand Down
10 changes: 3 additions & 7 deletions AdvancedAPI.Data/AdvancedApiContext.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,13 @@
using AdvancedAPI.Data.Models;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Identity.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore;

namespace AdvancedAPI.Data;

/// <summary>
/// Database context.
/// </summary>
public class AdvancedApiContext : DbContext
public class AdvancedApiContext : IdentityDbContext<IdentityUser>
{
/// <summary>
/// Constructor.
Expand All @@ -15,9 +16,4 @@ public AdvancedApiContext(DbContextOptions<AdvancedApiContext> options)
: base(options)
{
}

/// <summary>
/// DbSet of <see cref="House"/>.
/// </summary>
public DbSet<House> Houses { get; set; }
}
27 changes: 27 additions & 0 deletions AdvancedAPI.Data/AdvancedApiContextFactory.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Design;

namespace AdvancedAPI.Data
{
/// <summary>
/// Factory for creating <see cref="AdvancedApiContext"/> instances at design time for EF Core tooling.
/// </summary>
public class AdvancedApiContextFactory : IDesignTimeDbContextFactory<AdvancedApiContext>
{
/// <summary>
/// Creates a new <see cref="AdvancedApiContext"/> with design-time configuration.
/// </summary>
public AdvancedApiContext CreateDbContext(string[] args)
{
IConfigurationRoot? configuration = new ConfigurationBuilder()
.SetBasePath(Directory.GetCurrentDirectory())
.AddJsonFile("appsettings.json")
.Build();

DbContextOptionsBuilder<AdvancedApiContext> optionsBuilder = new DbContextOptionsBuilder<AdvancedApiContext>();
optionsBuilder.UseSqlServer(configuration.GetConnectionString("DefaultConnection"));

return new AdvancedApiContext(optionsBuilder.Options);
}
}
}
65 changes: 65 additions & 0 deletions AdvancedAPI.Data/DbInitializer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
using Microsoft.AspNetCore.Identity;

namespace AdvancedAPI.Data
{
/// <summary>
/// Database initializer.
/// </summary>
public class DbInitializer
{
/// <summary>
/// Initialization of the database.
/// </summary>
public static async Task Initialize(IServiceProvider serviceProvider)
{
UserManager<IdentityUser> userManager = serviceProvider.GetRequiredService<UserManager<IdentityUser>>();
RoleManager<IdentityRole> roleManager = serviceProvider.GetRequiredService<RoleManager<IdentityRole>>();

// Seed roles
await SeedRoles(roleManager);

// Seed admin user
await SeedAdminUser(userManager);
}

/// <summary>
/// Seeding roles into the database.
/// </summary>
private static async Task SeedRoles(RoleManager<IdentityRole> roleManager)
{
string[] roleNames = { "Admin", "User" };

foreach (string roleName in roleNames)
{
bool roleExist = await roleManager.RoleExistsAsync(roleName);
if (!roleExist)
{
// Create the roles and seed them to the database
await roleManager.CreateAsync(new IdentityRole(roleName));
}
}
}

/// <summary>
/// Seeding user into the database.
/// </summary>
private static async Task SeedAdminUser(UserManager<IdentityUser> userManager)
{
IdentityUser? adminUser = await userManager.FindByEmailAsync("[email protected]");
if (adminUser == null)
{
adminUser = new IdentityUser
{
UserName = "[email protected]",
Email = "[email protected]",
};

IdentityResult? result = await userManager.CreateAsync(adminUser, "P@ssw0rd");
if (result.Succeeded)
{
await userManager.AddToRoleAsync(adminUser, "Admin");
}
}
}
}
}
Loading

0 comments on commit 8f9030c

Please sign in to comment.