using System;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.EntityFrameworkCore;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using OpenIddict.Abstractions;
using OpenIddict.Server.AspNetCore;
using OpenIddict.Validation.AspNetCore;
using OpenIddict.EntityFrameworkCore;
using Volo.Abp;
using Volo.Abp.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonX;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.LeptonX.Bundling;
using Volo.Abp.AspNetCore.Mvc.UI.Theme.Shared;
using Volo.Abp.AspNetCore.Serilog;
using Volo.Abp.Auditing;
using Volo.Abp.AutoMapper;
using Volo.Abp.BackgroundJobs;
using Volo.Abp.Caching;
using Volo.Abp.Identity;
using Volo.Abp.Modularity;
using Volo.Abp.SettingManagement;
using Volo.Abp.VirtualFileSystem;
using Volo.Saas.Host;
using Volo.Abp.OpenIddict;
using Microsoft.IdentityModel.Tokens;
using System.Text;
using Thiqah.Maroof.EntityFrameworkCore;
using Volo.Abp.OpenIddict.Applications;
using Volo.Abp.OpenIddict.Authorizations;
using Volo.Abp.OpenIddict.Scopes;
using Volo.Abp.OpenIddict.Tokens;
using Thiqah.Maroof.MultiTenancy;
using Volo.Abp.Account.Public.Web.Impersonation;
using Volo.Abp.Account.Public.Web;
using Volo.Abp.Account.Web;
using Volo.Abp.Account;
using Volo.Abp.Autofac;
using Localization.Resources.AbpUi;
using Microsoft.AspNetCore.Authentication.Google;
using Microsoft.AspNetCore.Authentication.MicrosoftAccount;
using Microsoft.AspNetCore.Authentication.Twitter;
using Microsoft.AspNetCore.Cors;
using Microsoft.AspNetCore.DataProtection;
using Microsoft.AspNetCore.Extensions.DependencyInjection;
using Thiqah.Maroof.Localization;
using Volo.Abp.AspNetCore.Mvc.UI.Bundling;
using Volo.Abp.LeptonX.Shared;
using Volo.Abp.Localization;
using Volo.Abp.UI.Navigation.Urls;
using Volo.Abp.Account.Public.Web.ExternalProviders;
namespace Thiqah.Maroof
{
[DependsOn(
// ... other dependencies
typeof(AbpAspNetCoreMvcUiLeptonXThemeModule),
typeof(AbpOpenIddictAspNetCoreModule),
typeof(AbpOpenIddictDomainModule),
typeof(AbpSettingManagementDomainModule),
typeof(AbpAutofacModule),
typeof(AbpAspNetCoreSerilogModule),
typeof(AbpAccountPublicWebOpenIddictModule),
typeof(AbpAccountPublicHttpApiModule),
typeof(AbpAccountPublicApplicationModule),
typeof(AbpAccountPublicWebImpersonationModule),
typeof(SaasHostApplicationContractsModule),
typeof(MaroofEntityFrameworkCoreModule),
typeof(MaroofApplicationContractsModule),
typeof(MaroofDomainModule),
typeof(MaroofDomainSharedModule),
typeof(AbpAccountAdminApplicationContractsModule),
typeof(AbpAccountPublicApplicationContractsModule),
typeof(AbpAccountPublicWebModule),
typeof(AbpAccountSharedApplicationContractsModule),
typeof(AbpAccountSharedApplicationModule),
typeof(AbpAuditingModule),
typeof(AbpAutoMapperModule),
typeof(AbpCachingModule),
typeof(AbpSettingManagementDomainSharedModule)
)]
public class MaroofAuthServerModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
var configuration = context.Services.GetConfiguration();
PreConfigure<OpenIddictBuilder>(builder =>
{
builder.AddValidation(options =>
{
options.AddAudiences("XXXXX");
options.SetIssuer("https://localhost:44371");
options.UseAspNetCore();
options.UseLocalServer();
options.SetClientId("XXXXX")
.SetClientSecret("XXXXXXX");
})
.AddServer(options =>
{
options
.AllowClientCredentialsFlow();
options.SetIssuer("https://localhost:44371");
options.SetAuthorizationEndpointUris("/connect/authorize");
options.SetTokenEndpointUris("/connect/token");
options.SetUserinfoEndpointUris("/connect/userinfo");
options.SetIntrospectionEndpointUris("/connect/introspect");
options.SetLogoutEndpointUris("/connect/logout");
options.SetConfigurationEndpointUris("/.well-known/openid-configuration");
options.AllowAuthorizationCodeFlow()
.AllowPasswordFlow()
.AllowRefreshTokenFlow();
options.DisableScopeValidation();
options.RegisterScopes(OpenIddictConstants.Scopes.OpenId, OpenIddictConstants.Scopes.OfflineAccess, OpenIddictConstants.Scopes.Email);
options
.AddEphemeralEncryptionKey()
.AddEphemeralSigningKey();
options.UseAspNetCore()
.EnableTokenEndpointPassthrough();
options.AcceptAnonymousClients();
});
});
if (!hostingEnvironment.IsDevelopment())
{
PreConfigure<AbpOpenIddictAspNetCoreOptions>(options =>
{
options.AddDevelopmentEncryptionAndSigningCertificate = false;
});
PreConfigure<OpenIddictServerBuilder>(builder =>
{
builder.AddSigningCertificate(GetSigningCertificate(hostingEnvironment, configuration));
builder.AddEncryptionCertificate(GetSigningCertificate(hostingEnvironment, configuration));
builder.SetIssuer(new Uri(configuration["AuthServer:Authority"]));
});
}
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
var hostingEnvironment = context.Services.GetHostingEnvironment();
var configuration = context.Services.GetConfiguration();
context.Services.AddDbContext<MaroofDbContext>(options =>
{
options.UseSqlServer(configuration["ConnectionStrings:Default"]);
options.UseOpenIddict();
});
context.Services.AddOpenIddict().AddCore(options =>
{
var stors = options.UseEntityFrameworkCore()
.UseDbContext<MaroofDbContext>();
options.AddApplicationStore<AbpOpenIddictApplicationStore>();
options.AddAuthorizationStore<AbpOpenIddictAuthorizationStore>();
options.AddScopeStore<AbpOpenIddictScopeStore>();
options.AddTokenStore<AbpOpenIddictTokenStore>();
});
if (!Convert.ToBoolean(configuration["App:DisablePII"]))
{
Microsoft.IdentityModel.Logging.IdentityModelEventSource.ShowPII = true;
}
if (!Convert.ToBoolean(configuration["AuthServer:RequireHttpsMetadata"]))
{
Configure<OpenIddictServerAspNetCoreOptions>(options =>
{
options.DisableTransportSecurityRequirement = true;
});
}
context.Services.ForwardIdentityAuthenticationForBearer(OpenIddictValidationAspNetCoreDefaults.AuthenticationScheme);
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Get<MaroofResource>()
.AddBaseTypes(
typeof(AbpUiResource)
);
});
Configure<AbpBundlingOptions>(options =>
{
options.StyleBundles.Configure(
LeptonXThemeBundles.Styles.Global,
bundle =>
{
bundle.AddFiles("/global-styles.css");
}
);
});
Configure<AbpAuditingOptions>(options =>
{
options.ApplicationName = "AuthServer";
});
Configure<AppUrlOptions>(options =>
{
options.Applications["MVC"].RootUrl = configuration["App:SelfUrl"];
options.RedirectAllowedUrls.AddRange(configuration["App:RedirectAllowedUrls"]?.Split(',') ?? Array.Empty<string>());
options.Applications["Angular"].RootUrl = configuration["App:AngularUrl"];
options.Applications["Angular"].Urls[AccountUrlNames.PasswordReset] = "account/reset-password";
options.Applications["Angular"].Urls[AccountUrlNames.EmailConfirmation] = "account/email-confirmation";
});
Configure<AbpBackgroundJobOptions>(options =>
{
options.IsJobExecutionEnabled = false;
});
Configure<AbpDistributedCacheOptions>(options =>
{
options.KeyPrefix = "Maroof:";
});
var dataProtectionBuilder = context.Services.AddDataProtection().SetApplicationName("XXXXX");
//if (!hostingEnvironment.IsDevelopment())
//{
// var redis = ConnectionMultiplexer.Connect(configuration["Redis:Configuration"]);
// dataProtectionBuilder.PersistKeysToStackExchangeRedis(redis, "BookStore-Protection-Keys");
//}
//context.Services.AddSingleton<IDistributedLockProvider>(sp =>
//{
// var connection = ConnectionMultiplexer
// .Connect(configuration["Redis:Configuration"]);
// return new RedisDistributedSynchronizationProvider(connection.GetDatabase());
//});
context.Services.AddCors(options =>
{
options.AddDefaultPolicy(builder =>
{
builder
.WithOrigins(
configuration["App:CorsOrigins"]?
.Split(",", StringSplitOptions.RemoveEmptyEntries)
.Select(o => o.Trim().RemovePostFix("/"))
.ToArray() ?? Array.Empty<string>()
)
.WithAbpExposedHeaders()
.SetIsOriginAllowedToAllowWildcardSubdomains()
.AllowAnyHeader()
.AllowAnyMethod()
.AllowCredentials();
});
});
context.Services.AddAuthentication()
.AddGoogle(GoogleDefaults.AuthenticationScheme, _ => { })
.WithDynamicOptions<GoogleOptions, GoogleHandler>(
GoogleDefaults.AuthenticationScheme,
options =>
{
options.WithProperty(x => x.ClientId);
options.WithProperty(x => x.ClientSecret, isSecret: true);
}
)
.AddMicrosoftAccount(MicrosoftAccountDefaults.AuthenticationScheme, options =>
{
options.AuthorizationEndpoint = "https://login.microsoftonline.com/consumers/oauth2/v2.0/authorize";
options.TokenEndpoint = "https://login.microsoftonline.com/consumers/oauth2/v2.0/token";
})
.WithDynamicOptions<MicrosoftAccountOptions, MicrosoftAccountHandler>(
MicrosoftAccountDefaults.AuthenticationScheme,
options =>
{
options.WithProperty(x => x.ClientId);
options.WithProperty(x => x.ClientSecret, isSecret: true);
}
)
.AddTwitter(TwitterDefaults.AuthenticationScheme, options => options.RetrieveUserDetails = true)
.WithDynamicOptions<TwitterOptions, TwitterHandler>(
TwitterDefaults.AuthenticationScheme,
options =>
{
options.WithProperty(x => x.ConsumerKey);
options.WithProperty(x => x.ConsumerSecret, isSecret: true);
}
);
context.Services.Configure<AbpAccountOptions>(options =>
{
options.TenantAdminUserName = "admin";
options.ImpersonationTenantPermission = SaasHostPermissions.Tenants.Impersonation;
options.ImpersonationUserPermission = IdentityPermissions.Users.Impersonation;
});
Configure<LeptonXThemeOptions>(options =>
{
options.DefaultStyle = LeptonXStyleNames.System;
});
}
public override void OnApplicationInitialization(ApplicationInitializationContext context)
{
var app = context.GetApplicationBuilder();
var env = context.GetEnvironment();
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseAbpRequestLocalization();
if (!env.IsDevelopment())
{
app.UseErrorPage();
}
app.UseCorrelationId();
app.UseAbpSecurityHeaders();
app.UseStaticFiles();
app.UseRouting();
app.UseCors();
app.UseAuthentication();
app.UseAbpOpenIddictValidation();
if (MultiTenancyConsts.IsEnabled)
{
app.UseMultiTenancy();
}
app.UseUnitOfWork();
app.UseAuthorization();
app.UseAuditing();
app.UseAbpSerilogEnrichers();
app.UseConfiguredEndpoints();
}
private X509Certificate2 GetSigningCertificate(IWebHostEnvironment hostingEnv, IConfiguration configuration)
{
var fileName = "authserver.pfx";
var passPhrase = "2D7AA457-5D33-48D6-936F-C48E5EF468ED";
var file = Path.Combine(hostingEnv.ContentRootPath, fileName);
if (!File.Exists(file))
{
throw new FileNotFoundException($"Signing Certificate couldn't found: {file}");
}
return new X509Certificate2(file, passPhrase);
}
}
}
Autofac.Core.DependencyResolutionException: An exception was thrown while activating OpenIddict.Server.OpenIddictServerHandlers+Exchange+ValidateClientId -> λ:OpenIddict.Abstractions.IOpenIddictApplicationManager -> Volo.Abp.OpenIddict.Applications.AbpApplicationManager -> Volo.Abp.OpenIddict.Applications.AbpOpenIddictApplicationCache -> Volo.Abp.OpenIddict.Applications.AbpOpenIddictApplicationStore. ---> Autofac.Core.DependencyResolutionException: None of the constructors found on type 'Volo.Abp.OpenIddict.Applications.AbpOpenIddictApplicationStore' can be invoked with the available services and parameters: Cannot resolve parameter 'Volo.Abp.OpenIddict.Applications.IOpenIddictApplicationRepository repository' of constructor 'Void .ctor(Volo.Abp.OpenIddict.Applications.IOpenIddictApplicationRepository, Volo.Abp.Uow.IUnitOfWorkManager, Volo.Abp.OpenIddict.Tokens.IOpenIddictTokenRepository, Volo.Abp.Guids.IGuidGenerator, Volo.Abp.OpenIddict.AbpOpenIddictIdentifierConverter, Volo.Abp.OpenIddict.IOpenIddictDbConcurrencyExceptionHandler)'.