diff --git a/src/Core/Vault/Queries/GetCipherPermissionsForUserQuery.cs b/src/Core/Vault/Queries/GetCipherPermissionsForUserQuery.cs
new file mode 100644
index 0000000000..4c715297e9
--- /dev/null
+++ b/src/Core/Vault/Queries/GetCipherPermissionsForUserQuery.cs
@@ -0,0 +1,103 @@
+using Bit.Core.Context;
+using Bit.Core.Enums;
+using Bit.Core.Exceptions;
+using Bit.Core.Services;
+using Bit.Core.Vault.Models.Data;
+using Bit.Core.Vault.Repositories;
+
+namespace Bit.Core.Vault.Queries;
+
+public class GetCipherPermissionsForUserQuery : IGetCipherPermissionsForUserQuery
+{
+    private readonly ICurrentContext _currentContext;
+    private readonly ICipherRepository _cipherRepository;
+    private readonly IApplicationCacheService _applicationCacheService;
+    private readonly IFeatureService  _featureService;
+
+    public GetCipherPermissionsForUserQuery(ICurrentContext currentContext, ICipherRepository cipherRepository, IApplicationCacheService applicationCacheService, IFeatureService featureService)
+    {
+        _currentContext = currentContext;
+        _cipherRepository = cipherRepository;
+        _applicationCacheService = applicationCacheService;
+        _featureService = featureService;
+    }
+
+    public async Task<IDictionary<Guid, OrganizationCipherPermission>> GetByOrganization(Guid organizationId)
+    {
+        var org = _currentContext.GetOrganization(organizationId);
+        var userId = _currentContext.UserId;
+
+        if (org == null || !userId.HasValue)
+        {
+            throw new NotFoundException();
+        }
+
+        var cipherPermissions = (await _cipherRepository.GetCipherPermissionsForOrganizationAsync(organizationId, userId.Value)).ToList();
+
+        if (await CanEditAllCiphersAsync(org))
+        {
+            foreach (var cipher in cipherPermissions)
+            {
+                cipher.Edit = true;
+                cipher.Manage = true;
+                cipher.ViewPassword = true;
+            }
+        }
+
+        if (await CanAccessUnassignedCiphersAsync(org))
+        {
+            foreach (var unassignedCipher in cipherPermissions.Where(c => c.Unassigned))
+            {
+                unassignedCipher.Edit = true;
+                unassignedCipher.Manage = true;
+                unassignedCipher.ViewPassword = true;
+            }
+        }
+
+        return cipherPermissions.ToDictionary(c => c.Id);
+    }
+
+    private async Task<bool> CanEditAllCiphersAsync(CurrentContextOrganization org)
+    {
+        // Custom users with EditAnyCollection permissions can always edit all ciphers
+        if (org is { Type: OrganizationUserType.Custom, Permissions.EditAnyCollection: true })
+        {
+            return true;
+        }
+
+        var orgAbility = await _applicationCacheService.GetOrganizationAbilityAsync(org.Id);
+
+        // Owners/Admins can only edit all ciphers if the organization has the setting enabled
+        if (orgAbility is { AllowAdminAccessToAllCollectionItems: true } && org is
+                { Type: OrganizationUserType.Admin or OrganizationUserType.Owner })
+        {
+            return true;
+        }
+
+        // Provider users can edit all ciphers if RestrictProviderAccess is disabled
+        if (await _currentContext.ProviderUserForOrgAsync(org.Id))
+        {
+            return !_featureService.IsEnabled(FeatureFlagKeys.RestrictProviderAccess);
+        }
+
+        return false;
+    }
+
+    private async Task<bool> CanAccessUnassignedCiphersAsync(CurrentContextOrganization org)
+    {
+        if (org is
+            { Type: OrganizationUserType.Owner or OrganizationUserType.Admin } or
+            { Permissions.EditAnyCollection: true })
+        {
+            return true;
+        }
+
+        // Provider users can only access all ciphers if RestrictProviderAccess is disabled
+        if (await _currentContext.ProviderUserForOrgAsync(org.Id))
+        {
+            return !_featureService.IsEnabled(FeatureFlagKeys.RestrictProviderAccess);
+        }
+
+        return false;
+    }
+}
diff --git a/src/Core/Vault/Queries/IGetCipherPermissionsForUserQuery.cs b/src/Core/Vault/Queries/IGetCipherPermissionsForUserQuery.cs
new file mode 100644
index 0000000000..3ab40f26f0
--- /dev/null
+++ b/src/Core/Vault/Queries/IGetCipherPermissionsForUserQuery.cs
@@ -0,0 +1,19 @@
+using Bit.Core.Vault.Models.Data;
+
+namespace Bit.Core.Vault.Queries;
+
+public interface IGetCipherPermissionsForUserQuery
+{
+    /// <summary>
+    /// Retrieves the permissions of every organization cipher (including unassigned) for the
+    /// ICurrentContext's user.
+    ///
+    /// It considers the Collection Management setting for allowing Admin/Owners access to all ciphers.
+    /// </summary>
+    /// <remarks>
+    /// The primary use case of this query is internal cipher authorization logic.
+    /// </remarks>
+    /// <param name="organizationId"></param>
+    /// <returns>A dictionary of CipherIds and a corresponding OrganizationCipherPermission</returns>
+    public Task<IDictionary<Guid, OrganizationCipherPermission>> GetByOrganization(Guid organizationId);
+}
diff --git a/src/Core/Vault/VaultServiceCollectionExtensions.cs b/src/Core/Vault/VaultServiceCollectionExtensions.cs
index 5296f47e3e..3fda5a1ad3 100644
--- a/src/Core/Vault/VaultServiceCollectionExtensions.cs
+++ b/src/Core/Vault/VaultServiceCollectionExtensions.cs
@@ -15,5 +15,6 @@ public static class VaultServiceCollectionExtensions
     private static void AddVaultQueries(this IServiceCollection services)
     {
         services.AddScoped<IOrganizationCiphersQuery, OrganizationCiphersQuery>();
+        services.AddScoped<IGetCipherPermissionsForUserQuery, GetCipherPermissionsForUserQuery>();
     }
 }