From 5923b4c9bdd51704655d17cc8cc61c587ed48afa Mon Sep 17 00:00:00 2001
From: Kyle Spearrin <kyle.spearrin@gmail.com>
Date: Tue, 26 Feb 2019 17:01:33 -0500
Subject: [PATCH] org API clients

---
 src/Api/Startup.cs                      |  5 +++++
 src/Core/IdentityServer/ApiResources.cs |  3 ++-
 src/Core/IdentityServer/ClientStore.cs  | 25 +++++++++++++++++++++++++
 3 files changed, 32 insertions(+), 1 deletion(-)

diff --git a/src/Api/Startup.cs b/src/Api/Startup.cs
index d9ed03b23e..f23015cd3e 100644
--- a/src/Api/Startup.cs
+++ b/src/Api/Startup.cs
@@ -94,6 +94,11 @@ namespace Bit.Api
                     policy.RequireAuthenticatedUser();
                     policy.RequireClaim(JwtClaimTypes.Scope, "api.licensing");
                 });
+                config.AddPolicy("Organization", policy =>
+                {
+                    policy.RequireAuthenticatedUser();
+                    policy.RequireClaim(JwtClaimTypes.Scope, "api.organization");
+                });
             });
 
             services.AddScoped<AuthenticatorTokenProvider>();
diff --git a/src/Core/IdentityServer/ApiResources.cs b/src/Core/IdentityServer/ApiResources.cs
index bdca86b62d..1a432bff1b 100644
--- a/src/Core/IdentityServer/ApiResources.cs
+++ b/src/Core/IdentityServer/ApiResources.cs
@@ -24,7 +24,8 @@ namespace Bit.Core.IdentityServer
                 }),
                 new ApiResource("internal", new string[] { JwtClaimTypes.Subject }),
                 new ApiResource("api.push", new string[] { JwtClaimTypes.Subject }),
-                new ApiResource("api.licensing", new string[] { JwtClaimTypes.Subject })
+                new ApiResource("api.licensing", new string[] { JwtClaimTypes.Subject }),
+                new ApiResource("api.organization", new string[] { JwtClaimTypes.Subject })
             };
         }
     }
diff --git a/src/Core/IdentityServer/ClientStore.cs b/src/Core/IdentityServer/ClientStore.cs
index 49eec9a6f5..e686409c4b 100644
--- a/src/Core/IdentityServer/ClientStore.cs
+++ b/src/Core/IdentityServer/ClientStore.cs
@@ -15,13 +15,16 @@ namespace Bit.Core.IdentityServer
         private static IDictionary<string, Client> _apiClients = StaticClients.GetApiClients();
 
         private readonly IInstallationRepository _installationRepository;
+        private readonly IOrganizationRepository _organizationRepository;
         private readonly GlobalSettings _globalSettings;
 
         public ClientStore(
             IInstallationRepository installationRepository,
+            IOrganizationRepository organizationRepository,
             GlobalSettings globalSettings)
         {
             _installationRepository = installationRepository;
+            _organizationRepository = organizationRepository;
             _globalSettings = globalSettings;
         }
 
@@ -72,6 +75,28 @@ namespace Bit.Core.IdentityServer
                     }
                 }
             }
+            else if(clientId.StartsWith("organization."))
+            {
+                var idParts = clientId.Split('.');
+                if(idParts.Length > 1 && Guid.TryParse(idParts[1], out var id))
+                {
+                    var org = await _organizationRepository.GetByIdAsync(id);
+                    if(org != null)
+                    {
+                        return new Client
+                        {
+                            ClientId = $"organization.{org.Id}",
+                            RequireClientSecret = true,
+                            ClientSecrets = { new Secret(org.Id.ToString().Sha256()) }, // TODO: org.ApiKey
+                            AllowedScopes = new string[] { "api.organization" },
+                            AllowedGrantTypes = GrantTypes.ClientCredentials,
+                            AccessTokenLifetime = 3600 * 1,
+                            Enabled = org.Enabled, // TODO: && org.UseApi
+                            Claims = new List<Claim> { new Claim(JwtClaimTypes.Subject, org.Id.ToString()) }
+                        };
+                    }
+                }
+            }
 
             return _apiClients.ContainsKey(clientId) ? _apiClients[clientId] : null;
         }