AuthServer¶
- Configure
OpenIddictlibrary
Add GetSigningCertificate and GetEncryptionCertificate certificate method for handling certificates.
using GridLab.Abp.ZeroTrust;
private X509Certificate2 GetSigningCertificate(ServiceConfigurationContext context, IConfiguration configuration)
{
var certificateFactory = context.Services.GetCertificateFactory();
return certificateFactory.CreateFromPkcs12File(
configuration["App:Certificates:Signing:Path"],
configuration["App:Certificates:Signing:CertPassphrase"]
);
}
using GridLab.Abp.ZeroTrust;
private X509Certificate2 GetEncryptionCertificate(ServiceConfigurationContext context, IConfiguration configuration)
{
var certificateFactory = context.Services.GetCertificateFactory();
return certificateFactory.CreateFromPkcs12File(
configuration["App:Certificates:Encryption:Path"],
configuration["App:Certificates:Encryption:CertPassphrase"]
);
}
Add GetIssuer and GetAccessTokenLifetime specific library options methods.
private string GetIssuer(IConfiguration configuration)
{
// Solves bearer was not authenticated. Failure message: IDX10205: Issuer validation failed.
var issuer = configuration["App:Issuer"]?.Trim();
var selfUrl = configuration["App:SelfUrl"]?.Trim();
if (!string.IsNullOrEmpty(issuer))
return issuer;
if (!string.IsNullOrEmpty(selfUrl))
return selfUrl;
throw new InvalidOperationException("Neither App:Issuer nor App:SelfUrl is provided in configuration.");
}
private TimeSpan GetAccessTokenLifetime(IConfiguration configuration)
{
var accessTokenLifetimeString = configuration["App:AccessTokenLifetime"]?.Trim();
var defaultAccessTokenLifetime = TimeSpan.FromHours(1); // Define a default fallback value (1 hour)
if (TimeSpan.TryParse(accessTokenLifetimeString, out var accessTokenLifetime))
return accessTokenLifetime;
return defaultAccessTokenLifetime;
}
- Add Hangfire support.
Install GridLab.Abp.Hangfire module.
<ItemGroup>
<PackageReference Include="GridLab.Abp.Hangfire" Version="X.Y.Z" />
</ItemGroup>
Replace version number with latest available.
Add the AbpHangfireModule to the dependency list of your module:
[DependsOn(
//...other dependencies
typeof(AbpGridLabHangfireModule)
)]
public class GMSSAuthServerModule : AbpModule
{
}
Configure Hangfire module;
private void ConfigureHangfire(ServiceConfigurationContext context, IConfiguration configuration)
{
string serverName = configuration["Hangfire:ServerName"] ?? "gmss-auth-server";
string schemaName = configuration["Hangfire:SchemaName"] ?? string.Empty;
string? connectionString = configuration.GetConnectionString(GMSSDbProperties.ConnectionStringHangfireName);
if (connectionString.IsNullOrEmpty())
throw new ArgumentNullException(paramName: GMSSDbProperties.ConnectionStringHangfireName);
var serverStorageOptions = new EFCoreStorageOptions
{
CountersAggregationInterval = new TimeSpan(0, 5, 0),
DistributedLockTimeout = new TimeSpan(0, 10, 0),
JobExpirationCheckInterval = new TimeSpan(0, 30, 0),
QueuePollInterval = new TimeSpan(0, 0, 15),
Schema = schemaName,
SlidingInvisibilityTimeout = new TimeSpan(0, 5, 0),
};
var options = new DbContextOptionsBuilder<GMSSHangfireDbContext>()
.UseSqlServer(connectionString)
.Options;
GlobalConfiguration.Configuration.UseEFCoreStorage(
() => new GMSSHangfireDbContext(options, schemaName),
serverStorageOptions
);
Configure<AbpHangfireOptions>(options =>
{
options.Storage = EFCoreStorage.Current;
options.ServerOptions = new BackgroundJobServerOptions() { ServerName = serverName };
});
}
Add a new section for hangfire to application configuration settings.
"Hangfire": {
"ServerName": "gmss-auth-server"
},
Make sure you have updated your connection strings defined under ConnectionString at appsettings.json file.
"ConnectionStrings": {
...
"Hangfire": "Server=(localdb)\\MSSQLLocalDB;Database=gmss-hangfire;Trusted_Connection=True;TrustServerCertificate=true"
}
- Configure caching.
Replace Volo.Abp.Caching.StackExchangeRedis with GridLab.Abp.Caching.StackExchangeValkey module.
Remove:
<ItemGroup>
<PackageReference Include="Volo.Abp.Caching.StackExchangeRedis" Version="X.Y.Z" />
</ItemGroup>
Add:
<ItemGroup>
<PackageReference Include="GridLab.Abp.Caching.StackExchangeValkey" Version="X.Y.Z" />
</ItemGroup>
Replace package at GMSSAuthServerModule.cs
[DependsOn(
typeof(GMSSEntityFrameworkCoreModule)
//...other dependencies
~~typeof(AbpStackExchangeRedisModule),~~
typeof(AbpGridLabStackExchangeValkeyModule),
//...other dependencies
)]
public class GMSSAuthServerModule : AbpModule
{
}
Add ConfigureCache, ConfigureDataProtection and ConfigureDistributedLocking methods for handling cache connections.
private void ConfigureCache(IConfiguration configuration)
{
Configure<AbpDistributedCacheOptions>(options =>
{
options.KeyPrefix = "GMSS:";
});
}
Use AbpValkeyConfigurationHelper.CreateConfigurationOptions helper method to create connection.
private void ConfigureDataProtection(
ServiceConfigurationContext context,
IConfiguration configuration,
IWebHostEnvironment hostingEnvironment)
{
if (AbpStudioAnalyzeHelper.IsInAnalyzeMode)
{
return;
}
var dataProtectionBuilder = context.Services.AddDataProtection().SetApplicationName("GMSS");
if (!hostingEnvironment.IsDevelopment())
{
var certificateProvider = context.Services.GetCertificateProvider();
var certificateValidator = context.Services.GetCertificateValidator();
var options = configuration
.GetSection(AbpGridLabValkeyOptions.ServiceName)
.Get<AbpGridLabValkeyOptions>() ?? new AbpGridLabValkeyOptions();
var configurationOptions = AbpValkeyConfigurationHelper.CreateConfigurationOptions(
serviceOptions: options,
certificateProvider: certificateProvider,
certificateValidator: certificateValidator
);
var redis = ConnectionMultiplexer.Connect(configurationOptions);
dataProtectionBuilder.PersistKeysToStackExchangeRedis(redis, "GMSS-Protection-Keys");
}
}
private void ConfigureDistributedLocking(ServiceConfigurationContext context, IConfiguration configuration)
{
if (AbpStudioAnalyzeHelper.IsInAnalyzeMode)
{
return;
}
context.Services.AddSingleton<IDistributedLockProvider>(sp =>
{
var certificateProvider = context.Services.GetCertificateProvider();
var certificateValidator = context.Services.GetCertificateValidator();
var options = configuration
.GetSection(AbpGridLabValkeyOptions.ServiceName)
.Get<AbpGridLabValkeyOptions>() ?? new AbpGridLabValkeyOptions();
var configurationOptions = AbpValkeyConfigurationHelper.CreateConfigurationOptions(
serviceOptions: options,
certificateProvider: certificateProvider,
certificateValidator: certificateValidator
);
var connection = ConnectionMultiplexer.Connect(configurationOptions);
return new RedisDistributedSynchronizationProvider(connection.GetDatabase());
});
}
Add a new section for caching to application configuration settings.
"Valkey": {
"Enabled": true,
"Configuration": {
"Configuration": "127.0.0.1"
},
"Ssl": {
"Enabled": false
},
"Connection": {
"ConnectTimeout": 30,
"ConnectRetry": 3
}
},
- Activate clock at
GMSSAuthServerModule.cs, defaultKindisUnspecifiedthat actually make the Clock as it doesn't exists at all.
private void ConfigureClock()
{
Configure<AbpClockOptions>(options =>
{
options.Kind = DateTimeKind.Utc;
});
}
- Install
GridLab.Abp.Security.Providers.DockerSecretsmodule.
<ItemGroup>
<PackageReference Include="GridLab.Abp.Security.Providers.DockerSecrets" Version="X.Y.Z" />
</ItemGroup>
Replace version number with latest available.
Extend dependency list at GMSSAuthServerModule.cs
[DependsOn(
typeof(GMSSEntityFrameworkCoreModule)
//
typeof(AbpGridLabSecurityProvidersDockerSecretsModule),
//...other dependencies
)]
public class GMSSAuthServerModule : AbpModule
{
}
.NET Core configuration provider extensions allows reading docker secrets files and pull them into the .net core configuration.
builder.Host
.UseAutofac()
....
.UseSerilog((context, services, loggerConfiguration) =>
{
loggerConfiguration
#if DEBUG
.MinimumLevel.Debug()
.MinimumLevel.Override("DockerSecrets", LogEventLevel.Debug)
#else
.MinimumLevel.Information()
.MinimumLevel.Override("DockerSecrets", LogEventLevel.Information)
#endif
.MinimumLevel.Override("Microsoft", LogEventLevel.Information)
.MinimumLevel.Override("Microsoft.EntityFrameworkCore", LogEventLevel.Warning)
.WriteTo.Async(c => c.Console())
})
....
.ConfigureAppConfiguration((context, config) => {
if (!context.HostingEnvironment.IsDevelopment())
{
config.AddDockerSecrets(
options: () => new DockerSecretsConfigurationOptions
{
ColonPlaceholder = "__"
},
secretsPath: "/run/secrets",
logger: new SerilogLoggerProvider(Log.Logger).CreateLogger("DockerSecrets")
);
}
})
....
- Add new
GMSSBrandingProvider.cscs file to project root directory atGridLab.GMSS.AuthServerproject.
Copy the wwwroot folder from template folder to the src/GridLab.GMSS.AuthServer folder.
Delete existing logo-dark.png and logo-dark.png logos
[Dependency(ReplaceServices = true)]
public class GMSSBrandingProvider : DefaultBrandingProvider
{
private IStringLocalizer<GMSSResource> _localizer;
public GMSSBrandingProvider(IStringLocalizer<GMSSResource> localizer)
{
_localizer = localizer;
}
public override string AppName => "GMSS Auth Server";
public override string LogoUrl => "/images/logo/leptonx/logo-light.png";
public override string LogoReverseUrl => "/images/logo/leptonx/logo-dark.png";
}
- The versions of npm packages defined in
package.jsonshould be checked, where extra npm packages to be used in mvc ui should be defined.
{
"version": "0.1.0",
"name": "my-app-authserver",
"private": true,
"dependencies": {
"@volo/abp.aspnetcore.mvc.ui.theme.lepton": "~8.2.0",
"@volo/account": "~8.2.0"
}
}
add extra packages if necessary
{
"version": "0.1.0",
"name": "my-app-authserver",
"private": true,
"dependencies": {
"@volo/abp.aspnetcore.mvc.ui.theme.lepton": "~8.2.0",
"@volo/account": "~8.2.0",
"ace-builds": "^1.4.12",
"bootstrap-markdown-editor-4": "^3.0.0",
"jquery-datetimepicker": "^2.5.21",
"moment": "^2.29.1"
}
}
In order to run abp install-libs automation scripts, a definition must be made in abp.resourcemapping.js.
module.exports = {
aliases: {
"@node_modules": "./node_modules",
"@libs": "./wwwroot/libs"
},
clean: [
"@libs",
"!@libs/**/foo.txt"
],
mappings: {
"@node_modules/bootstrap-markdown-editor-4/dist/css/bootstrap-markdown-editor.min.css": "@libs/bootstrap-markdown-editor-4/css/",
"@node_modules/bootstrap-markdown-editor-4/dist/js/bootstrap-markdown-editor.min.js": "@libs/bootstrap-markdown-editor-4/js/",
"@node_modules/ace-builds/src-noconflict/ace.js": "@libs/ace/",
"@node_modules/ace-builds/src-noconflict/theme-tomorrow.js": "@libs/ace/",
"@node_modules/ace-builds/src-noconflict/mode-markdown.js": "@libs/ace/",
"@node_modules/ace-builds/src-noconflict/ext-language_tools.js": "@libs/ace/",
"@node_modules/moment/moment.js": "@libs/moment/",
"@node_modules/jquery-datetimepicker/jquery.datetimepicker.js": "@libs/jquery-datetimepicker/",
"@node_modules/jquery-datetimepicker/jquery.datetimepicker.css": "@libs/jquery-datetimepicker/",
}
};
Clean wwwroot/libs and node_modules folders for clean installation. This is required action for abp install-libs script.
ABP CLI's abp install-libs command copies resources from node_modules to wwwroot/libs folder. Each standard package (see the @ABP NPM Packages section) defines the mapping for its own files. So, most of the time, you only configure dependencies.
- Add the following MSBuild instruction to your
GridLab.GMSS.AuthServer.csprojfile in order to load .pdb files during debugging.
<Target Name="_ResolveCopyLocalNuGetPackagePdbs" Condition="$(CopyLocalLockFileAssemblies) == true" AfterTargets="ResolveReferences">
<ItemGroup>
<ReferenceCopyLocalPaths Include="@(ReferenceCopyLocalPaths->'%(RootDir)%(Directory)%(Filename).pdb')" Condition="'%(ReferenceCopyLocalPaths.NuGetPackageId)' != '' and Exists('%(RootDir)%(Directory)%(Filename).pdb')" />
</ItemGroup>
</Target>