diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Microsoft/Extensions/DependencyInjection/AbpOpenIdConnectExtensions.cs b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Microsoft/Extensions/DependencyInjection/AbpOpenIdConnectExtensions.cs index 894ba470a8..2a2d0a712d 100644 --- a/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Microsoft/Extensions/DependencyInjection/AbpOpenIdConnectExtensions.cs +++ b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Microsoft/Extensions/DependencyInjection/AbpOpenIdConnectExtensions.cs @@ -3,8 +3,10 @@ using System.Threading.Tasks; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authentication.OAuth.Claims; using Microsoft.AspNetCore.Authentication.OpenIdConnect; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; using Microsoft.IdentityModel.Protocols.OpenIdConnect; +using Volo.Abp.AspNetCore.Authentication.OpenIdConnect; using Volo.Abp.AspNetCore.MultiTenancy; namespace Microsoft.Extensions.DependencyInjection; @@ -47,6 +49,20 @@ public static class AbpOpenIdConnectExtensions } return Task.CompletedTask; }; + + options.Events.OnTokenValidated = async (context) => + { + var client = context.HttpContext.RequestServices.GetRequiredService(); + try + { + await client.CreateOrUpdateAsync(context); + } + catch (Exception ex) + { + var logger = context.HttpContext.RequestServices.GetService>(); + logger?.LogException(ex); + } + }; }); } diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo.Abp.AspNetCore.Authentication.OpenIdConnect.csproj b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo.Abp.AspNetCore.Authentication.OpenIdConnect.csproj index 6e6b2aa109..48cf90f03c 100644 --- a/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo.Abp.AspNetCore.Authentication.OpenIdConnect.csproj +++ b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo.Abp.AspNetCore.Authentication.OpenIdConnect.csproj @@ -15,6 +15,7 @@ + diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo/Abp/AspNetCore/Authentication/OpenIdConnect/AbpAspNetCoreAuthenticationOpenIdConnectModule.cs b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo/Abp/AspNetCore/Authentication/OpenIdConnect/AbpAspNetCoreAuthenticationOpenIdConnectModule.cs index 8670fbea17..6b66a105d3 100644 --- a/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo/Abp/AspNetCore/Authentication/OpenIdConnect/AbpAspNetCoreAuthenticationOpenIdConnectModule.cs +++ b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo/Abp/AspNetCore/Authentication/OpenIdConnect/AbpAspNetCoreAuthenticationOpenIdConnectModule.cs @@ -1,12 +1,15 @@ using Volo.Abp.AspNetCore.Authentication.OAuth; using Volo.Abp.Modularity; using Volo.Abp.MultiTenancy; +using Volo.Abp.RemoteServices; namespace Volo.Abp.AspNetCore.Authentication.OpenIdConnect; [DependsOn( typeof(AbpMultiTenancyModule), - typeof(AbpAspNetCoreAuthenticationOAuthModule))] + typeof(AbpAspNetCoreAuthenticationOAuthModule), + typeof(AbpRemoteServicesModule) + )] public class AbpAspNetCoreAuthenticationOpenIdConnectModule : AbpModule { diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo/Abp/AspNetCore/Authentication/OpenIdConnect/IOpenIdLocalUserCreationClient.cs b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo/Abp/AspNetCore/Authentication/OpenIdConnect/IOpenIdLocalUserCreationClient.cs new file mode 100644 index 0000000000..5b6b8ee61d --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo/Abp/AspNetCore/Authentication/OpenIdConnect/IOpenIdLocalUserCreationClient.cs @@ -0,0 +1,9 @@ +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication.OpenIdConnect; + +namespace Volo.Abp.AspNetCore.Authentication.OpenIdConnect; + +public interface IOpenIdLocalUserCreationClient +{ + Task CreateOrUpdateAsync(TokenValidatedContext tokenValidatedContext); +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo/Abp/AspNetCore/Authentication/OpenIdConnect/OpenIdLocalUserCreationClient.cs b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo/Abp/AspNetCore/Authentication/OpenIdConnect/OpenIdLocalUserCreationClient.cs new file mode 100644 index 0000000000..d0d71ca6d4 --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo/Abp/AspNetCore/Authentication/OpenIdConnect/OpenIdLocalUserCreationClient.cs @@ -0,0 +1,59 @@ +using System; +using System.Net.Http; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication.OpenIdConnect; +using Microsoft.Extensions.Options; +using Microsoft.Net.Http.Headers; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Http.Client; + +namespace Volo.Abp.AspNetCore.Authentication.OpenIdConnect; + +public class OpenIdLocalUserCreationClient : IOpenIdLocalUserCreationClient, ITransientDependency +{ + protected OpenIdLocalUserCreationClientOptions Options { get; } + protected IHttpClientFactory HttpClientFactory { get; } + protected IRemoteServiceConfigurationProvider RemoteServiceConfigurationProvider { get; } + + public OpenIdLocalUserCreationClient( + IOptions options, + IHttpClientFactory httpClientFactory, + IRemoteServiceConfigurationProvider remoteServiceConfigurationProvider) + { + HttpClientFactory = httpClientFactory; + RemoteServiceConfigurationProvider = remoteServiceConfigurationProvider; + Options = options.Value; + } + + public virtual async Task CreateOrUpdateAsync(TokenValidatedContext context) + { + if (!Options.IsEnabled) + { + return; + } + + using (var httpClient = HttpClientFactory.CreateClient(Options.HttpClientName)) + { + if (!Options.RemoteServiceName.IsNullOrWhiteSpace()) + { + var configuration = await RemoteServiceConfigurationProvider.GetConfigurationOrDefaultAsync(Options.RemoteServiceName); + if (configuration.BaseUrl != null) + { + httpClient.BaseAddress = new Uri(configuration.BaseUrl); + } + } + + httpClient.DefaultRequestHeaders.Add( + HeaderNames.Authorization, + "Bearer " + context.SecurityToken.RawData + ); + + var response = await httpClient.PostAsync( + Options.Url, + new StringContent(string.Empty) + ); + + response.EnsureSuccessStatusCode(); + } + } +} \ No newline at end of file diff --git a/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo/Abp/AspNetCore/Authentication/OpenIdConnect/OpenIdLocalUserCreationClientOptions.cs b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo/Abp/AspNetCore/Authentication/OpenIdConnect/OpenIdLocalUserCreationClientOptions.cs new file mode 100644 index 0000000000..02bbae675a --- /dev/null +++ b/framework/src/Volo.Abp.AspNetCore.Authentication.OpenIdConnect/Volo/Abp/AspNetCore/Authentication/OpenIdConnect/OpenIdLocalUserCreationClientOptions.cs @@ -0,0 +1,32 @@ +using System.Net.Http; + +namespace Volo.Abp.AspNetCore.Authentication.OpenIdConnect; + +public class OpenIdLocalUserCreationClientOptions +{ + /// + /// Can be used to enable/disable request to the server to create/update local users. + /// Default value: false + /// + public bool IsEnabled { get; set; } + + /// + /// Default value: "AbpIdentity". + /// Fallbacks to the "Default" remote service configuration, if "AbpIdentity" configuration is not available. + /// Set to null if you don't want to use a remote service configuration. In this case, you can set an + /// absolute URL in the option. + /// + public string RemoteServiceName { get; set; } = "AbpIdentity"; + + /// + /// URL to make a POST request after the current user successfully authenticated through an OpenIdConnect provider. + /// + public string Url { get; set; } = "/api/identity-profile/create-or-update"; + + /// + /// Can be set to a value if you want to use a named instance + /// while creating it from . + /// Default value: "" (). + /// + public string HttpClientName { get; } = Microsoft.Extensions.Options.Options.DefaultName; +} \ No newline at end of file