From 7531f8726a7674c83dd84ba5a113714d18ad46d3 Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Tue, 30 May 2023 03:24:42 -0400 Subject: [PATCH 1/2] OpenIddictDataSeedContributor can now update clients --- .../OpenIddictDataSeedContributor.cs | 355 +++++++++--------- 1 file changed, 183 insertions(+), 172 deletions(-) diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/OpenIddict/OpenIddictDataSeedContributor.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/OpenIddict/OpenIddictDataSeedContributor.cs index 6101a1a1e8..04b597fd3c 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/OpenIddict/OpenIddictDataSeedContributor.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.Domain/OpenIddict/OpenIddictDataSeedContributor.cs @@ -1,16 +1,19 @@ using System; using System.Collections.Generic; using System.Linq; +using System.Text.Json; using System.Threading.Tasks; using JetBrains.Annotations; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.Localization; +using Microsoft.Extensions.Logging; using OpenIddict.Abstractions; using Volo.Abp; using Volo.Abp.Authorization.Permissions; using Volo.Abp.Data; using Volo.Abp.DependencyInjection; using Volo.Abp.OpenIddict.Applications; +using Volo.Abp.OpenIddict.Scopes; using Volo.Abp.PermissionManagement; using Volo.Abp.Uow; @@ -22,20 +25,26 @@ namespace MyCompanyName.MyProjectName.OpenIddict; public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDependency { private readonly IConfiguration _configuration; + private readonly IOpenIddictApplicationRepository _openIddictApplicationRepository; private readonly IAbpApplicationManager _applicationManager; + private readonly IOpenIddictScopeRepository _openIddictScopeRepository; private readonly IOpenIddictScopeManager _scopeManager; private readonly IPermissionDataSeeder _permissionDataSeeder; private readonly IStringLocalizer L; public OpenIddictDataSeedContributor( IConfiguration configuration, + IOpenIddictApplicationRepository openIddictApplicationRepository, IAbpApplicationManager applicationManager, + IOpenIddictScopeRepository openIddictScopeRepository, IOpenIddictScopeManager scopeManager, IPermissionDataSeeder permissionDataSeeder, - IStringLocalizer l) + IStringLocalizer l ) { _configuration = configuration; + _openIddictApplicationRepository = openIddictApplicationRepository; _applicationManager = applicationManager; + _openIddictScopeRepository = openIddictScopeRepository; _scopeManager = scopeManager; _permissionDataSeeder = permissionDataSeeder; L = l; @@ -50,24 +59,17 @@ public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDep private async Task CreateScopesAsync() { - if (await _scopeManager.FindByNameAsync("MyProjectName") == null) + if (await _openIddictScopeRepository.FindByNameAsync("MyProjectName") == null) { - await _scopeManager.CreateAsync(new OpenIddictScopeDescriptor - { - Name = "MyProjectName", - DisplayName = "MyProjectName API", - Resources = - { - "MyProjectName" - } + await _scopeManager.CreateAsync(new OpenIddictScopeDescriptor { + Name = "MyProjectName", DisplayName = "MyProjectName API", Resources = { "MyProjectName" } }); } } private async Task CreateApplicationsAsync() { - var commonScopes = new List - { + var commonScopes = new List { OpenIddictConstants.Permissions.Scopes.Address, OpenIddictConstants.Permissions.Scopes.Email, OpenIddictConstants.Permissions.Scopes.Phone, @@ -94,8 +96,7 @@ public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDep secret: configurationSection["MyProjectName_Web:ClientSecret"] ?? "1q2w3e*", grantTypes: new List //Hybrid flow { - OpenIddictConstants.GrantTypes.AuthorizationCode, - OpenIddictConstants.GrantTypes.Implicit + OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.Implicit }, scopes: commonScopes, redirectUri: $"{webClientRootUrl}signin-oidc", @@ -115,8 +116,7 @@ public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDep consentType: OpenIddictConstants.ConsentTypes.Implicit, displayName: "Console Test / Angular Application", secret: null, - grantTypes: new List - { + grantTypes: new List { OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.Password, OpenIddictConstants.GrantTypes.ClientCredentials, @@ -141,10 +141,7 @@ public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDep consentType: OpenIddictConstants.ConsentTypes.Implicit, displayName: "Blazor Application", secret: null, - grantTypes: new List - { - OpenIddictConstants.GrantTypes.AuthorizationCode, - }, + grantTypes: new List { OpenIddictConstants.GrantTypes.AuthorizationCode, }, scopes: commonScopes, redirectUri: $"{blazorRootUrl}/authentication/login-callback", clientUri: blazorRootUrl, @@ -156,7 +153,8 @@ public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDep var blazorServerTieredClientId = configurationSection["MyProjectName_BlazorServerTiered:ClientId"]; if (!blazorServerTieredClientId.IsNullOrWhiteSpace()) { - var blazorServerTieredRootUrl = configurationSection["MyProjectName_BlazorServerTiered:RootUrl"].EnsureEndsWith('/'); + var blazorServerTieredRootUrl = + configurationSection["MyProjectName_BlazorServerTiered:RootUrl"].EnsureEndsWith('/'); await CreateApplicationAsync( name: blazorServerTieredClientId!, @@ -166,8 +164,7 @@ public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDep secret: configurationSection["MyProjectName_BlazorServerTiered:ClientSecret"] ?? "1q2w3e*", grantTypes: new List //Hybrid flow { - OpenIddictConstants.GrantTypes.AuthorizationCode, - OpenIddictConstants.GrantTypes.Implicit + OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.Implicit }, scopes: commonScopes, redirectUri: $"{blazorServerTieredRootUrl}signin-oidc", @@ -188,10 +185,7 @@ public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDep consentType: OpenIddictConstants.ConsentTypes.Implicit, displayName: "Swagger Application", secret: null, - grantTypes: new List - { - OpenIddictConstants.GrantTypes.AuthorizationCode, - }, + grantTypes: new List { OpenIddictConstants.GrantTypes.AuthorizationCode, }, scopes: commonScopes, redirectUri: $"{swaggerRootUrl}/swagger/oauth2-redirect.html", clientUri: swaggerRootUrl @@ -212,194 +206,211 @@ public class OpenIddictDataSeedContributor : IDataSeedContributor, ITransientDep string? postLogoutRedirectUri = null, List? permissions = null) { - if (!string.IsNullOrEmpty(secret) && string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) + if (!string.IsNullOrEmpty(secret) && string.Equals(type, OpenIddictConstants.ClientTypes.Public, + StringComparison.OrdinalIgnoreCase)) { throw new BusinessException(L["NoClientSecretCanBeSetForPublicApplications"]); } - if (string.IsNullOrEmpty(secret) && string.Equals(type, OpenIddictConstants.ClientTypes.Confidential, StringComparison.OrdinalIgnoreCase)) + if (string.IsNullOrEmpty(secret) && string.Equals(type, OpenIddictConstants.ClientTypes.Confidential, + StringComparison.OrdinalIgnoreCase)) { throw new BusinessException(L["TheClientSecretIsRequiredForConfidentialApplications"]); } - if (!string.IsNullOrEmpty(name) && await _applicationManager.FindByClientIdAsync(name) != null) + var client = await _openIddictApplicationRepository.FindByClientIdAsync(name); + + var application = new AbpApplicationDescriptor { + ClientId = name, + Type = type, + ClientSecret = secret, + ConsentType = consentType, + DisplayName = displayName, + ClientUri = clientUri, + }; + + Check.NotNullOrEmpty(grantTypes, nameof(grantTypes)); + Check.NotNullOrEmpty(scopes, nameof(scopes)); + + if (new[] { OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.Implicit }.All( + grantTypes.Contains)) { - return; - //throw new BusinessException(L["TheClientIdentifierIsAlreadyTakenByAnotherApplication"]); + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken); + + if (string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) + { + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken); + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeToken); + } } - var client = await _applicationManager.FindByClientIdAsync(name); - if (client == null) + if (!redirectUri.IsNullOrWhiteSpace() || !postLogoutRedirectUri.IsNullOrWhiteSpace()) { - var application = new AbpApplicationDescriptor + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Logout); + } + + var buildInGrantTypes = new[] { + OpenIddictConstants.GrantTypes.Implicit, OpenIddictConstants.GrantTypes.Password, + OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.ClientCredentials, + OpenIddictConstants.GrantTypes.DeviceCode, OpenIddictConstants.GrantTypes.RefreshToken + }; + + foreach (var grantType in grantTypes) + { + if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode) { - ClientId = name, - Type = type, - ClientSecret = secret, - ConsentType = consentType, - DisplayName = displayName, - ClientUri = clientUri, - }; - - Check.NotNullOrEmpty(grantTypes, nameof(grantTypes)); - Check.NotNullOrEmpty(scopes, nameof(scopes)); - - if (new [] { OpenIddictConstants.GrantTypes.AuthorizationCode, OpenIddictConstants.GrantTypes.Implicit }.All(grantTypes.Contains)) + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode); + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Code); + } + + if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode || + grantType == OpenIddictConstants.GrantTypes.Implicit) { - application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdToken); + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Authorization); + } + + if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode || + grantType == OpenIddictConstants.GrantTypes.ClientCredentials || + grantType == OpenIddictConstants.GrantTypes.Password || + grantType == OpenIddictConstants.GrantTypes.RefreshToken || + grantType == OpenIddictConstants.GrantTypes.DeviceCode) + { + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Token); + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Revocation); + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Introspection); + } + if (grantType == OpenIddictConstants.GrantTypes.ClientCredentials) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.ClientCredentials); + } + + if (grantType == OpenIddictConstants.GrantTypes.Implicit) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Implicit); + } + + if (grantType == OpenIddictConstants.GrantTypes.Password) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Password); + } + + if (grantType == OpenIddictConstants.GrantTypes.RefreshToken) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.RefreshToken); + } + + if (grantType == OpenIddictConstants.GrantTypes.DeviceCode) + { + application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.DeviceCode); + application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Device); + } + + if (grantType == OpenIddictConstants.GrantTypes.Implicit) + { + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdToken); if (string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) { - application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeIdTokenToken); - application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.CodeToken); + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken); + application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Token); } } - if (!redirectUri.IsNullOrWhiteSpace() || !postLogoutRedirectUri.IsNullOrWhiteSpace()) + if (!buildInGrantTypes.Contains(grantType)) { - application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Logout); + application.Permissions.Add(OpenIddictConstants.Permissions.Prefixes.GrantType + grantType); } + } + + var buildInScopes = new[] { + OpenIddictConstants.Permissions.Scopes.Address, OpenIddictConstants.Permissions.Scopes.Email, + OpenIddictConstants.Permissions.Scopes.Phone, OpenIddictConstants.Permissions.Scopes.Profile, + OpenIddictConstants.Permissions.Scopes.Roles + }; - var buildInGrantTypes = new [] + foreach (var scope in scopes) + { + if (buildInScopes.Contains(scope)) { - OpenIddictConstants.GrantTypes.Implicit, - OpenIddictConstants.GrantTypes.Password, - OpenIddictConstants.GrantTypes.AuthorizationCode, - OpenIddictConstants.GrantTypes.ClientCredentials, - OpenIddictConstants.GrantTypes.DeviceCode, - OpenIddictConstants.GrantTypes.RefreshToken - }; - - foreach (var grantType in grantTypes) + application.Permissions.Add(scope); + } + else { - if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode) - { - application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.AuthorizationCode); - application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Code); - } - - if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode || grantType == OpenIddictConstants.GrantTypes.Implicit) - { - application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Authorization); - } - - if (grantType == OpenIddictConstants.GrantTypes.AuthorizationCode || - grantType == OpenIddictConstants.GrantTypes.ClientCredentials || - grantType == OpenIddictConstants.GrantTypes.Password || - grantType == OpenIddictConstants.GrantTypes.RefreshToken || - grantType == OpenIddictConstants.GrantTypes.DeviceCode) - { - application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Token); - application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Revocation); - application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Introspection); - } - - if (grantType == OpenIddictConstants.GrantTypes.ClientCredentials) - { - application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.ClientCredentials); - } - - if (grantType == OpenIddictConstants.GrantTypes.Implicit) - { - application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Implicit); - } - - if (grantType == OpenIddictConstants.GrantTypes.Password) - { - application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.Password); - } - - if (grantType == OpenIddictConstants.GrantTypes.RefreshToken) - { - application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.RefreshToken); - } - - if (grantType == OpenIddictConstants.GrantTypes.DeviceCode) - { - application.Permissions.Add(OpenIddictConstants.Permissions.GrantTypes.DeviceCode); - application.Permissions.Add(OpenIddictConstants.Permissions.Endpoints.Device); - } - - if (grantType == OpenIddictConstants.GrantTypes.Implicit) - { - application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdToken); - if (string.Equals(type, OpenIddictConstants.ClientTypes.Public, StringComparison.OrdinalIgnoreCase)) - { - application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.IdTokenToken); - application.Permissions.Add(OpenIddictConstants.Permissions.ResponseTypes.Token); - } - } - - if (!buildInGrantTypes.Contains(grantType)) - { - application.Permissions.Add(OpenIddictConstants.Permissions.Prefixes.GrantType + grantType); - } + application.Permissions.Add(OpenIddictConstants.Permissions.Prefixes.Scope + scope); } + } - var buildInScopes = new [] - { - OpenIddictConstants.Permissions.Scopes.Address, - OpenIddictConstants.Permissions.Scopes.Email, - OpenIddictConstants.Permissions.Scopes.Phone, - OpenIddictConstants.Permissions.Scopes.Profile, - OpenIddictConstants.Permissions.Scopes.Roles - }; - - foreach (var scope in scopes) + if (redirectUri != null) + { + if (!redirectUri.IsNullOrEmpty()) { - if (buildInScopes.Contains(scope)) + if (!Uri.TryCreate(redirectUri, UriKind.Absolute, out var uri) || !uri.IsWellFormedOriginalString()) { - application.Permissions.Add(scope); + throw new BusinessException(L["InvalidRedirectUri", redirectUri]); } - else + + if (application.RedirectUris.All(x => x != uri)) { - application.Permissions.Add(OpenIddictConstants.Permissions.Prefixes.Scope + scope); + application.RedirectUris.Add(uri); } } + } - if (redirectUri != null) + if (postLogoutRedirectUri != null) + { + if (!postLogoutRedirectUri.IsNullOrEmpty()) { - if (!redirectUri.IsNullOrEmpty()) + if (!Uri.TryCreate(postLogoutRedirectUri, UriKind.Absolute, out var uri) || + !uri.IsWellFormedOriginalString()) { - if (!Uri.TryCreate(redirectUri, UriKind.Absolute, out var uri) || !uri.IsWellFormedOriginalString()) - { - throw new BusinessException(L["InvalidRedirectUri", redirectUri]); - } - - if (application.RedirectUris.All(x => x != uri)) - { - application.RedirectUris.Add(uri); - } + throw new BusinessException(L["InvalidPostLogoutRedirectUri", postLogoutRedirectUri]); } - } - if (postLogoutRedirectUri != null) - { - if (!postLogoutRedirectUri.IsNullOrEmpty()) + if (application.PostLogoutRedirectUris.All(x => x != uri)) { - if (!Uri.TryCreate(postLogoutRedirectUri, UriKind.Absolute, out var uri) || !uri.IsWellFormedOriginalString()) - { - throw new BusinessException(L["InvalidPostLogoutRedirectUri", postLogoutRedirectUri]); - } - - if (application.PostLogoutRedirectUris.All(x => x != uri)) - { - application.PostLogoutRedirectUris.Add(uri); - } + application.PostLogoutRedirectUris.Add(uri); } } + } - if (permissions != null) - { - await _permissionDataSeeder.SeedAsync( - ClientPermissionValueProvider.ProviderName, - name, - permissions, - null - ); - } + if (permissions != null) + { + await _permissionDataSeeder.SeedAsync( + ClientPermissionValueProvider.ProviderName, + name, + permissions, + null + ); + } + if (client == null) + { await _applicationManager.CreateAsync(application); + return; + } + + if (!HasSameRedirectUris(client, application)) + { + client.RedirectUris = JsonSerializer.Serialize(application.RedirectUris.Select(q => q.ToString().TrimEnd('/'))); + client.PostLogoutRedirectUris = JsonSerializer.Serialize(application.PostLogoutRedirectUris.Select(q => q.ToString().TrimEnd('/'))); + + await _applicationManager.UpdateAsync(client.ToModel()); } + + if (!HasSameScopes(client, application)) + { + client.Permissions = JsonSerializer.Serialize(application.Permissions.Select(q => q.ToString())); + await _applicationManager.UpdateAsync(client.ToModel()); + } + } + + private bool HasSameRedirectUris(OpenIddictApplication existingClient, AbpApplicationDescriptor application) + { + return existingClient.RedirectUris == JsonSerializer.Serialize(application.RedirectUris.Select(q => q.ToString().TrimEnd('/'))); + } + + private bool HasSameScopes(OpenIddictApplication existingClient, AbpApplicationDescriptor application) + { + return existingClient.Permissions == JsonSerializer.Serialize(application.Permissions.Select(q => q.ToString().TrimEnd('/'))); } -} +} \ No newline at end of file From 3a3095d8219e9576543065c82b5f0107c2bf4a93 Mon Sep 17 00:00:00 2001 From: Galip Tolga Erdem Date: Tue, 30 May 2023 03:25:11 -0400 Subject: [PATCH 2/2] Added distributed caching for cache invalidation --- .../MyCompanyName.MyProjectName.DbMigrator.csproj | 3 +++ .../MyProjectNameDbMigratorModule.cs | 14 +++++++++++++- .../appsettings.json | 5 +++++ 3 files changed, 21 insertions(+), 1 deletion(-) diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj index 3c581e3947..fe67de71db 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyCompanyName.MyProjectName.DbMigrator.csproj @@ -18,6 +18,9 @@ + + + diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyProjectNameDbMigratorModule.cs b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyProjectNameDbMigratorModule.cs index 06c4b3d1b5..a984925ea5 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyProjectNameDbMigratorModule.cs +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/MyProjectNameDbMigratorModule.cs @@ -1,15 +1,27 @@ using MyCompanyName.MyProjectName.EntityFrameworkCore; using Volo.Abp.Autofac; +using Volo.Abp.Caching; +// +using Volo.Abp.Caching.StackExchangeRedis; +// using Volo.Abp.Modularity; namespace MyCompanyName.MyProjectName.DbMigrator; [DependsOn( typeof(AbpAutofacModule), + // + typeof(AbpCachingStackExchangeRedisModule), + // typeof(MyProjectNameEntityFrameworkCoreModule), typeof(MyProjectNameApplicationContractsModule) )] public class MyProjectNameDbMigratorModule : AbpModule { - + // + public override void ConfigureServices(ServiceConfigurationContext context) + { + Configure(options => { options.KeyPrefix = "MyProjectName:"; }); + } + // } diff --git a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/appsettings.json b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/appsettings.json index 0602764acb..5332ea7677 100644 --- a/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/appsettings.json +++ b/templates/app/aspnet-core/src/MyCompanyName.MyProjectName.DbMigrator/appsettings.json @@ -2,6 +2,11 @@ "ConnectionStrings": { "Default": "Server=(LocalDb)\\MSSQLLocalDB;Database=MyProjectName;Trusted_Connection=True;TrustServerCertificate=True" }, + // + "Redis": { + "Configuration": "127.0.0.1" + }, + // "OpenIddict": { "Applications": { "MyProjectName_Web": {