Add project files.

This commit is contained in:
2023-04-29 09:17:17 +03:00
commit 62178f1f32
493 changed files with 45863 additions and 0 deletions
@@ -0,0 +1,167 @@
namespace MyOffice.Web.Identity;
using MyOffice.Data.Models.Users;
using Domain;
using Data.Repositories.Users;
using Repositories;
using IdentityModel;
using IdentityServer4.Models;
using IdentityServer4.Validation;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Options;
using System.Security.Claims;
using Core.Extensions;
using Core.Identity;
public class ExtensionGrantValidator : IExtensionGrantValidator
{
private readonly IUserStore<ApplicationUser<Guid>> _userStore;
private readonly ILogger<ExtensionGrantValidator> _logger;
private readonly AppUserManager _appUserManager;
private readonly IUserExternalRepository _userExternalRepository;
private readonly IHttpContextAccessor _httpContextAccessor;
private readonly ExternalProvidersConfig _externalProvidersConfig;
private readonly IEnumerable<IExternalProviderValidator> _externalProviderValidators;
public ExtensionGrantValidator(
ILogger<ExtensionGrantValidator> logger,
IUserStore<ApplicationUser<Guid>> userStore,
AppUserManager appUserManager,
IUserExternalRepository userExternalRepository,
IHttpContextAccessor httpContextAccessor,
IOptions<ExternalProvidersConfig> externalProvidersConfig,
IEnumerable<IExternalProviderValidator> externalProviderValidators
)
{
if (externalProvidersConfig == null)
throw new ArgumentNullException(nameof(externalProvidersConfig));
_userStore = userStore ?? throw new ArgumentNullException(nameof(userStore));
_appUserManager = appUserManager ?? throw new ArgumentNullException(nameof(appUserManager));
_userExternalRepository =
userExternalRepository ?? throw new ArgumentNullException(nameof(userExternalRepository));
_httpContextAccessor = httpContextAccessor ?? throw new ArgumentNullException(nameof(httpContextAccessor));
_externalProvidersConfig = externalProvidersConfig.Value;
_externalProviderValidators = externalProviderValidators;
_logger = logger ?? throw new ArgumentNullException(nameof(logger));
}
public string GrantType => "external";
public async Task ValidateAsync(ExtensionGrantValidationContext context)
{
var provider = context.Request.Raw["provider"];
if (provider == null)
throw new ArgumentNullException("provider not found");
var validator = _externalProviderValidators.FirstOrDefault(x => x.Provider.EqualsIgnoreCase(provider));
if (validator == null || !validator.IsConfigured)
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest,
$"Provider not supported: {provider}");
return;
}
var token = context.Request.Raw["token"];
if (token == null)
throw new ArgumentNullException("token not found");
var result = await validator.ValidateAsync(token);
if (!result.IsSuccessed)
{
context.Result = new GrantValidationResult(TokenRequestErrors.InvalidRequest, $"Token not valid");
return;
}
context.Result = await ProcessAsync(result.Email!, result.ExternalId!, provider, result.EmailVerified,
result.FullName);
}
private readonly object _lock = new();
private async Task<GrantValidationResult> ProcessAsync(
string email,
string externlaId,
string provider,
bool isEmailConfirmed,
string? fullName
)
{
// connect to exists user
if (_httpContextAccessor.HttpContext?.User?.Identity?.IsAuthenticated == true)
{
return new GrantValidationResult(TokenRequestErrors.InvalidRequest, $"Authentication failed");
}
else
{
var user = await _appUserManager.FindByEmailAsync(email);
if (user == null)
{
if (!isEmailConfirmed)
return new GrantValidationResult(TokenRequestErrors.InvalidRequest, "Email not confirmed");
user = await CreateUser(email, isEmailConfirmed, fullName);
if (user == null) return new GrantValidationResult(TokenRequestErrors.InvalidRequest);
}
var claim = await _userExternalRepository.GetByUserIdAsync(user.Id, provider);
if (claim == null) claim = AddClaim(user, email, externlaId, provider);
return ClaimToGrantValidationResult(claim.UserId, "", "");
}
}
private async Task<ApplicationUser<Guid>?> CreateUser(string email, bool isEmailConfirmed, string? fullName)
{
var user = new ApplicationUser<Guid>
{
Id = Guid.NewGuid(),
UserName = email,
Email = email,
IsEmailConfirmed = isEmailConfirmed,
FullName = fullName
};
var password = "Qq1!_" + Guid.NewGuid();
var result = await _appUserManager.CreateAsync(user, password);
if (!result.Succeeded) return null;
return user;
}
private UserExternal AddClaim(ApplicationUser<Guid> user, string email, string externalId, string provider)
{
lock (_lock)
{
var claim = _userExternalRepository.GetByUserId(user.Id, provider);
if (claim != null) return claim;
claim = new UserExternal
{
UserId = user.Id,
CreatedOn = DateTime.UtcNow,
Provider = provider.ToLower(),
ExternalId = externalId,
Email = email
};
_userExternalRepository.AddUserExternal(claim);
return claim;
}
}
private GrantValidationResult ClaimToGrantValidationResult(Guid userId, string provider, string email)
{
var userIdStr = userId.ToString();
var claims = new List<Claim>
{
new(JwtClaimTypes.Id, userIdStr),
new(JwtClaimTypes.Subject, userIdStr),
new(JwtClaimTypes.Email, email)
};
var grantValidationResult = new GrantValidationResult(userIdStr, provider, claims);
return grantValidationResult;
}
}