Skip to content

Commit

Permalink
JWT token and authentication
Browse files Browse the repository at this point in the history
  • Loading branch information
matinayo committed Aug 6, 2023
1 parent 35a1217 commit 2a20d65
Show file tree
Hide file tree
Showing 9 changed files with 87 additions and 4 deletions.
10 changes: 10 additions & 0 deletions HalceraAPI.Common/AppsettingsOptions/JWTOptions.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
namespace HalceraAPI.Common.AppsettingsOptions
{
/// <summary>
/// Get JWT Token from Appsettings
/// </summary>
public class JWTOptions
{
public string Token { get; set; } = string.Empty;
}
}
9 changes: 9 additions & 0 deletions HalceraAPI.Common/HalceraAPI.Common.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net7.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

</Project>
1 change: 1 addition & 0 deletions HalceraAPI.Model/Requests/ApplicationUser/UserResponse.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,5 +12,6 @@ public class UserResponse
public DateTime? LockoutEnd { get; set; }
public DateTime? UserCreatedDate { get; set; }
public DateTime? DateLastModified { get; set; }
public string? Token { get; set; }
}
}
1 change: 1 addition & 0 deletions HalceraAPI.Services/HalceraAPI.Services.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\HalceraAPI.Common\HalceraAPI.Common.csproj" />
<ProjectReference Include="..\HalceraAPI.DataAccess\HalceraAPI.DataAccess.csproj" />
<ProjectReference Include="..\HalceraAPI.Model\HalceraAPI.Models.csproj" />
</ItemGroup>
Expand Down
53 changes: 51 additions & 2 deletions HalceraAPI.Services/Operations/ApplicationUserOperation.cs
Original file line number Diff line number Diff line change
@@ -1,8 +1,14 @@
using AutoMapper;
using HalceraAPI.Common.AppsettingsOptions;
using HalceraAPI.DataAccess.Contract;
using HalceraAPI.Models;
using HalceraAPI.Models.Requests.ApplicationUser;
using HalceraAPI.Services.Contract;
using Microsoft.Extensions.Options;
using Microsoft.IdentityModel.Tokens;
using System.IdentityModel.Tokens.Jwt;
using System.Security.Claims;
using System.Text;
using System.Text.RegularExpressions;

namespace HalceraAPI.Services.Operations
Expand All @@ -11,11 +17,13 @@ public class ApplicationUserOperation : IApplicationUserOperation
{
private readonly IUnitOfWork _unitOfWork;
private readonly IMapper _mapper;
private readonly JWTOptions jwtOptions;

public ApplicationUserOperation(IUnitOfWork unitOfWork, IMapper mapper)
public ApplicationUserOperation(IUnitOfWork unitOfWork, IMapper mapper, IOptions<JWTOptions> options)
{
_unitOfWork = unitOfWork;
_mapper = mapper;
jwtOptions = options.Value;
}

public async Task<UserResponse> Register(RegisterRequest registerRequest)
Expand All @@ -40,6 +48,8 @@ public async Task<UserResponse> Register(RegisterRequest registerRequest)
await _unitOfWork.SaveAsync();

UserResponse userResponse = _mapper.Map<UserResponse>(applicationUser);
string token = CreateToken(applicationUser);
userResponse.Token = token;
return userResponse;
}
catch (Exception)
Expand All @@ -58,10 +68,14 @@ public async Task<UserResponse> Login(LoginRequest loginRequest)
throw new Exception("Incorrect email or password.");
}
VerifyPassword(loginRequest.Password, applicationUserFromDb.PasswordHash);
ValidateAccountStatus(applicationUserFromDb);

applicationUserFromDb.LastLoginDate = DateTime.UtcNow;
await _unitOfWork.SaveAsync();

UserResponse userResponse = _mapper.Map<UserResponse>(applicationUserFromDb);
string token = CreateToken(applicationUserFromDb);
userResponse.Token = token;
return userResponse;
}
catch (Exception)
Expand Down Expand Up @@ -149,6 +163,41 @@ private static void VerifyPassword(string? requestedPassword, string application
}
}

//private static string CreateToken(ApplicationUser )
/// <summary>
/// Validating Account status and preferences
/// </summary>
/// <param name="applicationUser">Application User from db</param>
private static void ValidateAccountStatus(ApplicationUser applicationUser)
{
DateTime lockoutEnd = applicationUser.LockoutEnd ?? DateTime.UtcNow.AddYears(100);
int result = DateTime.Compare(lockoutEnd, DateTime.UtcNow);
if (result >= 0 || !applicationUser.Active)
{
// account is inactive
throw new Exception("Account is inactive");
}
}

/// <summary>
/// Create Json Web Token for user
/// </summary>
/// <param name="applicationUser">User from Db</param>
/// <returns>Json Token</returns>
private string CreateToken(ApplicationUser applicationUser)
{
List<Claim> claims = new()
{
new Claim(ClaimTypes.Name, applicationUser.Name ?? string.Empty),
new Claim(ClaimTypes.Email, applicationUser.Email)
};

// key to create and verify JWT
var key = new SymmetricSecurityKey(Encoding.UTF8.GetBytes(jwtOptions.Token));
var credentials = new SigningCredentials(key, SecurityAlgorithms.HmacSha512Signature);
var token = new JwtSecurityToken(claims: claims, expires: DateTime.UtcNow.AddDays(1), signingCredentials: credentials);

var jwt = new JwtSecurityTokenHandler().WriteToken(token);
return jwt;
}
}
}
6 changes: 6 additions & 0 deletions HalceraAPI.sln
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HalceraAPI.Models", "Halcer
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "HalceraAPI.Services", "HalceraAPI.Services\HalceraAPI.Services.csproj", "{44666F4B-B5BF-4AD2-88B1-0312D08A5423}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "HalceraAPI.Common", "HalceraAPI.Common\HalceraAPI.Common.csproj", "{959E69AF-07F2-4BD5-9FF3-37B735C21BB3}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -33,6 +35,10 @@ Global
{44666F4B-B5BF-4AD2-88B1-0312D08A5423}.Debug|Any CPU.Build.0 = Debug|Any CPU
{44666F4B-B5BF-4AD2-88B1-0312D08A5423}.Release|Any CPU.ActiveCfg = Release|Any CPU
{44666F4B-B5BF-4AD2-88B1-0312D08A5423}.Release|Any CPU.Build.0 = Release|Any CPU
{959E69AF-07F2-4BD5-9FF3-37B735C21BB3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{959E69AF-07F2-4BD5-9FF3-37B735C21BB3}.Debug|Any CPU.Build.0 = Debug|Any CPU
{959E69AF-07F2-4BD5-9FF3-37B735C21BB3}.Release|Any CPU.ActiveCfg = Release|Any CPU
{959E69AF-07F2-4BD5-9FF3-37B735C21BB3}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
1 change: 1 addition & 0 deletions HalceraAPI/HalceraAPI.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\HalceraAPI.Common\HalceraAPI.Common.csproj" />
<ProjectReference Include="..\HalceraAPI.DataAccess\HalceraAPI.DataAccess.csproj" />
<ProjectReference Include="..\HalceraAPI.Services\HalceraAPI.Services.csproj" />
</ItemGroup>
Expand Down
5 changes: 4 additions & 1 deletion HalceraAPI/Utilities/Extensions/ServiceExtension.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
using HalceraAPI.DataAccess;
using HalceraAPI.Common.AppsettingsOptions;
using HalceraAPI.DataAccess;
using HalceraAPI.DataAccess.Contract;
using HalceraAPI.DataAccess.Repository;
using HalceraAPI.Services.Contract;
Expand All @@ -17,9 +18,11 @@ public static void ConfigureDbContextAsync(this IServiceCollection services, ICo
services.AddDbContext<ApplicationDbContext>(options =>
{
options.UseSqlServer(configuration.GetConnectionString("DefaultConnection"));
// configuration.GetSection("AppSettings:Token").Value
});

services.AddScoped<IUnitOfWork, UnitOfWork>();
services.Configure<JWTOptions>(configuration.GetSection("JWTOptions"));
}

public static void ConfigureOperationsInjection(this IServiceCollection services)
Expand Down
5 changes: 4 additions & 1 deletion HalceraAPI/appsettings.Development.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,8 @@
"Default": "Information",
"Microsoft.AspNetCore": "Warning"
}
}
},
"JWTOptions": {
"Token": "Secret key of at least 16 characters"
}
}

0 comments on commit 2a20d65

Please sign in to comment.