1
0
mirror of https://github.com/bitwarden/server synced 2026-01-20 09:23:28 +00:00

[PM-25415] move files into better place for code ownership (#6275)

* chore: move files into better place for code ownership

* fix: import correct namespace
This commit is contained in:
Ike
2025-09-04 10:08:03 -04:00
committed by GitHub
parent cdf1d7f074
commit 96fe09af89
54 changed files with 65 additions and 65 deletions

View File

@@ -0,0 +1,30 @@
using Duende.IdentityServer.Models;
namespace Bit.Core.Auth.IdentityServer;
public static class ApiScopes
{
public const string Api = "api";
public const string ApiInstallation = "api.installation";
public const string ApiLicensing = "api.licensing";
public const string ApiOrganization = "api.organization";
public const string ApiPush = "api.push";
public const string ApiSecrets = "api.secrets";
public const string Internal = "internal";
public const string ApiSendAccess = "api.send.access";
public static IEnumerable<ApiScope> GetApiScopes()
{
return new List<ApiScope>
{
new(Api, "API Access"),
new(ApiPush, "API Push Access"),
new(ApiLicensing, "API Licensing Access"),
new(ApiOrganization, "API Organization Access"),
new(ApiInstallation, "API Installation Access"),
new(Internal, "Internal Access"),
new(ApiSecrets, "Secrets Manager Access"),
new(ApiSendAccess, "API Send Access"),
};
}
}

View File

@@ -0,0 +1,46 @@
// FIXME: Update this file to be null safe and then delete the line below
#nullable disable
using Duende.IdentityServer.Configuration;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Options;
namespace Bit.Core.Auth.IdentityServer;
public class ConfigureOpenIdConnectDistributedOptions : IPostConfigureOptions<CookieAuthenticationOptions>
{
private readonly IdentityServerOptions _idsrv;
private readonly IDistributedCache _distributedCache;
private readonly IDataProtectionProvider _dataProtectionProvider;
public ConfigureOpenIdConnectDistributedOptions(
[FromKeyedServices("persistent")]
IDistributedCache distributedCache,
IDataProtectionProvider dataProtectionProvider,
IdentityServerOptions idsrv)
{
_idsrv = idsrv;
_distributedCache = distributedCache;
_dataProtectionProvider = dataProtectionProvider;
}
public void PostConfigure(string name, CookieAuthenticationOptions options)
{
options.CookieManager = new DistributedCacheCookieManager();
if (name != AuthenticationSchemes.BitwardenExternalCookieAuthenticationScheme)
{
// Ignore
return;
}
options.Cookie.Name = AuthenticationSchemes.BitwardenExternalCookieAuthenticationScheme;
options.Cookie.IsEssential = true;
options.Cookie.SameSite = _idsrv.Authentication.CookieSameSiteMode;
options.TicketDataFormat = new DistributedCacheTicketDataFormatter(_distributedCache, _dataProtectionProvider, name);
options.SessionStore = new DistributedCacheTicketStore(_distributedCache);
}
}

View File

@@ -0,0 +1,71 @@
// FIXME: Update this file to be null safe and then delete the line below
#nullable disable
using System.Text;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Caching.Distributed;
using Microsoft.Extensions.DependencyInjection;
namespace Bit.Core.Auth.IdentityServer;
public class DistributedCacheCookieManager : ICookieManager
{
private readonly ChunkingCookieManager _cookieManager;
public DistributedCacheCookieManager()
{
_cookieManager = new ChunkingCookieManager();
}
private string CacheKeyPrefix => "cookie-data";
public void AppendResponseCookie(HttpContext context, string key, string value, CookieOptions options)
{
var id = Guid.NewGuid().ToString();
var cacheKey = GetKey(key, id);
var expiresUtc = options.Expires ?? DateTimeOffset.UtcNow.AddMinutes(15);
var cacheOptions = new DistributedCacheEntryOptions()
.SetAbsoluteExpiration(expiresUtc);
var data = Encoding.UTF8.GetBytes(value);
var cache = GetCache(context);
cache.Set(cacheKey, data, cacheOptions);
// Write the cookie with the identifier as the body
_cookieManager.AppendResponseCookie(context, key, id, options);
}
public void DeleteCookie(HttpContext context, string key, CookieOptions options)
{
_cookieManager.DeleteCookie(context, key, options);
var id = GetId(context, key);
if (!string.IsNullOrWhiteSpace(id))
{
var cacheKey = GetKey(key, id);
GetCache(context).Remove(cacheKey);
}
}
public string GetRequestCookie(HttpContext context, string key)
{
var id = GetId(context, key);
if (string.IsNullOrWhiteSpace(id))
{
return null;
}
var cacheKey = GetKey(key, id);
return GetCache(context).GetString(cacheKey);
}
private IDistributedCache GetCache(HttpContext context) =>
context.RequestServices.GetRequiredKeyedService<IDistributedCache>("persistent");
private string GetKey(string key, string id) => $"{CacheKeyPrefix}-{key}-{id}";
private string GetId(HttpContext context, string key) =>
context.Request.Cookies.TryGetValue(key, out var cookie) ?
cookie : null;
}

View File

@@ -0,0 +1,67 @@
// FIXME: Update this file to be null safe and then delete the line below
#nullable disable
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.Extensions.Caching.Distributed;
namespace Bit.Core.Auth.IdentityServer;
public class DistributedCacheTicketDataFormatter : ISecureDataFormat<AuthenticationTicket>
{
private const string CacheKeyPrefix = "ticket-data";
private readonly IDistributedCache _distributedCache;
private readonly IDataProtector _dataProtector;
private readonly string _prefix;
public DistributedCacheTicketDataFormatter(
IDistributedCache distributedCache,
IDataProtectionProvider dataProtectionProvider,
string name)
{
_distributedCache = distributedCache;
_dataProtector = dataProtectionProvider.CreateProtector(CacheKeyPrefix, name);
_prefix = $"{CacheKeyPrefix}-{name}";
}
public string Protect(AuthenticationTicket data) => Protect(data, null);
public string Protect(AuthenticationTicket data, string purpose)
{
var key = Guid.NewGuid().ToString();
var cacheKey = $"{_prefix}-{purpose}-{key}";
var expiresUtc = data.Properties.ExpiresUtc ??
DateTimeOffset.UtcNow.AddMinutes(15);
var options = new DistributedCacheEntryOptions();
options.SetAbsoluteExpiration(expiresUtc);
var ticket = TicketSerializer.Default.Serialize(data);
_distributedCache.Set(cacheKey, ticket, options);
return _dataProtector.Protect(key);
}
public AuthenticationTicket Unprotect(string protectedText) => Unprotect(protectedText, null);
public AuthenticationTicket Unprotect(string protectedText, string purpose)
{
if (string.IsNullOrWhiteSpace(protectedText))
{
return null;
}
// Decrypt the key and retrieve the data from the cache.
var key = _dataProtector.Unprotect(protectedText);
var cacheKey = $"{_prefix}-{purpose}-{key}";
var ticket = _distributedCache.Get(cacheKey);
if (ticket == null)
{
return null;
}
var data = TicketSerializer.Default.Deserialize(ticket);
return data;
}
}

View File

@@ -0,0 +1,66 @@
// FIXME: Update this file to be null safe and then delete the line below
#nullable disable
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.Extensions.Caching.Distributed;
namespace Bit.Core.Auth.IdentityServer;
public class DistributedCacheTicketStore : ITicketStore
{
private const string KeyPrefix = "auth-";
private readonly IDistributedCache _cache;
public DistributedCacheTicketStore(IDistributedCache distributedCache)
{
_cache = distributedCache;
}
public async Task<string> StoreAsync(AuthenticationTicket ticket)
{
var key = $"{KeyPrefix}{Guid.NewGuid()}";
await RenewAsync(key, ticket);
return key;
}
public Task RenewAsync(string key, AuthenticationTicket ticket)
{
var options = new DistributedCacheEntryOptions();
var expiresUtc = ticket.Properties.ExpiresUtc ??
DateTimeOffset.UtcNow.AddMinutes(15);
options.SetAbsoluteExpiration(expiresUtc);
var val = SerializeToBytes(ticket);
_cache.Set(key, val, options);
return Task.FromResult(0);
}
public Task<AuthenticationTicket> RetrieveAsync(string key)
{
AuthenticationTicket ticket;
var bytes = _cache.Get(key);
ticket = DeserializeFromBytes(bytes);
return Task.FromResult(ticket);
}
public Task RemoveAsync(string key)
{
_cache.Remove(key);
return Task.FromResult(0);
}
private static byte[] SerializeToBytes(AuthenticationTicket source)
{
return TicketSerializer.Default.Serialize(source);
}
private static AuthenticationTicket DeserializeFromBytes(byte[] source)
{
return source == null ? null : TicketSerializer.Default.Deserialize(source);
}
}