1
0
mirror of https://github.com/bitwarden/server.git synced 2024-12-28 17:57:37 +01:00

Added static client store (#899)

This commit is contained in:
Kyle Spearrin 2020-08-28 13:32:15 -04:00 committed by GitHub
parent db7d05b52f
commit 38728143d8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 148 additions and 123 deletions

View File

@ -0,0 +1,79 @@
using IdentityServer4.Models;
using System.Collections.Generic;
using System.Linq;
namespace Bit.Core.IdentityServer
{
public class ApiClient : Client
{
public ApiClient(
GlobalSettings globalSettings,
string id,
int refreshTokenSlidingDays,
int accessTokenLifetimeHours,
string[] scopes = null)
{
ClientId = id;
AllowedGrantTypes = new[] { GrantType.ResourceOwnerPassword, GrantType.AuthorizationCode };
RefreshTokenExpiration = TokenExpiration.Sliding;
RefreshTokenUsage = TokenUsage.ReUse;
SlidingRefreshTokenLifetime = 86400 * refreshTokenSlidingDays;
AbsoluteRefreshTokenLifetime = 0; // forever
UpdateAccessTokenClaimsOnRefresh = true;
AccessTokenLifetime = 3600 * accessTokenLifetimeHours;
AllowOfflineAccess = true;
RequireConsent = false;
RequirePkce = true;
RequireClientSecret = false;
if (id == "web")
{
RedirectUris = new[] { $"{globalSettings.BaseServiceUri.Vault}/sso-connector.html" };
PostLogoutRedirectUris = new[] { globalSettings.BaseServiceUri.Vault };
AllowedCorsOrigins = new[] { globalSettings.BaseServiceUri.Vault };
}
else if (id == "desktop")
{
RedirectUris = new[] { "bitwarden://sso-callback" };
PostLogoutRedirectUris = new[] { "bitwarden://logged-out" };
}
else if (id == "connector")
{
var connectorUris = new List<string>();
for (var port = 8065; port <= 8070; port++)
{
connectorUris.Add(string.Format("http://localhost:{0}", port));
}
RedirectUris = connectorUris.Append("bwdc://sso-callback").ToList();
PostLogoutRedirectUris = connectorUris.Append("bwdc://logged-out").ToList();
}
else if (id == "browser")
{
RedirectUris = new[] { $"{globalSettings.BaseServiceUri.Vault}/sso-connector.html" };
PostLogoutRedirectUris = new[] { globalSettings.BaseServiceUri.Vault };
AllowedCorsOrigins = new[] { globalSettings.BaseServiceUri.Vault };
}
else if (id == "cli")
{
var cliUris = new List<string>();
for (var port = 8065; port <= 8070; port++)
{
cliUris.Add(string.Format("http://localhost:{0}", port));
}
RedirectUris = cliUris;
PostLogoutRedirectUris = cliUris;
}
else if (id == "mobile")
{
RedirectUris = new[] { "bitwarden://sso-callback" };
PostLogoutRedirectUris = new[] { "bitwarden://logged-out" };
}
if (scopes == null)
{
scopes = new string[] { "api" };
}
AllowedScopes = scopes;
}
}
}

View File

@ -4,7 +4,6 @@ using IdentityServer4.Models;
using System.Collections.Generic;
using Bit.Core.Repositories;
using System;
using System.Security.Claims;
using IdentityModel;
using Bit.Core.Utilities;
@ -12,20 +11,21 @@ namespace Bit.Core.IdentityServer
{
public class ClientStore : IClientStore
{
private static IDictionary<string, Client> _apiClients = StaticClients.GetApiClients();
private readonly IInstallationRepository _installationRepository;
private readonly IOrganizationRepository _organizationRepository;
private readonly GlobalSettings _globalSettings;
private readonly StaticClientStore _staticClientStore;
public ClientStore(
IInstallationRepository installationRepository,
IOrganizationRepository organizationRepository,
GlobalSettings globalSettings)
GlobalSettings globalSettings,
StaticClientStore staticClientStore)
{
_installationRepository = installationRepository;
_organizationRepository = organizationRepository;
_globalSettings = globalSettings;
_staticClientStore = staticClientStore;
}
public async Task<Client> FindClientByIdAsync(string clientId)
@ -47,7 +47,10 @@ namespace Bit.Core.IdentityServer
AllowedGrantTypes = GrantTypes.ClientCredentials,
AccessTokenLifetime = 3600 * 24,
Enabled = installation.Enabled,
Claims = new List<ClientClaim> { new ClientClaim(JwtClaimTypes.Subject, installation.Id.ToString()) }
Claims = new List<ClientClaim>
{
new ClientClaim(JwtClaimTypes.Subject, installation.Id.ToString())
}
};
}
}
@ -70,7 +73,10 @@ namespace Bit.Core.IdentityServer
AllowedGrantTypes = GrantTypes.ClientCredentials,
AccessTokenLifetime = 3600 * 24,
Enabled = true,
Claims = new List<ClientClaim> { new ClientClaim(JwtClaimTypes.Subject, id) }
Claims = new List<ClientClaim>
{
new ClientClaim(JwtClaimTypes.Subject, id)
}
};
}
}
@ -92,13 +98,17 @@ namespace Bit.Core.IdentityServer
AllowedGrantTypes = GrantTypes.ClientCredentials,
AccessTokenLifetime = 3600 * 1,
Enabled = org.Enabled && org.UseApi,
Claims = new List<ClientClaim> { new ClientClaim(JwtClaimTypes.Subject, org.Id.ToString()) }
Claims = new List<ClientClaim>
{
new ClientClaim(JwtClaimTypes.Subject, org.Id.ToString())
}
};
}
}
}
return _apiClients.ContainsKey(clientId) ? _apiClients[clientId] : null;
return _staticClientStore.ApiClients.ContainsKey(clientId) ?
_staticClientStore.ApiClients[clientId] : null;
}
}
}

View File

@ -0,0 +1,26 @@
using IdentityServer4;
using IdentityServer4.Models;
using System.Collections.Generic;
namespace Bit.Core.IdentityServer
{
public class OidcIdentityClient : Client
{
public OidcIdentityClient(GlobalSettings globalSettings)
{
ClientId = "oidc-identity";
RequireClientSecret = true;
RequirePkce = true;
ClientSecrets = new List<Secret> { new Secret(globalSettings.OidcIdentityClientKey.Sha256()) };
AllowedScopes = new string[]
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
};
AllowedGrantTypes = GrantTypes.Code;
Enabled = true;
RedirectUris = new List<string> { $"{globalSettings.BaseServiceUri.Identity}/signin-oidc" };
RequireConsent = false;
}
}
}

View File

@ -0,0 +1,24 @@
using IdentityServer4.Models;
using System.Collections.Generic;
using System.Linq;
namespace Bit.Core.IdentityServer
{
public class StaticClientStore
{
public StaticClientStore(GlobalSettings globalSettings)
{
ApiClients = new List<Client>
{
new ApiClient(globalSettings, "mobile", 90, 1),
new ApiClient(globalSettings, "web", 30, 1),
new ApiClient(globalSettings, "browser", 30, 1),
new ApiClient(globalSettings, "desktop", 30, 1),
new ApiClient(globalSettings, "cli", 30, 1),
new ApiClient(globalSettings, "connector", 30, 24)
}.ToDictionary(c => c.ClientId);
}
public IDictionary<string, Client> ApiClients { get; private set; }
}
}

View File

@ -1,115 +0,0 @@
using IdentityServer4;
using IdentityServer4.Models;
using System.Collections.Generic;
using System.Linq;
namespace Bit.Core.IdentityServer
{
public class StaticClients
{
public static IDictionary<string, Client> GetApiClients()
{
return new List<Client>
{
new ApiClient("mobile", 90, 1),
new ApiClient("web", 30, 1),
new ApiClient("browser", 30, 1),
new ApiClient("desktop", 30, 1),
new ApiClient("cli", 30, 1),
new ApiClient("connector", 30, 24)
}.ToDictionary(c => c.ClientId);
}
public class ApiClient : Client
{
public ApiClient(
string id,
int refreshTokenSlidingDays,
int accessTokenLifetimeHours,
string[] scopes = null)
{
ClientId = id;
AllowedGrantTypes = new[] { GrantType.ResourceOwnerPassword, GrantType.AuthorizationCode };
RefreshTokenExpiration = TokenExpiration.Sliding;
RefreshTokenUsage = TokenUsage.ReUse;
SlidingRefreshTokenLifetime = 86400 * refreshTokenSlidingDays;
AbsoluteRefreshTokenLifetime = 0; // forever
UpdateAccessTokenClaimsOnRefresh = true;
AccessTokenLifetime = 3600 * accessTokenLifetimeHours;
AllowOfflineAccess = true;
RequireConsent = false;
RequirePkce = true;
RequireClientSecret = false;
if (id == "web")
{
RedirectUris = new[] { "https://localhost:8080/sso-connector.html" };
PostLogoutRedirectUris = new[] { "https://localhost:8080" };
AllowedCorsOrigins = new[] { "https://localhost:8080" };
}
else if (id == "desktop")
{
RedirectUris = new[] { "bitwarden://sso-callback" };
PostLogoutRedirectUris = new[] { "bitwarden://logged-out" };
}
else if (id == "connector")
{
var connectorUris = new List<string>();
for (var port = 8065; port <= 8070; port++)
{
connectorUris.Add(string.Format("http://localhost:{0}", port));
}
RedirectUris = connectorUris.Append("bwdc://sso-callback").ToList();
PostLogoutRedirectUris = connectorUris.Append("bwdc://logged-out").ToList();
}
else if (id == "browser")
{
RedirectUris = new[] { "https://localhost:8080/sso-connector.html" };
PostLogoutRedirectUris = new[] { "https://localhost:8080" };
AllowedCorsOrigins = new[] { "https://localhost:8080" };
}
else if (id == "cli")
{
var cliUris = new List<string>();
for (var port = 8065; port <= 8070; port++)
{
cliUris.Add(string.Format("http://localhost:{0}", port));
}
RedirectUris = cliUris;
PostLogoutRedirectUris = cliUris;
}
else if (id == "mobile")
{
RedirectUris = new[] { "bitwarden://sso-callback" };
PostLogoutRedirectUris = new[] { "bitwarden://logged-out" };
}
if (scopes == null)
{
scopes = new string[] { "api" };
}
AllowedScopes = scopes;
}
}
public class OidcIdentityClient : Client
{
public OidcIdentityClient(GlobalSettings globalSettings)
{
ClientId = "oidc-identity";
RequireClientSecret = true;
RequirePkce = true;
ClientSecrets = new List<Secret> { new Secret(globalSettings.OidcIdentityClientKey.Sha256()) };
AllowedScopes = new string[]
{
IdentityServerConstants.StandardScopes.OpenId,
IdentityServerConstants.StandardScopes.Profile
};
AllowedGrantTypes = GrantTypes.Code;
Enabled = true;
RedirectUris = new List<string> { $"{globalSettings.BaseServiceUri.Identity}/signin-oidc" };
RequireConsent = false;
}
}
}
}

View File

@ -192,6 +192,7 @@ namespace Bit.Identity
public static IIdentityServerBuilder AddCustomIdentityServerServices(IServiceCollection services,
IWebHostEnvironment env, GlobalSettings globalSettings)
{
services.AddSingleton<StaticClientStore>();
services.AddTransient<IAuthorizationCodeStore, AuthorizationCodeStore>();
var issuerUri = new Uri(globalSettings.BaseServiceUri.InternalIdentity);