|
|
|
@ -12,30 +12,39 @@ using System.Threading.Tasks; |
|
|
|
using IdentityServer4; |
|
|
|
using IdentityServer4.Models; |
|
|
|
using IdentityServer4.Stores; |
|
|
|
using Microsoft.AspNetCore.Identity; |
|
|
|
using Microsoft.Extensions.Options; |
|
|
|
using Squidex.Config; |
|
|
|
using Squidex.Domain.Apps.Core.Apps; |
|
|
|
using Squidex.Domain.Apps.Entities; |
|
|
|
using Squidex.Domain.Users; |
|
|
|
using Squidex.Infrastructure; |
|
|
|
using Squidex.Infrastructure.Security; |
|
|
|
using Squidex.Shared; |
|
|
|
using Squidex.Shared.Identity; |
|
|
|
using Squidex.Shared.Users; |
|
|
|
using Squidex.Web; |
|
|
|
|
|
|
|
namespace Squidex.Areas.IdentityServer.Config |
|
|
|
{ |
|
|
|
public class LazyClientStore : IClientStore |
|
|
|
{ |
|
|
|
private readonly UserManager<IdentityUser> userManager; |
|
|
|
private readonly IAppProvider appProvider; |
|
|
|
private readonly Dictionary<string, Client> staticClients = new Dictionary<string, Client>(StringComparer.OrdinalIgnoreCase); |
|
|
|
|
|
|
|
public LazyClientStore( |
|
|
|
UserManager<IdentityUser> userManager, |
|
|
|
IOptions<UrlsOptions> urlsOptions, |
|
|
|
IOptions<MyIdentityOptions> identityOptions, |
|
|
|
IAppProvider appProvider) |
|
|
|
{ |
|
|
|
Guard.NotNull(identityOptions, nameof(identityOptions)); |
|
|
|
Guard.NotNull(urlsOptions, nameof(urlsOptions)); |
|
|
|
Guard.NotNull(userManager, nameof(userManager)); |
|
|
|
Guard.NotNull(appProvider, nameof(appProvider)); |
|
|
|
|
|
|
|
this.userManager = userManager; |
|
|
|
this.appProvider = appProvider; |
|
|
|
|
|
|
|
CreateStaticClients(urlsOptions, identityOptions); |
|
|
|
@ -52,23 +61,52 @@ namespace Squidex.Areas.IdentityServer.Config |
|
|
|
|
|
|
|
var (appName, appClientId) = clientId.GetClientParts(); |
|
|
|
|
|
|
|
if (appName == null) |
|
|
|
if (!string.IsNullOrWhiteSpace(appName)) |
|
|
|
{ |
|
|
|
return null; |
|
|
|
} |
|
|
|
var app = await appProvider.GetAppAsync(appName); |
|
|
|
|
|
|
|
var app = await appProvider.GetAppAsync(appName); |
|
|
|
var appClient = app?.Clients.GetOrDefault(appClientId); |
|
|
|
|
|
|
|
var appClient = app?.Clients.GetOrDefault(appClientId); |
|
|
|
if (appClient != null) |
|
|
|
{ |
|
|
|
return CreateClientFromApp(clientId, appClient); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
if (appClient == null) |
|
|
|
var user = await userManager.FindByIdWithClaimsAsync(clientId); |
|
|
|
|
|
|
|
if (!string.IsNullOrWhiteSpace(user?.ClientSecret())) |
|
|
|
{ |
|
|
|
return null; |
|
|
|
return CreateClientFromUser(user); |
|
|
|
} |
|
|
|
|
|
|
|
client = CreateClientFromApp(clientId, appClient); |
|
|
|
return null; |
|
|
|
} |
|
|
|
|
|
|
|
return client; |
|
|
|
private Client CreateClientFromUser(UserWithClaims user) |
|
|
|
{ |
|
|
|
return new Client |
|
|
|
{ |
|
|
|
ClientId = user.Id, |
|
|
|
ClientName = $"{user.Email} Client", |
|
|
|
ClientClaimsPrefix = null, |
|
|
|
ClientSecrets = new List<Secret> |
|
|
|
{ |
|
|
|
new Secret(user.ClientSecret().Sha256()) |
|
|
|
}, |
|
|
|
AccessTokenLifetime = (int)TimeSpan.FromDays(30).TotalSeconds, |
|
|
|
AllowedGrantTypes = GrantTypes.ClientCredentials, |
|
|
|
AllowedScopes = new List<string> |
|
|
|
{ |
|
|
|
Constants.ApiScope, |
|
|
|
Constants.RoleScope, |
|
|
|
Constants.PermissionsScope |
|
|
|
}, |
|
|
|
Claims = new List<Claim> |
|
|
|
{ |
|
|
|
new Claim(OpenIdClaims.Subject, user.Id) |
|
|
|
} |
|
|
|
}; |
|
|
|
} |
|
|
|
|
|
|
|
private static Client CreateClientFromApp(string id, AppClient appClient) |
|
|
|
@ -77,7 +115,10 @@ namespace Squidex.Areas.IdentityServer.Config |
|
|
|
{ |
|
|
|
ClientId = id, |
|
|
|
ClientName = id, |
|
|
|
ClientSecrets = new List<Secret> { new Secret(appClient.Secret.Sha256()) }, |
|
|
|
ClientSecrets = new List<Secret> |
|
|
|
{ |
|
|
|
new Secret(appClient.Secret.Sha256()) |
|
|
|
}, |
|
|
|
AccessTokenLifetime = (int)TimeSpan.FromDays(30).TotalSeconds, |
|
|
|
AllowedGrantTypes = GrantTypes.ClientCredentials, |
|
|
|
AllowedScopes = new List<string> |
|
|
|
@ -136,7 +177,10 @@ namespace Squidex.Areas.IdentityServer.Config |
|
|
|
{ |
|
|
|
ClientId = internalClient, |
|
|
|
ClientName = internalClient, |
|
|
|
ClientSecrets = new List<Secret> { new Secret(Constants.InternalClientSecret) }, |
|
|
|
ClientSecrets = new List<Secret> |
|
|
|
{ |
|
|
|
new Secret(Constants.InternalClientSecret) |
|
|
|
}, |
|
|
|
RedirectUris = new List<string> |
|
|
|
{ |
|
|
|
urlsOptions.BuildUrl($"{Constants.PortalPrefix}/signin-internal", false), |
|
|
|
@ -165,7 +209,10 @@ namespace Squidex.Areas.IdentityServer.Config |
|
|
|
{ |
|
|
|
ClientId = id, |
|
|
|
ClientName = id, |
|
|
|
ClientSecrets = new List<Secret> { new Secret(identityOptions.AdminClientSecret.Sha256()) }, |
|
|
|
ClientSecrets = new List<Secret> |
|
|
|
{ |
|
|
|
new Secret(identityOptions.AdminClientSecret.Sha256()) |
|
|
|
}, |
|
|
|
AccessTokenLifetime = (int)TimeSpan.FromDays(30).TotalSeconds, |
|
|
|
AllowedGrantTypes = GrantTypes.ClientCredentials, |
|
|
|
AllowedScopes = new List<string> |
|
|
|
|