feat(AuthController): Erstellt, um Token für Benutzer von UserManager bereitzustellen.
This commit is contained in:
parent
0a3e1566eb
commit
a66570bebb
123
src/DigitalData.Auth.API/Controllers/AuthController.cs
Normal file
123
src/DigitalData.Auth.API/Controllers/AuthController.cs
Normal file
@ -0,0 +1,123 @@
|
|||||||
|
using DigitalData.Auth.API.Config;
|
||||||
|
using DigitalData.Core.Abstractions.Security;
|
||||||
|
using DigitalData.UserManager.Domain.Entities;
|
||||||
|
using Microsoft.AspNetCore.Authorization;
|
||||||
|
using Microsoft.AspNetCore.Mvc;
|
||||||
|
using Microsoft.Extensions.Options;
|
||||||
|
using System.Security.Claims;
|
||||||
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
|
using DigitalData.UserManager.Application.DTOs.Auth;
|
||||||
|
using DigitalData.UserManager.Application.Contracts;
|
||||||
|
using DigitalData.UserManager.Application.DTOs.User;
|
||||||
|
using DigitalData.Core.Abstractions.Application;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
namespace DigitalData.Auth.API.Controllers
|
||||||
|
{
|
||||||
|
[Route("api/[controller]")]
|
||||||
|
[ApiController]
|
||||||
|
public class AuthController : ControllerBase
|
||||||
|
{
|
||||||
|
private readonly IJwtSignatureHandler<UserReadDto> _userSignatureHandler;
|
||||||
|
|
||||||
|
private readonly AuthApiParams _apiParams;
|
||||||
|
|
||||||
|
private readonly ICryptoFactory _cryptoFactory;
|
||||||
|
|
||||||
|
private readonly ILogger<AuthController> _logger;
|
||||||
|
|
||||||
|
private readonly IUserService _userService;
|
||||||
|
|
||||||
|
private readonly IDirectorySearchService _dirSearchService;
|
||||||
|
|
||||||
|
public AuthController(IJwtSignatureHandler<UserReadDto> userSignatureHandler, IOptions<AuthApiParams> cookieParamsOptions, ICryptoFactory cryptoFactory, ILogger<AuthController> logger, IUserService userService, IDirectorySearchService dirSearchService)
|
||||||
|
{
|
||||||
|
_apiParams = cookieParamsOptions.Value;
|
||||||
|
_userSignatureHandler = userSignatureHandler;
|
||||||
|
_cryptoFactory = cryptoFactory;
|
||||||
|
_logger = logger;
|
||||||
|
_userService = userService;
|
||||||
|
_dirSearchService = dirSearchService;
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IActionResult> CreateTokenAsync(LogInDto login, string consumerRoute, bool cookie = true)
|
||||||
|
{
|
||||||
|
bool isValid = _dirSearchService.ValidateCredentials(login.Username, login.Password);
|
||||||
|
|
||||||
|
if (!isValid)
|
||||||
|
return Unauthorized();
|
||||||
|
|
||||||
|
//find the user
|
||||||
|
var uRes = await _userService.ReadByUsernameAsync(login.Username);
|
||||||
|
if (!uRes.IsSuccess || uRes.Data is null)
|
||||||
|
{
|
||||||
|
return Unauthorized();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!_apiParams.Consumers.TryGetByRoute(consumerRoute, out var consumer))
|
||||||
|
return Unauthorized();
|
||||||
|
|
||||||
|
_cryptoFactory.TokenDescriptors.TryGet(_apiParams.Issuer, consumer.Audience, out var descriptor);
|
||||||
|
|
||||||
|
var token = _userSignatureHandler.WriteToken(uRes.Data, descriptor);
|
||||||
|
|
||||||
|
//set cookie
|
||||||
|
if (cookie)
|
||||||
|
{
|
||||||
|
Response.Cookies.Append(_apiParams.CookieName, token, consumer.CookieOptions.Create(lifetime: descriptor.Lifetime));
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return Ok(token);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: Add role depends on group name
|
||||||
|
[HttpPost("~/{consumerRoute}/login")]
|
||||||
|
[AllowAnonymous]
|
||||||
|
public async Task<IActionResult> Login([FromBody] LogInDto login, string consumerRoute)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await CreateTokenAsync(login, consumerRoute, true);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "{Message}", ex.Message);
|
||||||
|
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("logout")]
|
||||||
|
public IActionResult Logout()
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Response.Cookies.Delete(_apiParams.CookieName);
|
||||||
|
return Ok();
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "{Message}", ex.Message);
|
||||||
|
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpPost("{consumerRoute}")]
|
||||||
|
public async Task<IActionResult> CreateTokenViaBody([FromBody] LogInDto login, [FromRoute] string consumerRoute, [FromQuery] bool cookie = false)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return await CreateTokenAsync(login, consumerRoute, cookie);
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_logger.LogError(ex, "{Message}", ex.Message);
|
||||||
|
return StatusCode(StatusCodes.Status500InternalServerError);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
[HttpGet("check")]
|
||||||
|
[Authorize]
|
||||||
|
public IActionResult Check() => Ok();
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -12,11 +12,9 @@
|
|||||||
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.12" />
|
<PackageReference Include="Microsoft.AspNetCore.Authentication.JwtBearer" Version="8.0.12" />
|
||||||
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.3.0" />
|
<PackageReference Include="Microsoft.IdentityModel.Tokens" Version="8.3.0" />
|
||||||
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
<PackageReference Include="Swashbuckle.AspNetCore" Version="6.4.0" />
|
||||||
<PackageReference Include="UserManager.Domain" Version="2.0.0" />
|
<PackageReference Include="UserManager.Application" Version="3.1.0" />
|
||||||
</ItemGroup>
|
<PackageReference Include="UserManager.Domain" Version="3.0.0" />
|
||||||
|
<PackageReference Include="UserManager.Infrastructure" Version="3.0.0" />
|
||||||
<ItemGroup>
|
|
||||||
<Folder Include="Controllers\" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@ -3,7 +3,8 @@ using DigitalData.Auth.API.Dto;
|
|||||||
using DigitalData.Auth.API.Services;
|
using DigitalData.Auth.API.Services;
|
||||||
using DigitalData.Core.Abstractions.Security;
|
using DigitalData.Core.Abstractions.Security;
|
||||||
using DigitalData.Core.Security;
|
using DigitalData.Core.Security;
|
||||||
using DigitalData.UserManager.Domain.Entities;
|
using DigitalData.UserManager.Application;
|
||||||
|
using DigitalData.UserManager.Application.DTOs.User;
|
||||||
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
using Microsoft.AspNetCore.Authentication.JwtBearer;
|
||||||
using Microsoft.IdentityModel.JsonWebTokens;
|
using Microsoft.IdentityModel.JsonWebTokens;
|
||||||
using Microsoft.IdentityModel.Tokens;
|
using Microsoft.IdentityModel.Tokens;
|
||||||
@ -27,7 +28,7 @@ builder.Services.AddJwtSignatureHandler<ConsumerApi>(api => new Dictionary<strin
|
|||||||
{ JwtRegisteredClaimNames.Sub, api.Name },
|
{ JwtRegisteredClaimNames.Sub, api.Name },
|
||||||
{ JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds() }
|
{ JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds() }
|
||||||
});
|
});
|
||||||
builder.Services.AddJwtSignatureHandler<User>(user => new Dictionary<string, object>
|
builder.Services.AddJwtSignatureHandler<UserReadDto>(user => new Dictionary<string, object>
|
||||||
{
|
{
|
||||||
{ JwtRegisteredClaimNames.Sub, user.Id },
|
{ JwtRegisteredClaimNames.Sub, user.Id },
|
||||||
{ JwtRegisteredClaimNames.UniqueName, user.Id },
|
{ JwtRegisteredClaimNames.UniqueName, user.Id },
|
||||||
@ -37,6 +38,10 @@ builder.Services.AddJwtSignatureHandler<User>(user => new Dictionary<string, obj
|
|||||||
{ JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds() }
|
{ JwtRegisteredClaimNames.Iat, DateTimeOffset.UtcNow.ToUnixTimeSeconds() }
|
||||||
});
|
});
|
||||||
|
|
||||||
|
var cnn_str = builder.Configuration.GetConnectionString("Default") ?? throw new InvalidOperationException("Default connection string is not found.");
|
||||||
|
|
||||||
|
builder.Services.AddUserManager(cnn_str);
|
||||||
|
|
||||||
builder.Services.AddControllers();
|
builder.Services.AddControllers();
|
||||||
|
|
||||||
builder.Services.AddEndpointsApiExplorer();
|
builder.Services.AddEndpointsApiExplorer();
|
||||||
|
|||||||
@ -8,8 +8,8 @@ namespace DigitalData.Auth.API.Services
|
|||||||
{
|
{
|
||||||
public static IServiceCollection AddConsumerApiServiceFromConfiguration(this IServiceCollection services, IConfiguration configuration, string key = "ConsumerAPIs")
|
public static IServiceCollection AddConsumerApiServiceFromConfiguration(this IServiceCollection services, IConfiguration configuration, string key = "ConsumerAPIs")
|
||||||
{
|
{
|
||||||
var ConsumerApis = configuration.GetValue<IEnumerable<ConsumerApi>>("ConsumerAPIs") ?? throw new InvalidOperationException($"No Consumer list found in {key} in configuration.");
|
var consumerApis = configuration.GetValue<IEnumerable<ConsumerApi>>("ConsumerAPIs") ?? throw new InvalidOperationException($"No Consumer list found in {key} in configuration.");
|
||||||
services.AddSingleton(Options.Create(ConsumerApis));
|
services.AddSingleton(Options.Create(consumerApis));
|
||||||
services.AddSingleton<IConsumerApiService, ConfiguredConsumerApiService>();
|
services.AddSingleton<IConsumerApiService, ConfiguredConsumerApiService>();
|
||||||
return services;
|
return services;
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,6 +5,9 @@
|
|||||||
"Microsoft.AspNetCore": "Warning"
|
"Microsoft.AspNetCore": "Warning"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"ConnectionStrings": {
|
||||||
|
"Default": "Server=SDD-VMP04-SQL17\\DD_DEVELOP01;Database=DD_ECM;User Id=sa;Password=dd;Encrypt=false;TrustServerCertificate=True;"
|
||||||
|
},
|
||||||
"AllowedHosts": "*",
|
"AllowedHosts": "*",
|
||||||
"CryptParams": {
|
"CryptParams": {
|
||||||
"KeySizeInBits": 4096,
|
"KeySizeInBits": 4096,
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user