Browse Source

setup authentication and read userid from principal

pull/2/head
Kyle Spearrin 4 years ago
parent
commit
f9bed31d11
  1. 33
      src/CryptoAgent/Controllers/UserKeysController.cs
  2. 1
      src/CryptoAgent/CryptoAgent.csproj
  3. 2
      src/CryptoAgent/CryptoAgentSettings.cs
  4. 105
      src/CryptoAgent/Startup.cs
  5. 3
      src/CryptoAgent/appsettings.Development.json
  6. 1
      src/CryptoAgent/appsettings.json

33
src/CryptoAgent/Controllers/UserKeysController.cs

@ -1,33 +1,42 @@ @@ -1,33 +1,42 @@
using Bit.CryptoAgent.Models;
using Bit.CryptoAgent.Repositories;
using Bit.CryptoAgent.Services;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Security.Claims;
using System.Threading.Tasks;
namespace Bit.CryptoAgent.Controllers
{
[Authorize("Application")]
[Route("user-keys")]
public class UserKeysController : Controller
{
private readonly ILogger<UserKeysController> _logger;
private readonly ICryptoService _cryptoService;
private readonly IUserKeyRepository _userKeyRepository;
private readonly IdentityOptions _identityOptions;
public UserKeysController(
IOptions<IdentityOptions> optionsAccessor,
ILogger<UserKeysController> logger,
IUserKeyRepository userKeyRepository,
ICryptoService cryptoService)
{
_identityOptions = optionsAccessor?.Value ?? new IdentityOptions();
_logger = logger;
_cryptoService = cryptoService;
_userKeyRepository = userKeyRepository;
}
[HttpPost("{userId}/get")]
public async Task<IActionResult> Get(Guid userId, [FromBody] UserKeyGetRequestModel model)
[HttpPost("get")]
public async Task<IActionResult> Get([FromBody] UserKeyGetRequestModel model)
{
var userId = GetProperUserId().Value;
var publicKey = Convert.FromBase64String(model.PublicKey);
var user = await _userKeyRepository.ReadAsync(userId);
if (user == null)
@ -45,9 +54,10 @@ namespace Bit.CryptoAgent.Controllers @@ -45,9 +54,10 @@ namespace Bit.CryptoAgent.Controllers
return new JsonResult(response);
}
[HttpPost("{userId}")]
public async Task<IActionResult> Post(Guid userId, [FromBody] UserKeyRequestModel model)
[HttpPost]
public async Task<IActionResult> Post([FromBody] UserKeyRequestModel model)
{
var userId = GetProperUserId().Value;
var user = await _userKeyRepository.ReadAsync(userId);
if (user != null)
{
@ -63,9 +73,10 @@ namespace Bit.CryptoAgent.Controllers @@ -63,9 +73,10 @@ namespace Bit.CryptoAgent.Controllers
return new OkResult();
}
[HttpPut("{userId}")]
public async Task<IActionResult> Put(Guid userId, [FromBody] UserKeyRequestModel model)
[HttpPut]
public async Task<IActionResult> Put([FromBody] UserKeyRequestModel model)
{
var userId = GetProperUserId().Value;
var user = await _userKeyRepository.ReadAsync(userId);
if (user != null)
{
@ -80,5 +91,15 @@ namespace Bit.CryptoAgent.Controllers @@ -80,5 +91,15 @@ namespace Bit.CryptoAgent.Controllers
await _userKeyRepository.UpdateAsync(user);
return new OkResult();
}
public Guid? GetProperUserId()
{
var userId = User.FindFirstValue(_identityOptions.ClaimsIdentity.UserIdClaimType);
if (!Guid.TryParse(userId, out var userIdGuid))
{
return null;
}
return userIdGuid;
}
}
}

1
src/CryptoAgent/CryptoAgent.csproj

@ -14,6 +14,7 @@ @@ -14,6 +14,7 @@
<PackageReference Include="Azure.Security.KeyVault.Secrets" Version="4.2.0" />
<PackageReference Include="Azure.Storage.Blobs" Version="12.9.1" />
<PackageReference Include="Google.Cloud.Kms.V1" Version="2.4.0" />
<PackageReference Include="IdentityServer4.AccessTokenValidation" Version="3.0.1" />
<PackageReference Include="JsonFlatFileDataStore" Version="2.2.3" />
<PackageReference Include="VaultSharp" Version="1.6.5.1" />
</ItemGroup>

2
src/CryptoAgent/CryptoAgentSettings.cs

@ -2,6 +2,8 @@ @@ -2,6 +2,8 @@
{
public class CryptoAgentSettings
{
public string IdentityServerUri { get; set; }
public DatabaseSettings Database { get; set; }
public CertificateSettings Certificate { get; set; }
public RsaKeySettings RsaKey { get; set; }

105
src/CryptoAgent/Startup.cs

@ -1,13 +1,17 @@ @@ -1,13 +1,17 @@
using Bit.CryptoAgent.Repositories;
using Bit.CryptoAgent.Services;
using IdentityModel;
using IdentityServer4.AccessTokenValidation;
using JsonFlatFileDataStore;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Identity;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System;
using System.Globalization;
using System.Security.Claims;
namespace Bit.CryptoAgent
{
@ -29,6 +33,51 @@ namespace Bit.CryptoAgent @@ -29,6 +33,51 @@ namespace Bit.CryptoAgent
ConfigurationBinder.Bind(Configuration.GetSection("CryptoAgentSettings"), settings);
services.AddSingleton(s => settings);
AddAuthentication(services, settings);
AddRsaKeyProvider(services, settings);
services.AddSingleton<ICryptoFunctionService, CryptoFunctionService>();
services.AddSingleton<ICryptoService, CryptoService>();
AddDatabase(services, settings);
services.AddControllers();
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseAuthentication();
app.UseAuthorization();
app.UseEndpoints(endpoints => endpoints.MapDefaultControllerRoute());
}
private void AddDatabase(IServiceCollection services, CryptoAgentSettings settings)
{
var databaseProvider = settings.Database.Provider?.ToLowerInvariant();
if (databaseProvider == "json")
{
// Assign foobar to keyProperty in order to not use incrementing Id functionality
services.AddSingleton<IDataStore>(
new DataStore(settings.Database.JsonFilePath, keyProperty: "--foobar--"));
services.AddSingleton<IApplicationDataRepository, Repositories.JsonFile.ApplicationDataRepository>();
services.AddSingleton<IUserKeyRepository, Repositories.JsonFile.UserKeyRepository>();
}
else
{
throw new Exception("No database configured.");
}
}
private void AddRsaKeyProvider(IServiceCollection services, CryptoAgentSettings settings)
{
var rsaKeyProvider = settings.RsaKey.Provider?.ToLowerInvariant();
if (rsaKeyProvider == "certificate")
{
@ -76,36 +125,44 @@ namespace Bit.CryptoAgent @@ -76,36 +125,44 @@ namespace Bit.CryptoAgent
{
throw new Exception("Unknown rsa key provider configured.");
}
}
services.AddSingleton<ICryptoFunctionService, CryptoFunctionService>();
services.AddSingleton<ICryptoService, CryptoService>();
var databaseProvider = settings.Database.Provider?.ToLowerInvariant();
if (databaseProvider == "json")
{
// Assign foobar to keyProperty in order to not use incrementing Id functionality
services.AddSingleton<IDataStore>(
new DataStore(settings.Database.JsonFilePath, keyProperty: "--foobar--"));
services.AddSingleton<IApplicationDataRepository, Repositories.JsonFile.ApplicationDataRepository>();
services.AddSingleton<IUserKeyRepository, Repositories.JsonFile.UserKeyRepository>();
}
else
private void AddAuthentication(IServiceCollection services, CryptoAgentSettings settings)
{
services.Configure<IdentityOptions>(options =>
{
throw new Exception("No database configured.");
}
options.ClaimsIdentity = new ClaimsIdentityOptions
{
UserNameClaimType = JwtClaimTypes.Email,
UserIdClaimType = JwtClaimTypes.Subject
};
});
services
.AddAuthentication(IdentityServerAuthenticationDefaults.AuthenticationScheme)
.AddIdentityServerAuthentication(options =>
{
options.Authority = settings.IdentityServerUri;
options.RequireHttpsMetadata = !Environment.IsDevelopment() &&
settings.IdentityServerUri.StartsWith("https");
options.NameClaimType = ClaimTypes.Email;
options.SupportedTokens = SupportedTokens.Jwt;
});
services.AddControllers();
}
services
.AddAuthorization(config =>
{
config.AddPolicy("Application", policy =>
{
policy.RequireAuthenticatedUser();
policy.RequireClaim(JwtClaimTypes.AuthenticationMethod, "Application", "external");
policy.RequireClaim(JwtClaimTypes.Scope, "api");
});
});
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
if (Environment.IsDevelopment())
{
app.UseDeveloperExceptionPage();
Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;
}
app.UseRouting();
app.UseEndpoints(endpoints => endpoints.MapDefaultControllerRoute());
}
}
}

3
src/CryptoAgent/appsettings.Development.json

@ -5,5 +5,8 @@ @@ -5,5 +5,8 @@
"Microsoft": "Warning",
"Microsoft.Hosting.Lifetime": "Information"
}
},
"cryptoAgentSettings": {
"identityServerUri": "http://localhost:33656/"
}
}

1
src/CryptoAgent/appsettings.json

@ -8,6 +8,7 @@ @@ -8,6 +8,7 @@
},
"AllowedHosts": "*",
"cryptoAgentSettings": {
"identityServerUri": "https://identity.bitwarden.com/",
"database": {
"provider": "json",
"jsonFilePath": "/etc/bitwarden/data.json"

Loading…
Cancel
Save