diff --git a/.gitignore b/.gitignore index a8491e0f..5fbdcfed 100644 --- a/.gitignore +++ b/.gitignore @@ -44,3 +44,4 @@ yavsc-pre *.env generated/ +*.lscache diff --git a/.vscode/settings.json b/.vscode/settings.json index 79924b17..cf480807 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -13,5 +13,8 @@ "fr" ], "cSpell.reportUnknownWords": true, - "cSpell.language": "fr,fr-FR,en,en-GB" + "cSpell.language": "fr,fr-FR,en,en-GB", + "chat.tools.terminal.autoApprove": { + "dotnet test": true + } } diff --git a/src/Yavsc.Org/Extensions/HostingExtensions.cs b/src/Yavsc.Org/Extensions/HostingExtensions.cs index f75cf7e7..4eedb087 100644 --- a/src/Yavsc.Org/Extensions/HostingExtensions.cs +++ b/src/Yavsc.Org/Extensions/HostingExtensions.cs @@ -1,16 +1,18 @@ -using System.Diagnostics; using System.Globalization; +using System.IdentityModel.Tokens.Jwt; +using System.Reflection; using Google.Apis.Util.Store; +using IdentityModel; using IdentityServer8; -using Microsoft.Extensions.DependencyInjection; +using IdentityServer8.EntityFramework.Entities; +using IdentityServer8.EntityFramework.Services; +using IdentityServer8.EntityFramework.Stores; using IdentityServer8.Stores; -using IdentityServer8.EntityFramework; -using IdentityServer8.Extensions; - -using Microsoft.AspNetCore.Authentication; +using IdentityServer8.Validation; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.DataProtection; using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.AspNetCore.Localization; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Razor; @@ -22,28 +24,12 @@ using Microsoft.Net.Http.Headers; using Newtonsoft.Json; using Yavsc.Helpers; using Yavsc.Interface; +using Yavsc.Interfaces; using Yavsc.Models; +using Yavsc.Server.Helpers; using Yavsc.Services; using Yavsc.Settings; using Yavsc.ViewModels.Auth; -using Yavsc.Server.Helpers; -using System.Security.Cryptography; -using Microsoft.IdentityModel.Tokens; -using Microsoft.IdentityModel.Protocols.Configuration; -using IdentityModel; -using Yavsc.Interfaces; -using Microsoft.AspNetCore.Identity.EntityFrameworkCore; -using Npgsql; -using System.Reflection; -using IdentityServer8.EntityFramework.DbContexts; -using IdentityServer8.EntityFramework.Mappers; -using System.IdentityModel.Tokens.Jwt; -using IdentityServer8.EntityFramework.Stores; -using IdentityServer8.EntityFramework.Services; -using IdentityServer8.EntityFramework.Interfaces; -using Microsoft.AspNetCore.Authentication.Cookies; -using IdentityServer8.Validation; -using IdentityServer8.EntityFramework.Entities; namespace Yavsc.Extensions; @@ -177,7 +163,7 @@ public static class HostingExtensions }); } - return services.AddIdentity( + var identityBuilder = services.AddIdentity( options => { options.SignIn.RequireConfirmedAccount = builder.Environment.IsEnvironment( @@ -187,6 +173,10 @@ public static class HostingExtensions } ) .AddEntityFrameworkStores(); + + services.AddScoped, UserClaimsPrincipalFactory>(); + + return identityBuilder; } private static void AddYavscPolicies(IServiceCollection services) @@ -280,7 +270,7 @@ public static class HostingExtensions }); } - private static IIdentityServerBuilder AddIdentityServer(WebApplicationBuilder builder) + public static IIdentityServerBuilder AddIdentityServer(WebApplicationBuilder builder) { builder.Services.Configure(options => { diff --git a/src/Yavsc.Org/Helpers/EventHelpers.cs b/src/Yavsc.Org/Helpers/EventHelpers.cs index d9f90dc3..48c23c1b 100644 --- a/src/Yavsc.Org/Helpers/EventHelpers.cs +++ b/src/Yavsc.Org/Helpers/EventHelpers.cs @@ -50,7 +50,7 @@ namespace Yavsc.Helpers } public static string GetSender(this ApplicationUser user) { - return user.UserName+" ["+user.Id+"@"+Config.Authority+"]"; + return user.UserName+" ["+user.Id+"@"+Config.AuthorityDomain+"]"; } public static HairCutQueryEvent CreateEvent(this HairMultiCutQuery query, IStringLocalizer SR, BrusherProfile bpr) diff --git a/src/Yavsc.Server/Config.cs b/src/Yavsc.Server/Config.cs index 7340770e..5d2bcdff 100644 --- a/src/Yavsc.Server/Config.cs +++ b/src/Yavsc.Server/Config.cs @@ -9,8 +9,24 @@ namespace Yavsc; public static class Config { + /// + /// Authority URL for IdentityServer, used for authentication and authorization. + /// public static string Authority { get; set; } + public static string AuthorityDomain + { + get + { + if (Uri.TryCreate(Authority, UriKind.Absolute, out var uri)) + { + return uri.GetLeftPart(UriPartial.Authority); + } + throw new InvalidOperationException("Invalid Authority URL"); + } + } + + public static IConfigurationRoot? GoogleWebClientConfiguration { get; set; } public static GoogleServiceAccount? GServiceAccount { get; set; } diff --git a/test/yavscTests/Mandatory/Remoting.cs b/test/yavscTests/Mandatory/Remoting.cs index b22c9a17..9d3aae6b 100644 --- a/test/yavscTests/Mandatory/Remoting.cs +++ b/test/yavscTests/Mandatory/Remoting.cs @@ -1,9 +1,8 @@ -using isnd.tests; +using System.Security.Cryptography.X509Certificates; +using System.Net.Security; +using isnd.tests; using Xunit.Abstractions; using IdentityModel.Client; -using System.Net; -using System.Security.Cryptography.X509Certificates; -using System.Net.Security; namespace yavscTests { @@ -20,64 +19,55 @@ namespace yavscTests [Fact] public async Task ObtainServiceToken() - { - var serverUrl = _serverFixture.Addresses.FirstOrDefault( - u => u.StartsWith("https:") - ); + { + var serverUrl = _serverFixture.Addresses.FirstOrDefault(u => u.StartsWith("https:")); + if (string.IsNullOrEmpty(serverUrl)) + throw new InvalidOperationException("No HTTPS server address found"); + + HttpClient client = NewHttpClient(); + var disco = await client.GetDiscoveryDocumentAsync(serverUrl); + if (disco.IsError) throw new Exception(disco.Error); - String authority = _serverFixture.SiteSettings.Authority; - HttpClient client = NewHttpClient(); - var disco = await client.GetDiscoveryDocumentAsync(authority); - if (disco.IsError) throw new Exception(disco.Error); - - var response = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest - { - Address = disco.TokenEndpoint, - ClientId = _serverFixture.TestClientId, - ClientSecret = _serverFixture.TestClientSecret, - Scope = "test", - GrantType = "client_credentials" - }); - /*"mvc"; - options.ClientSecret = "49C1A7E1-0C79-4A89-A3D6-A37998FB86B0";*/ - if (response.IsError) throw new Exception(response.Error); - - } + var response = await client.RequestClientCredentialsTokenAsync(new ClientCredentialsTokenRequest + { + Address = disco.TokenEndpoint, + ClientId = _serverFixture.TestClientId, + ClientSecret = _serverFixture.TestClientSecret, + Scope = "test", + GrantType = "client_credentials" + }); + if (response.IsError) throw new Exception(response.Error); + } private static HttpClient NewHttpClient() { return new HttpClient(new BypassSslValidationHandler()); } - [Fact] + [Fact] public async Task ObtainResourceOwnerPasswordToken() { - var serverUrl = _serverFixture.Addresses.FirstOrDefault( - u => u.StartsWith("https:") - ); - - String authority = _serverFixture.SiteSettings.Authority; + var serverUrl = _serverFixture.Addresses.FirstOrDefault(u => u.StartsWith("https:")); + if (string.IsNullOrEmpty(serverUrl)) + throw new InvalidOperationException("No HTTPS server address found"); + var client = NewHttpClient(); - var disco = await client.GetDiscoveryDocumentAsync(authority); + var disco = await client.GetDiscoveryDocumentAsync(serverUrl); if (disco.IsError) throw new Exception(disco.Error); var response = await client.RequestPasswordTokenAsync(new PasswordTokenRequest - { - Address = disco.TokenEndpoint, - - ClientId = _serverFixture.TestClientId, - ClientSecret = _serverFixture.TestClientSecret, - - UserName = _serverFixture.TestingUserName, - Password = _serverFixture.TestingUserPassword, - - Scope = "test", - - Parameters = + { + Address = disco.TokenEndpoint, + ClientId = _serverFixture.TestClientId, + ClientSecret = _serverFixture.TestClientSecret, + UserName = _serverFixture.TestingUserName, + Password = _serverFixture.TestingUserPassword, + Scope = "test", + Parameters = { { "acr_values", "tenant:custom_account_store1 foo bar quux" } } - }); + }); if (response.IsError) throw new Exception(response.Error); diff --git a/test/yavscTests/WebServerFixture.cs b/test/yavscTests/WebServerFixture.cs index 2e2cf674..e07c350e 100644 --- a/test/yavscTests/WebServerFixture.cs +++ b/test/yavscTests/WebServerFixture.cs @@ -1,20 +1,24 @@ +using IdentityServer8.EntityFramework.Entities; +using IdentityServer8.Models; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting.Server; using Microsoft.AspNetCore.Hosting.Server.Features; using Microsoft.AspNetCore.Identity; +using Microsoft.AspNetCore.Server.Kestrel.Core; +using Microsoft.EntityFrameworkCore; using Microsoft.Extensions.Configuration; using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using Yavsc; -using Yavsc.Models; -using Yavsc.Extensions; -using Microsoft.EntityFrameworkCore; using Serilog; using Serilog.Events; using Serilog.Sinks.SystemConsole.Themes; -using IdentityServer8.EntityFramework.Entities; -using IdentityServer8.Models; +using System.Net; +using System.Security.Cryptography; +using System.Security.Cryptography.X509Certificates; +using Yavsc; +using Yavsc.Extensions; +using Yavsc.Models; using Client = IdentityServer8.EntityFramework.Entities.Client; namespace isnd.tests @@ -88,6 +92,7 @@ namespace isnd.tests ["Smtp:SenderName"] = "Yavsc Test", ["Smtp:SenderEmail"] = "test@example.com" }); + Configuration = builder.Configuration; this.app = builder.ConfigureWebAppServices(); diff --git a/test/yavscTests/appsettings.json b/test/yavscTests/appsettings.json index becfb6ea..28b36a57 100644 --- a/test/yavscTests/appsettings.json +++ b/test/yavscTests/appsettings.json @@ -1,6 +1,6 @@ { "Site": { - "Authority": "localhost", + "Authority": "https://localhost", "Title": "Yavsc dev", "Slogan": "Yavsc : WIP.", "Banner": "/images/yavsc.png",