diff --git a/apps/auth-server/src/EShopOnAbp.AuthServer/EShopOnAbpAuthServerModule.cs b/apps/auth-server/src/EShopOnAbp.AuthServer/EShopOnAbpAuthServerModule.cs index 7e304d5c..10a23010 100644 --- a/apps/auth-server/src/EShopOnAbp.AuthServer/EShopOnAbpAuthServerModule.cs +++ b/apps/auth-server/src/EShopOnAbp.AuthServer/EShopOnAbpAuthServerModule.cs @@ -12,11 +12,15 @@ using System; using System.Collections.Generic; using System.IO; using System.Linq; +using System.Security.Claims; using System.Security.Cryptography.X509Certificates; +using System.Threading.Tasks; using IdentityServer4.Configuration; using IdentityServer4.Extensions; +using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Hosting; using Microsoft.Extensions.Configuration; +using Microsoft.IdentityModel.Protocols.OpenIdConnect; using Volo.Abp; using Volo.Abp.Account; using Volo.Abp.Account.Web; @@ -80,6 +84,8 @@ public class EShopOnAbpAuthServerModule : AbpModule ConfigureSwagger(context, configuration); + ConfigureExternalProviders(context, configuration); + context.Services.AddAuthentication() .AddJwtBearer(options => { @@ -148,6 +154,41 @@ public class EShopOnAbpAuthServerModule : AbpModule } } + private void ConfigureExternalProviders(ServiceConfigurationContext context, IConfiguration configuration) + { + Configure(options => + { + options.RequestedClaims.AddRange(new[]{ + "ipaddr", + "myCustomClaimFromAzure" + }); + }); + context.Services.AddAuthentication() + .AddOpenIdConnect("AzureOpenId", "Azure AD OpenId", options => + { + options.Authority = "https://login.microsoftonline.com/" + configuration["AzureAd:TenantId"] + + "/v2.0/"; + options.ClientId = configuration["AzureAd:ClientId"]; + options.ResponseType = OpenIdConnectResponseType.CodeIdToken; + options.CallbackPath = configuration["AzureAd:CallbackPath"]; + options.ClientSecret = configuration["AzureAd:ClientSecret"]; + options.RequireHttpsMetadata = false; + options.SaveTokens = false; + options.GetClaimsFromUserInfoEndpoint = true; + options.Scope.Add("email"); + + options.ClaimActions.Remove("ipaddr"); + + options.ClaimActions.MapJsonKey(ClaimTypes.NameIdentifier, "sub"); + + options.Events.OnTokenValidated = async ctx => + { + var claimsFromOidcProvider = ctx.Principal?.Claims.ToList(); // AzureAD claims + await Task.CompletedTask; + }; + }); + } + public override void OnApplicationInitialization(ApplicationInitializationContext context) { var app = context.GetApplicationBuilder(); @@ -197,7 +238,6 @@ public class EShopOnAbpAuthServerModule : AbpModule app.UseAuditing(); app.UseConfiguredEndpoints(); } - private X509Certificate2 GetSigningCertificate(IWebHostEnvironment hostingEnv) { const string fileName = "eshoponabp-authserver.pfx"; @@ -211,7 +251,6 @@ public class EShopOnAbpAuthServerModule : AbpModule return new X509Certificate2(file, passPhrase); } - private void ConfigureSwagger(ServiceConfigurationContext context, IConfiguration configuration) { SwaggerWithAuthConfigurationHelper.Configure( @@ -228,4 +267,4 @@ public class EShopOnAbpAuthServerModule : AbpModule apiTitle: "Account Service API" ); } -} \ No newline at end of file +} diff --git a/apps/auth-server/src/EShopOnAbp.AuthServer/EShopUserPrincipleFactory.cs b/apps/auth-server/src/EShopOnAbp.AuthServer/EShopUserPrincipleFactory.cs new file mode 100644 index 00000000..7864c420 --- /dev/null +++ b/apps/auth-server/src/EShopOnAbp.AuthServer/EShopUserPrincipleFactory.cs @@ -0,0 +1,57 @@ +using System.Linq; +using System.Security.Claims; +using System.Security.Principal; +using System.Threading.Tasks; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Http; +using Microsoft.AspNetCore.Identity; +using Microsoft.EntityFrameworkCore.Infrastructure; +using Microsoft.Extensions.Options; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Identity; +using Volo.Abp.Security.Claims; +using IdentityRole = Volo.Abp.Identity.IdentityRole; +using IdentityUser = Volo.Abp.Identity.IdentityUser; + +namespace EShopOnAbp.AuthServer; + +[Dependency(ReplaceServices = true)] +[ExposeServices(typeof(AbpUserClaimsPrincipalFactory))] +public class EShopUserPrincipleFactory: AbpUserClaimsPrincipalFactory +{ + private readonly IHttpContextAccessor _httpContextAccessor; + + public EShopUserPrincipleFactory(UserManager userManager, + RoleManager roleManager, + IOptions options, + ICurrentPrincipalAccessor currentPrincipalAccessor, + IAbpClaimsPrincipalFactory abpClaimsPrincipalFactory, + IHttpContextAccessor httpContextAccessor) : base(userManager, + roleManager, + options, + currentPrincipalAccessor, + abpClaimsPrincipalFactory) + { + _httpContextAccessor = httpContextAccessor; + } + + public override async Task CreateAsync(IdentityUser user) + { + var principal = await base.CreateAsync(user); + var identity = principal.Identities.First(); + if (_httpContextAccessor.HttpContext != null) + { + var auth = await _httpContextAccessor.HttpContext.AuthenticateAsync(IdentityConstants.ExternalScheme); + if (auth.Succeeded) + { + var ipaddr = auth?.Principal?.FindFirst("ipaddr"); + if (ipaddr != null) + { + identity?.AddIfNotContains(ipaddr); + } + } + } + + return principal; + } +} diff --git a/apps/auth-server/src/EShopOnAbp.AuthServer/Pages/Index.cshtml.cs b/apps/auth-server/src/EShopOnAbp.AuthServer/Pages/Index.cshtml.cs index 29fe87d3..88ad3ba0 100644 --- a/apps/auth-server/src/EShopOnAbp.AuthServer/Pages/Index.cshtml.cs +++ b/apps/auth-server/src/EShopOnAbp.AuthServer/Pages/Index.cshtml.cs @@ -7,6 +7,8 @@ namespace EShopOnAbp.AuthServer.Pages { public ActionResult OnGet() { + var ipaddr = CurrentUser.FindClaim("ipaddr"); + if (!CurrentUser.IsAuthenticated) { return Redirect("~/Account/Login"); diff --git a/apps/auth-server/src/EShopOnAbp.AuthServer/appsettings.json b/apps/auth-server/src/EShopOnAbp.AuthServer/appsettings.json index 290fc0f6..23d90329 100644 --- a/apps/auth-server/src/EShopOnAbp.AuthServer/appsettings.json +++ b/apps/auth-server/src/EShopOnAbp.AuthServer/appsettings.json @@ -22,6 +22,15 @@ "IdentityService": "User ID=postgres;Password=myPassw0rd;Host=localhost;Port=5432;Database=EShopOnAbp_Identity;Pooling=false;", "AdministrationService": "User ID=postgres;Password=myPassw0rd;Host=localhost;Port=5432;Database=EShopOnAbp_Administration;Pooling=false;" }, + "AzureAd": { + "Instance": "https://login.microsoftonline.com/", + "TenantId": "5b97904e-f789-4453-96b8-65004e6409f1", + "ClientId": "5780c686-bc9e-4dcd-843d-6729c547f1f8", + "Domain": "domain.onmicrosoft.com", + "CallbackPath": "/signin-azuread-oidc", + "SignedOutCallbackPath ": "/signout-azuread-oidc", + "ClientSecret": "6Or7Q~knYyJsAhKswJ5gMhbQ.zFYxlkkmIiyE" + }, "StringEncryption": { "DefaultPassPhrase": "gsKnGZ041HLL4IM8" }, @@ -42,4 +51,4 @@ "ElasticSearch": { "Url": "http://localhost:9200" } -} +} \ No newline at end of file