From 18368ef874280566c85ef4a90b2642d4cfffedc7 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Sat, 15 Feb 2025 19:57:08 +0000 Subject: [PATCH 1/9] require the goodclaim --- src/Api/Program.cs | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/Api/Program.cs b/src/Api/Program.cs index 0243fb86..b997878c 100644 --- a/src/Api/Program.cs +++ b/src/Api/Program.cs @@ -10,6 +10,7 @@ copies or substantial portions of the Software. */ +using IdentityModel; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.AspNetCore.Mvc; @@ -27,9 +28,11 @@ internal class Program var builder = WebApplication.CreateBuilder(args); var services = builder.Services; + builder.Services.AddDistributedMemoryCache(); // accepts any access token issued by identity server - // adds an authorization policy for scope 'api1' + // adds an authorization policy for scope 'scope1' + services .AddAuthorization(options => { @@ -37,7 +40,7 @@ internal class Program { policy .RequireAuthenticatedUser() - .RequireClaim("scope", "scope2"); + .RequireClaim(JwtClaimTypes.Scope, new string [] {"scope2"}); }); }) .AddCors(options => @@ -50,10 +53,10 @@ internal class Program .AllowAnyMethod(); }); }) - .AddControllersWithViews(); + .AddControllers(); // accepts any access token issued by identity server - var authenticationBuilder = services.AddAuthentication() + var authenticationBuilder = services.AddAuthentication("Bearer") .AddJwtBearer("Bearer", options => { options.IncludeErrorDetails = true; @@ -68,7 +71,7 @@ internal class Program services.AddSingleton(); services.AddTransient(); services.AddIdentityApiEndpoints(); - builder.Services.AddSession(); + services.AddSession(); services.AddTransient() .AddTransient() @@ -90,8 +93,12 @@ internal class Program endpoints.MapDefaultControllerRoute() .RequireAuthorization(); }); - app.MapIdentityApi().RequireAuthorization("ApiScope"); - app.UseSession(); + app.MapIdentityApi().RequireAuthorization("ApiScope"); + + app.MapGet("/identity", (HttpContext context) => + new JsonResult(context?.User?.Claims.Select(c => new { c.Type, c.Value })) + ).RequireAuthorization("ApiScope"); + app.UseSession(); await app.RunAsync(); }; From 7612ce1e8babf8baa03096e8613827c8cdc7ec57 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Sat, 15 Feb 2025 20:06:07 +0000 Subject: [PATCH 2/9] custom ProfileService --- src/Yavsc.Abstract/Constants.cs | 2 ++ src/Yavsc.Server/Services/ProfileService.cs | 10 ++++++---- src/Yavsc/Extensions/HostingExtensions.cs | 2 +- src/sampleWebAsWebApiClient/Startup.cs | 13 +++++++------ 4 files changed, 16 insertions(+), 11 deletions(-) diff --git a/src/Yavsc.Abstract/Constants.cs b/src/Yavsc.Abstract/Constants.cs index c84eabaf..b6c7bf2e 100644 --- a/src/Yavsc.Abstract/Constants.cs +++ b/src/Yavsc.Abstract/Constants.cs @@ -54,5 +54,7 @@ namespace Yavsc public const string LivePath = "/live/cast"; public const string StreamingPath = "/api/stream/put"; + + public const string RoleClaimName = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"; } } diff --git a/src/Yavsc.Server/Services/ProfileService.cs b/src/Yavsc.Server/Services/ProfileService.cs index b7705219..fb961a68 100644 --- a/src/Yavsc.Server/Services/ProfileService.cs +++ b/src/Yavsc.Server/Services/ProfileService.cs @@ -30,9 +30,11 @@ namespace Yavsc.Services foreach (var scope in context.RequestedResources.ParsedScopes) { - claims.Add(new Claim(JwtClaimTypes.Scope, scope.ParsedName)); - claimAdds.Add(scope.ParsedName); - // TODO scope has a ParsedParameter + if (context.Client.AllowedScopes.Contains(scope.ParsedName)) + { + claims.Add(new Claim(JwtClaimTypes.Scope, scope.ParsedName)); + claimAdds.Add(scope.ParsedName); + } } if (claimAdds.Contains(JwtClaimTypes.Profile)) @@ -54,7 +56,7 @@ namespace Yavsc.Services var roles = await this._userManager.GetRolesAsync(user); if (roles.Count()>0) { - claims.Add(new Claim("http://schemas.microsoft.com/ws/2008/06/identity/claims/role",String.Join(" ",roles))); + claims.AddRange(roles.Select(r => new Claim(Constants.RoleClaimName, r))); } } return claims; diff --git a/src/Yavsc/Extensions/HostingExtensions.cs b/src/Yavsc/Extensions/HostingExtensions.cs index 67fc960a..1158b8d2 100644 --- a/src/Yavsc/Extensions/HostingExtensions.cs +++ b/src/Yavsc/Extensions/HostingExtensions.cs @@ -146,7 +146,7 @@ public static class HostingExtensions AddIdentityDBAndStores(builder).AddDefaultTokenProviders();; - AddIdentityServer(builder); + AddIdentityServer(builder).AddProfileService(); //services.AddScoped(); services.AddSession(); diff --git a/src/sampleWebAsWebApiClient/Startup.cs b/src/sampleWebAsWebApiClient/Startup.cs index 9abcab39..deb2a39c 100644 --- a/src/sampleWebAsWebApiClient/Startup.cs +++ b/src/sampleWebAsWebApiClient/Startup.cs @@ -1,3 +1,4 @@ +using IdentityModel; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; @@ -5,6 +6,7 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Hosting; using Microsoft.IdentityModel.Tokens; using System.IdentityModel.Tokens.Jwt; +using Yavsc; public class Startup { @@ -34,12 +36,11 @@ public class Startup options.GetClaimsFromUserInfoEndpoint = true; options.SaveTokens = true; options.ClaimActions.MapUniqueJsonKey( - "http://schemas.microsoft.com/ws/2008/06/identity/claims/role", - "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"); - options.ClaimActions.MapUniqueJsonKey("role", - "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"); - options.ClaimActions.MapUniqueJsonKey("roles", - "http://schemas.microsoft.com/ws/2008/06/identity/claims/role"); + Constants.RoleClaimName, + Constants.RoleClaimName); + options.ClaimActions.MapUniqueJsonKey( + JwtClaimTypes.Scope, + JwtClaimTypes.Scope); options.TokenValidationParameters = new TokenValidationParameters { NameClaimType = "name", From 5cc72cd846f2f695381d91f63aa209dd45bcaada Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Sat, 15 Feb 2025 20:10:01 +0000 Subject: [PATCH 3/9] no usage of DefaultProfileService --- src/Yavsc.Server/Config.cs | 4 ++-- src/Yavsc.Server/Services/ProfileService.cs | 11 ++++++----- 2 files changed, 8 insertions(+), 7 deletions(-) diff --git a/src/Yavsc.Server/Config.cs b/src/Yavsc.Server/Config.cs index 9b7091c0..a479c4cc 100644 --- a/src/Yavsc.Server/Config.cs +++ b/src/Yavsc.Server/Config.cs @@ -47,8 +47,8 @@ public static class Config public static IEnumerable ApiScopes => new ApiScope[] { - new ApiScope("scope1"), - new ApiScope("scope2"), + new ApiScope("scope1",new string[] {"scope1"}), + new ApiScope("scope2",new string[] {"scope2"}), }; public static IEnumerable Clients => diff --git a/src/Yavsc.Server/Services/ProfileService.cs b/src/Yavsc.Server/Services/ProfileService.cs index fb961a68..3239672a 100644 --- a/src/Yavsc.Server/Services/ProfileService.cs +++ b/src/Yavsc.Server/Services/ProfileService.cs @@ -9,16 +9,17 @@ using Yavsc.Models; namespace Yavsc.Services { - public class ProfileService : DefaultProfileService, IProfileService + public class ProfileService : IProfileService { private readonly UserManager _userManager; public ProfileService( - UserManager userManager, ILogger logger) : base(logger) + UserManager userManager, + ILogger logger) { _userManager = userManager; } - public async Task> GetClaimsFromUserAsync( + private async Task> GetClaimsFromUserAsync( ProfileDataRequestContext context, ApplicationUser user) { @@ -62,7 +63,7 @@ namespace Yavsc.Services return claims; } - override public async Task GetProfileDataAsync(ProfileDataRequestContext context) + public async Task GetProfileDataAsync(ProfileDataRequestContext context) { var subjectId = GetSubjectId(context.Subject); if (subjectId==null) return; @@ -71,7 +72,7 @@ namespace Yavsc.Services context.IssuedClaims = await GetClaimsFromUserAsync(context, user); } - override public async Task IsActiveAsync(IsActiveContext context) + public async Task IsActiveAsync(IsActiveContext context) { string? subjectId = GetSubjectId(context.Subject); if (subjectId == null) From 088634129ecc34717fa83b5e6c073ed33a4ef7f0 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Sun, 16 Feb 2025 17:28:38 +0000 Subject: [PATCH 4/9] ya cleanup --- .gitlab-ci.yml | 67 ---------------- .nuget/NuGet.Config | 11 --- .nuget/packages.config | 4 - .travis.yml | 22 ------ global.json | 7 +- src/Api/Program.cs | 12 +-- src/Api/Properties/launchSettings.json | 30 ++++++++ src/Yavsc/Extensions/HostingExtensions.cs | 16 ++-- src/Yavsc/Properties/launchSettings.json | 18 ++--- src/Yavsc/ScaffoldingReadMe.txt | 3 - src/Yavsc/Views/Shared/Error.cshtml | 11 --- src/Yavsc/package.json | 14 ---- .../Controllers/HomeController.cs | 2 +- src/sampleWebAsWebApiClient/Program.cs | 69 +++++++++++++---- src/sampleWebAsWebApiClient/Startup.cs | 76 ------------------- yavsc.code-workspace | 38 ---------- yavsc.mdw | 6 -- 17 files changed, 106 insertions(+), 300 deletions(-) delete mode 100644 .gitlab-ci.yml delete mode 100644 .nuget/NuGet.Config delete mode 100644 .nuget/packages.config delete mode 100644 .travis.yml create mode 100644 src/Api/Properties/launchSettings.json delete mode 100644 src/Yavsc/ScaffoldingReadMe.txt delete mode 100644 src/Yavsc/package.json delete mode 100644 src/sampleWebAsWebApiClient/Startup.cs delete mode 100644 yavsc.code-workspace delete mode 100644 yavsc.mdw diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml deleted file mode 100644 index 71badf6b..00000000 --- a/.gitlab-ci.yml +++ /dev/null @@ -1,67 +0,0 @@ -# Please find the full example project here: -# https://gitlab.com/tobiaskoch/gitlab-ci-example-mono - -# see https://hub.docker.com/_/mono/ -image: mono:4.6.2.7 - -stages: - - build - - test - - deploy - -before_script: - - . /opt/mono-4.6/mono-env - - export GIT_SSL_NO_VERIFY=true - - curl --insecure -sSL https://lua.pschneider.fr/files/Paul/pub/dnx-install.sh | bash - - DNX_USER_HOME=`pwd -P`/dnx . ./dnx/dnvm/dnvm.sh - - cd src/OAuth.AspNet.Token && dnu restore --ignore-failed-sources - - cd ../OAuth.AspNet.AuthServer && dnu restore --ignore-failed-sources - - cd ../Yavsc.Abstract && dnu restore --ignore-failed-sources - - cd ../Yavsc.Server && dnu restore --ignore-failed-sources - - cd ../Yavsc && dnu restore --ignore-failed-sources - - cd ../cli && dnu restore --ignore-failed-sources - - cd ../../test/yavscTests && dnu restore --ignore-failed-sources - - cd ../.. - -after_script: - -debug: - stage: build - artifacts: - paths: - - test/yavscTests/bin - script: - - cd test/yavscTests - - dnu build - -non_reg: - stage: test - artifacts: - paths: - - test/yavscTests/test-results.xml - when: always - script: - - cd test/yavscTests - - cp $yavsc_client_secret_json yavsc-client-secret.json - - ASPNET_ENV=Development dnx test -trait ategory=non_reg -maxthreads 1 -xml test-results.xml - -release: - stage: deploy - only: - - vnext - artifacts: - paths: - - binaries/Debug - script: - - make packages - -deploy_staging: - stage: deploy - script: - - echo "Deploy to staging server" - - make strip_yavscd - - make packages - - isn push -s $ISNSOURCE -k $NUGETSOURCEAPIKEY src/Yavsc.Abstract/bin/*/*.nupkg - environment: - name: staging - url: https://yavscpre.pschneider.fr diff --git a/.nuget/NuGet.Config b/.nuget/NuGet.Config deleted file mode 100644 index 3082130d..00000000 --- a/.nuget/NuGet.Config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - diff --git a/.nuget/packages.config b/.nuget/packages.config deleted file mode 100644 index eaeeed58..00000000 --- a/.nuget/packages.config +++ /dev/null @@ -1,4 +0,0 @@ - - - - \ No newline at end of file diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 2a523d6b..00000000 --- a/.travis.yml +++ /dev/null @@ -1,22 +0,0 @@ -language: csharp -os: linux -mono: -- beta -sudo: false -install: -- curl --insecure -sSL https://lua.pschneider.fr/files/Paul/pub/dnx-install.sh | bash -- DNX_USER_HOME=`pwd -P`/dnx . ./dnx/dnvm/dnvm.sh -- cd src/OAuth.AspNet.Token && dnu restore --ignore-failed-sources -- cd ../OAuth.AspNet.AuthServer && dnu restore --ignore-failed-sources -- cd ../Yavsc.Abstract && dnu restore --ignore-failed-sources -- cd ../Yavsc.Server && dnu restore --ignore-failed-sources -- cd ../Yavsc && dnu restore --ignore-failed-sources -- cd ../test -- make restore -- make -- cd ../.. -- make - -script: -- "dnu build" - diff --git a/global.json b/global.json index f2fb072c..030b02f6 100644 --- a/global.json +++ b/global.json @@ -1,11 +1,6 @@ { - "projects": [ - "src", - "test" - ], "sdk": { "runtime": "dotnet", "version": "8.0.405" - }, - "packages": "packages" + } } diff --git a/src/Api/Program.cs b/src/Api/Program.cs index b997878c..a638add4 100644 --- a/src/Api/Program.cs +++ b/src/Api/Program.cs @@ -87,17 +87,19 @@ internal class Program app .UseRouting() .UseAuthentication() - .UseAuthorization().UseCors("default") + .UseAuthorization() + .UseCors("default") .UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute() .RequireAuthorization(); }); - app.MapIdentityApi().RequireAuthorization("ApiScope"); + app.MapIdentityApi().RequireAuthorization("ApiScope"); - app.MapGet("/identity", (HttpContext context) => - new JsonResult(context?.User?.Claims.Select(c => new { c.Type, c.Value })) - ).RequireAuthorization("ApiScope"); + app.MapGet("/identity", (HttpContext context) => + new JsonResult(context?.User?.Claims.Select(c => new { c.Type, c.Value })) + ); + app.UseSession(); await app.RunAsync(); }; diff --git a/src/Api/Properties/launchSettings.json b/src/Api/Properties/launchSettings.json new file mode 100644 index 00000000..c419c2c8 --- /dev/null +++ b/src/Api/Properties/launchSettings.json @@ -0,0 +1,30 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "https://localhost:5001", + "sslPort": 6001 + } + }, + "profiles": { + + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "applicationUrl": "https://localhost:6001;", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/src/Yavsc/Extensions/HostingExtensions.cs b/src/Yavsc/Extensions/HostingExtensions.cs index 1158b8d2..251d9e3f 100644 --- a/src/Yavsc/Extensions/HostingExtensions.cs +++ b/src/Yavsc/Extensions/HostingExtensions.cs @@ -1,3 +1,4 @@ +using System.Diagnostics; using System.Globalization; using System.Security.Cryptography.X509Certificates; using Google.Apis.Util.Store; @@ -144,11 +145,9 @@ public static class HostingExtensions o.EnableDetailedErrors = true; }); - AddIdentityDBAndStores(builder).AddDefaultTokenProviders();; - - AddIdentityServer(builder).AddProfileService(); - //services.AddScoped(); - + AddIdentityDBAndStores(builder).AddDefaultTokenProviders(); + AddIdentityServer(builder); + services.AddSession(); // TODO .AddServerSideSessionStore() @@ -329,14 +328,17 @@ public static class HostingExtensions .AddInMemoryClients(Config.Clients) .AddInMemoryApiScopes(Config.ApiScopes) .AddAspNetIdentity() - .AddJwtBearerClientAuthentication(); + // .AddProfileService() + .AddJwtBearerClientAuthentication() + ; if (builder.Environment.IsDevelopment()) { identityServerBuilder.AddDeveloperSigningCredential(); } else { - var key = builder.Configuration["YOUR-KEY-NAME"]; + var key = builder.Configuration["YavscSigningCert"]; + Debug.Assert(key != null); var pfxBytes = Convert.FromBase64String(key); var cert = new X509Certificate2(pfxBytes, (string)null, X509KeyStorageFlags.MachineKeySet); identityServerBuilder.AddSigningCredential(cert); diff --git a/src/Yavsc/Properties/launchSettings.json b/src/Yavsc/Properties/launchSettings.json index c7aa64d5..a78ff8ae 100644 --- a/src/Yavsc/Properties/launchSettings.json +++ b/src/Yavsc/Properties/launchSettings.json @@ -1,27 +1,19 @@ -{ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", "iisSettings": { "windowsAuthentication": false, "anonymousAuthentication": true, "iisExpress": { - "applicationUrl": "http://localhost:30089", - "sslPort": 44391 + "applicationUrl": "https://localhost:5001", + "sslPort": 5001 } }, "profiles": { - "http": { - "commandName": "Project", - "dotnetRunMessages": true, - "launchBrowser": true, - "applicationUrl": "http://localhost:5172", - "environmentVariables": { - "ASPNETCORE_ENVIRONMENT": "Development" - } - }, "https": { "commandName": "Project", "dotnetRunMessages": true, "launchBrowser": true, - "applicationUrl": "https://localhost:7062;http://localhost:5172", + "applicationUrl": "https://localhost:5001;", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" } diff --git a/src/Yavsc/ScaffoldingReadMe.txt b/src/Yavsc/ScaffoldingReadMe.txt deleted file mode 100644 index 6e6208dc..00000000 --- a/src/Yavsc/ScaffoldingReadMe.txt +++ /dev/null @@ -1,3 +0,0 @@ -Support for ASP.NET Core Identity was added to your project. - -For setup and configuration information, see https://go.microsoft.com/fwlink/?linkid=2116645. diff --git a/src/Yavsc/Views/Shared/Error.cshtml b/src/Yavsc/Views/Shared/Error.cshtml index d5a8de36..3bfd9196 100644 --- a/src/Yavsc/Views/Shared/Error.cshtml +++ b/src/Yavsc/Views/Shared/Error.cshtml @@ -12,14 +12,3 @@ Request ID: @Model.RequestId

} - -

Development Mode

-

- Swapping to Development environment will display more detailed information about the error that occurred. -

-

- The Development environment shouldn't be enabled for deployed applications. - It can result in displaying sensitive information from exceptions to end users. - For local debugging, enable the Development environment by setting the ASPNETCORE_ENVIRONMENT environment variable to Development - and restarting the app. -

diff --git a/src/Yavsc/package.json b/src/Yavsc/package.json deleted file mode 100644 index 545fc0a6..00000000 --- a/src/Yavsc/package.json +++ /dev/null @@ -1,14 +0,0 @@ -{ - "name": "yavsc", - "version": "1.0.7", - "description": "Yet Another Very Small Company", - "repository": { - "type": "Git", - "url": "https://github.com/pazof/yavsc" - }, - "license": "GPL-3.0", - "devDependencies": {}, - "dependencies": { - "paypal-permissions-sdk": "^1.0.10" - } -} diff --git a/src/sampleWebAsWebApiClient/Controllers/HomeController.cs b/src/sampleWebAsWebApiClient/Controllers/HomeController.cs index 46ea870b..70d64c58 100755 --- a/src/sampleWebAsWebApiClient/Controllers/HomeController.cs +++ b/src/sampleWebAsWebApiClient/Controllers/HomeController.cs @@ -71,7 +71,7 @@ namespace testOauthClient.Controllers var accessToken = await HttpContext.GetTokenAsync("access_token"); var client = new HttpClient(new HttpClientHandler(){ AllowAutoRedirect=false }); client.DefaultRequestHeaders.Add("Accept", "application/json"); - client.SetBearerToken(accessToken); + client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); var content = await client.GetAsync("https://localhost:6001/identity"); content.EnsureSuccessStatusCode(); var json = await content.Content.ReadAsStreamAsync(); diff --git a/src/sampleWebAsWebApiClient/Program.cs b/src/sampleWebAsWebApiClient/Program.cs index 966579dd..2aab156a 100644 --- a/src/sampleWebAsWebApiClient/Program.cs +++ b/src/sampleWebAsWebApiClient/Program.cs @@ -1,19 +1,56 @@ -using Microsoft.AspNetCore.Authentication.OAuth; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Identity; -using Microsoft.AspNetCore.Mvc; +/* + Copyright (c) 2024 HigginsSoft, Alexander Higgins - https://github.com/alexhiggins732/ - public class Program + Copyright (c) 2018, Brock Allen & Dominick Baier. All rights reserved. + + Licensed under the Apache License, Version 2.0. See LICENSE in the project root for license information. + Source code and license this software can be found + + The above copyright notice and this permission notice shall be included in all + copies or substantial portions of the Software. +*/ + +using System.IdentityModel.Tokens.Jwt; + +JwtSecurityTokenHandler.DefaultMapInboundClaims = false; + + +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddControllersWithViews(); +builder.Services + .AddAuthentication(options => { - public static void Main(string[] args) - { - CreateHostBuilder(args).Build().Run(); - } + options.DefaultScheme = "Cookies"; + options.DefaultChallengeScheme = "oidc"; + }) + .AddCookie("Cookies") + .AddOpenIdConnect("oidc", options => + { + options.Authority = "https://localhost:5001"; - public static IHostBuilder CreateHostBuilder(string[] args) => - Host.CreateDefaultBuilder(args) - .ConfigureWebHostDefaults(webBuilder => - { - webBuilder.UseStartup(); - }); - } + options.ClientId = "mvc"; + options.ClientSecret = "49C1A7E1-0C79-4A89-A3D6-A37998FB86B0"; + options.ResponseType = "code"; + + options.Scope.Add("scope2"); + + options.SaveTokens = true; + }); + + +using (var app = builder.Build()) +{ + if (app.Environment.IsDevelopment()) + app.UseDeveloperExceptionPage(); + else + app.UseExceptionHandler("/Home/Error"); + + app.UseStaticFiles(); + app.UseRouting(); + app.UseAuthentication(); + app.UseAuthorization(); + app.MapDefaultControllerRoute().RequireAuthorization(); + + await app.RunAsync(); +} diff --git a/src/sampleWebAsWebApiClient/Startup.cs b/src/sampleWebAsWebApiClient/Startup.cs deleted file mode 100644 index deb2a39c..00000000 --- a/src/sampleWebAsWebApiClient/Startup.cs +++ /dev/null @@ -1,76 +0,0 @@ -using IdentityModel; -using Microsoft.AspNetCore.Authentication; -using Microsoft.AspNetCore.Builder; -using Microsoft.AspNetCore.Hosting; -using Microsoft.Extensions.DependencyInjection; -using Microsoft.Extensions.Hosting; -using Microsoft.IdentityModel.Tokens; -using System.IdentityModel.Tokens.Jwt; -using Yavsc; - -public class Startup -{ - public void ConfigureServices(IServiceCollection services) - { - - services.AddControllersWithViews(); - services - .AddAuthentication(options => - { - options.DefaultScheme = "Cookies"; - options.DefaultChallengeScheme = "oidc"; - }) - .AddCookie("Cookies") - .AddOpenIdConnect("oidc", options => - { - options.Authority = "https://localhost:5001"; - - options.ClientId = "mvc"; - options.ClientSecret = "49C1A7E1-0C79-4A89-A3D6-A37998FB86B0"; - options.ResponseType = "code"; - - options.Scope.Add("scope2"); - - options.SaveTokens = true; - - options.GetClaimsFromUserInfoEndpoint = true; - options.SaveTokens = true; - options.ClaimActions.MapUniqueJsonKey( - Constants.RoleClaimName, - Constants.RoleClaimName); - options.ClaimActions.MapUniqueJsonKey( - JwtClaimTypes.Scope, - JwtClaimTypes.Scope); - options.TokenValidationParameters = new TokenValidationParameters - { - NameClaimType = "name", - RoleClaimType = "http://schemas.microsoft.com/ws/2008/06/identity/claims/role" - }; - }); - - } - - public void Configure(IApplicationBuilder app, IWebHostEnvironment env) - { - if (env.IsDevelopment()) - { - app.UseDeveloperExceptionPage(); - } - else - { - app.UseExceptionHandler("/Home/Error"); - } - - app.UseStaticFiles(); - - app.UseRouting(); - app.UseAuthentication(); - app.UseAuthorization(); - - app.UseEndpoints(endpoints => - { - endpoints.MapDefaultControllerRoute() - .RequireAuthorization(); - }); - } -} diff --git a/yavsc.code-workspace b/yavsc.code-workspace deleted file mode 100644 index 29367081..00000000 --- a/yavsc.code-workspace +++ /dev/null @@ -1,38 +0,0 @@ -{ - "folders": [ - { - "path": ".vscode" - }, - { - "path": "." - }, - { - "path": "src/test" - }, - { - "path": "src/Yavsc" - }, - { - "path": "src/cli" - }, - { - "path": "src/GoogleCode" - }, - { - "path": "src/OAuth.AspNet.AuthServer" - }, - { - "path": "src/OAuth.AspNet.Token" - }, - { - "path": "src/Yavsc.Abstract" - }, - { - "path": "src/Yavsc.Server" - } - ], - "settings": { - "mocha.enabled": true, - "git.ignoreLimitWarning": true - } -} \ No newline at end of file diff --git a/yavsc.mdw b/yavsc.mdw deleted file mode 100644 index 45b134a7..00000000 --- a/yavsc.mdw +++ /dev/null @@ -1,6 +0,0 @@ - - - ZicMoove.sln - yagui/yagui.sln - - \ No newline at end of file From 7f1c0bc1d89e161c204ca22ce8dad13dec87f45c Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Sun, 16 Feb 2025 18:42:51 +0000 Subject: [PATCH 5/9] don't launch browser on API services --- src/Api/Properties/launchSettings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/Api/Properties/launchSettings.json b/src/Api/Properties/launchSettings.json index c419c2c8..e27c888f 100644 --- a/src/Api/Properties/launchSettings.json +++ b/src/Api/Properties/launchSettings.json @@ -13,7 +13,7 @@ "https": { "commandName": "Project", "dotnetRunMessages": true, - "launchBrowser": true, + "launchBrowser": false, "applicationUrl": "https://localhost:6001;", "environmentVariables": { "ASPNETCORE_ENVIRONMENT": "Development" From 5961e436d545bef978ffc8a7e2f6fbc1d2dfe119 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Sun, 16 Feb 2025 18:43:18 +0000 Subject: [PATCH 6/9] simply render the test response --- src/sampleWebAsWebApiClient/Controllers/HomeController.cs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/sampleWebAsWebApiClient/Controllers/HomeController.cs b/src/sampleWebAsWebApiClient/Controllers/HomeController.cs index 70d64c58..f92fa675 100755 --- a/src/sampleWebAsWebApiClient/Controllers/HomeController.cs +++ b/src/sampleWebAsWebApiClient/Controllers/HomeController.cs @@ -74,9 +74,8 @@ namespace testOauthClient.Controllers client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", accessToken); var content = await client.GetAsync("https://localhost:6001/identity"); content.EnsureSuccessStatusCode(); - var json = await content.Content.ReadAsStreamAsync(); - var obj = JsonSerializer.Deserialize(json); - return View("UserInfo", obj.ToString()); + var json = await content.Content.ReadAsStringAsync(); + return View("UserInfo", json); } From 968859babedbe0417d7d8e28e5cbde7ca875c907 Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Sun, 16 Feb 2025 18:43:32 +0000 Subject: [PATCH 7/9] references cleanup --- src/Yavsc.Abstract/Yavsc.Abstract.csproj | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/Yavsc.Abstract/Yavsc.Abstract.csproj b/src/Yavsc.Abstract/Yavsc.Abstract.csproj index 4483fe35..6d0c7e5f 100644 --- a/src/Yavsc.Abstract/Yavsc.Abstract.csproj +++ b/src/Yavsc.Abstract/Yavsc.Abstract.csproj @@ -9,8 +9,5 @@ - - - From 84e58bb9ebfebb9957bafebfab8a0f8193205fdd Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Sun, 16 Feb 2025 22:40:51 +0000 Subject: [PATCH 8/9] Api protected --- src/Api/Api.csproj | 3 +- .../accounting/AccountController.cs | 157 +++--------------- src/Api/Program.cs | 35 ++-- src/Yavsc.Server/Config.cs | 2 +- src/Yavsc/Extensions/HostingExtensions.cs | 65 ++++---- src/sampleWebAsWebApiClient/Program.cs | 2 + 6 files changed, 82 insertions(+), 182 deletions(-) diff --git a/src/Api/Api.csproj b/src/Api/Api.csproj index b1e26b9c..6e024e9b 100644 --- a/src/Api/Api.csproj +++ b/src/Api/Api.csproj @@ -1,8 +1,9 @@ - + net8.0 enable enable + 1c73094f-959f-4211-b1a1-6a69b236c283 diff --git a/src/Api/Controllers/accounting/AccountController.cs b/src/Api/Controllers/accounting/AccountController.cs index 6137c544..5ae21995 100644 --- a/src/Api/Controllers/accounting/AccountController.cs +++ b/src/Api/Controllers/accounting/AccountController.cs @@ -17,165 +17,56 @@ namespace Yavsc.WebApi.Controllers [Authorize("ApiScope")] public class ApiAccountController : Controller { - private UserManager _userManager; - private readonly SignInManager _signInManager; readonly ApplicationDbContext _dbContext; private readonly ILogger _logger; - public ApiAccountController(UserManager userManager, - SignInManager signInManager, - RoleManager roleManager, + public ApiAccountController( ILoggerFactory loggerFactory, ApplicationDbContext dbContext) { - UserManager = userManager; - this.roleManager = roleManager; - _signInManager = signInManager; _logger = loggerFactory.CreateLogger(nameof(ApiAccountController)); _dbContext = dbContext; } - public UserManager UserManager - { - get - { - return _userManager; - } - private set - { - _userManager = value; - } - } - private readonly RoleManager roleManager; - - // POST api/Account/ChangePassword - - public async Task ChangePassword(ChangePasswordBindingModel model) - { - if (!ModelState.IsValid) - { - return new BadRequestObjectResult(ModelState); - } - var user = await _userManager.FindByIdAsync(User.GetUserId()); - if (user == null || !(await _userManager.IsEmailConfirmedAsync(user))) { - IdentityResult result = await UserManager.ChangePasswordAsync(user, model.OldPassword, - model.NewPassword); - - if (!result.Succeeded) - { - AddErrors("NewPassword",result); - return new BadRequestObjectResult(ModelState); - } - } - return Ok(); - } - - // POST api/Account/SetPassword - - public async Task SetPassword(SetPasswordBindingModel model) - { - if (!ModelState.IsValid) - { - return new BadRequestObjectResult(ModelState); - } - var user = await _userManager.FindByIdAsync(User.GetUserId()); - if (user == null || !(await _userManager.IsEmailConfirmedAsync(user))) { - IdentityResult result = await UserManager.AddPasswordAsync(user, model.NewPassword); - if (!result.Succeeded) - { - AddErrors ("NewPassword",result); - return new BadRequestObjectResult(ModelState); - } - } - return Ok(); - } - - // POST api/Account/Register - [AllowAnonymous] - public async Task Register(RegisterModel model) - { - if (!ModelState.IsValid) - { - return new BadRequestObjectResult(ModelState); - } - - var user = new ApplicationUser { UserName = model.Email, Email = model.Email }; - - IdentityResult result = await UserManager.CreateAsync(user, model.Password); - - if (!result.Succeeded) - { - AddErrors ("Register",result); - return new BadRequestObjectResult(ModelState); - } - await _signInManager.SignInAsync(user, isPersistent: false); - return Ok(); - } - private void AddErrors(string key, IdentityResult result) - { - foreach (var error in result.Errors) - { - ModelState.AddModelError(key, error.Description); - } - } - protected override void Dispose(bool disposing) - { - if (disposing) - { - UserManager.Dispose(); - } - - base.Dispose(disposing); - } [HttpGet("me")] public async Task Me() { - if (User==null) - return new BadRequestObjectResult( - new { error = "user not found" }); + if (User == null) + return new BadRequestObjectResult( + new { error = "user not found" }); var uid = User.GetUserId(); - - var userData = await _dbContext.Users - .Include(u=>u.PostalAddress) - .Include(u=>u.AccountBalance) - .FirstAsync(u=>u.Id == uid); - var user = new Yavsc.Models.Auth.Me(userData.Id, userData.UserName, userData.Email, - userData.Avatar , - userData.PostalAddress, userData.DedicatedGoogleCalendar ); + var userData = await GetUserData(uid); - var userRoles = _dbContext.UserRoles.Where(u=>u.UserId == uid).Select(r => r.RoleId).ToArray(); + var user = new Yavsc.Models.Auth.Me(userData.Id, userData.UserName, userData.Email, + userData.Avatar, + userData.PostalAddress, userData.DedicatedGoogleCalendar); - IdentityRole [] roles = _dbContext.Roles.Where(r=>userRoles.Contains(r.Id)).ToArray(); - - user.Roles = roles.Select(r=>r.Name).ToArray(); + var userRoles = _dbContext.UserRoles.Where(u => u.UserId == uid).Select(r => r.RoleId).ToArray(); + + IdentityRole[] roles = _dbContext.Roles.Where(r => userRoles.Contains(r.Id)).ToArray(); + + user.Roles = roles.Select(r => r.Name).ToArray(); return Ok(user); } + private async Task GetUserData(string uid) + { + return await _dbContext.Users + .Include(u => u.PostalAddress) + .Include(u => u.AccountBalance) + .FirstAsync(u => u.Id == uid); + } + [HttpGet("myhost")] public IActionResult MyHost () { return Ok(new { host = Request.ForHost() }); } - /// - /// Actually only updates the user's name. - /// - /// MyUpdate containing the new user name - /// Ok when all is ok. - [HttpPut("me")] - public async Task UpdateMe(UserInfo me) - { - if (!ModelState.IsValid) return new BadRequestObjectResult( - new { error = "Specify some valid user update request." }); - var user = await _userManager.FindByIdAsync(User.GetUserId()); - var result = await _userManager.SetUserNameAsync(user, me.UserName); - if (result.Succeeded) - return Ok(); - else return new BadRequestObjectResult(result); - } + /// /// Updates the avatar /// @@ -184,11 +75,11 @@ namespace Yavsc.WebApi.Controllers public async Task SetAvatar() { var root = User.InitPostToFileSystem(null); - var user = await _userManager.FindByIdAsync(User.GetUserId()); + var user = await GetUserData(User.GetUserId()); if (Request.Form.Files.Count!=1) return new BadRequestResult(); var info = user.ReceiveAvatar(Request.Form.Files[0]); - await _userManager.UpdateAsync(user); + await _dbContext.SaveChangesAsync(); return Ok(info); } diff --git a/src/Api/Program.cs b/src/Api/Program.cs index a638add4..dd8a4606 100644 --- a/src/Api/Program.cs +++ b/src/Api/Program.cs @@ -28,7 +28,7 @@ internal class Program var builder = WebApplication.CreateBuilder(args); var services = builder.Services; - builder.Services.AddDistributedMemoryCache(); + // builder.Services.AddDistributedMemoryCache(); // accepts any access token issued by identity server // adds an authorization policy for scope 'scope1' @@ -63,22 +63,21 @@ internal class Program options.Authority = "https://localhost:5001"; options.TokenValidationParameters = new() { ValidateAudience = false }; - }); - services.AddDbContext(options => - options.UseNpgsql(builder.Configuration.GetConnectionString("Default"))); - services.AddScoped>(); + }); + + services.AddDbContext(options => + options.UseNpgsql(builder.Configuration.GetConnectionString("Default"))); + + services.AddTransient() + .AddTransient() + .AddTransient(); + /* services.AddSingleton(); services.AddSingleton(); services.AddTransient(); services.AddIdentityApiEndpoints(); services.AddSession(); - - services.AddTransient() - .AddTransient() - .AddTransient() - .AddTransient, UserStore>() - .AddTransient(); - +*/ using (var app = builder.Build()) { if (app.Environment.IsDevelopment()) @@ -89,18 +88,20 @@ internal class Program .UseAuthentication() .UseAuthorization() .UseCors("default") - .UseEndpoints(endpoints => + /* .UseEndpoints(endpoints => { endpoints.MapDefaultControllerRoute() .RequireAuthorization(); - }); - app.MapIdentityApi().RequireAuthorization("ApiScope"); - + })*/ + + ; + // app.MapIdentityApi().RequireAuthorization("ApiScope"); + app.MapDefaultControllerRoute(); app.MapGet("/identity", (HttpContext context) => new JsonResult(context?.User?.Claims.Select(c => new { c.Type, c.Value })) ); - app.UseSession(); + // app.UseSession(); await app.RunAsync(); }; diff --git a/src/Yavsc.Server/Config.cs b/src/Yavsc.Server/Config.cs index a479c4cc..17d12cff 100644 --- a/src/Yavsc.Server/Config.cs +++ b/src/Yavsc.Server/Config.cs @@ -73,12 +73,12 @@ public static class Config ClientSecrets = { new Secret("49C1A7E1-0C79-4A89-A3D6-A37998FB86B0".Sha256()) }, AllowedGrantTypes = GrantTypes.Code, + AlwaysIncludeUserClaimsInIdToken = true, RedirectUris = { "https://localhost:5003/signin-oidc", "http://localhost:5002/signin-oidc" }, PostLogoutRedirectUris = { "https://localhost:5003/signout-callback-oidc" }, - AllowOfflineAccess = true, AllowedScopes = { IdentityServerConstants.StandardScopes.OpenId, diff --git a/src/Yavsc/Extensions/HostingExtensions.cs b/src/Yavsc/Extensions/HostingExtensions.cs index 251d9e3f..d781de86 100644 --- a/src/Yavsc/Extensions/HostingExtensions.cs +++ b/src/Yavsc/Extensions/HostingExtensions.cs @@ -4,6 +4,7 @@ using System.Security.Cryptography.X509Certificates; using Google.Apis.Util.Store; using IdentityServer8; using IdentityServer8.Services; +using IdentityServerHost.Quickstart.UI; using Microsoft.AspNetCore.Authentication; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.DataProtection; @@ -138,28 +139,28 @@ public static class HostingExtensions { IServiceCollection services = LoadConfiguration(builder); - services.AddRazorPages(); + //services.AddRazorPages(); - services.AddSignalR(o => - { - o.EnableDetailedErrors = true; - }); - - AddIdentityDBAndStores(builder).AddDefaultTokenProviders(); - AddIdentityServer(builder); - + services.AddSession(); // TODO .AddServerSideSessionStore() - AddAuthentication(services, builder.Configuration); // Add the system clock service _ = services.AddSingleton(); _ = services.AddSingleton(); _ = services.AddSingleton(); _ = services.AddTransient(); + + AddIdentityDBAndStores(builder).AddDefaultTokenProviders(); + AddIdentityServer(builder); + services.AddSignalR(o => + { + o.EnableDetailedErrors = true; + }); + services.AddMvc(config => { /* var policy = new AuthorizationPolicyBuilder() @@ -207,6 +208,7 @@ public static class HostingExtensions services.AddSingleton(); + AddAuthentication(builder); // accepts any access token issued by identity server return builder.Build(); @@ -296,20 +298,16 @@ public static class HostingExtensions return services; } - private static void AddAuthentication(IServiceCollection services, IConfigurationRoot configurationRoot) + private static void AddAuthentication(WebApplicationBuilder builder) { - string? googleClientId = configurationRoot["Authentication:Google:ClientId"]; + IServiceCollection services=builder.Services; + IConfigurationRoot configurationRoot=builder.Configuration; + string? googleClientId = configurationRoot["Authentication:Google:ClientId"]; string? googleClientSecret = configurationRoot["Authentication:Google:ClientSecret"]; - var authenticationBuilder = services.AddAuthentication() - .AddJwtBearer("Bearer", options => - { - options.IncludeErrorDetails = true; - options.Authority = "https://localhost:5001"; - options.TokenValidationParameters = - new() { ValidateAudience = false }; - }); + var authenticationBuilder = services.AddAuthentication(); + if (googleClientId!=null && googleClientSecret!=null) authenticationBuilder.AddGoogle(options => { options.SignInScheme = IdentityServerConstants.ExternalCookieAuthenticationScheme; @@ -323,13 +321,23 @@ public static class HostingExtensions } private static IIdentityServerBuilder AddIdentityServer(WebApplicationBuilder builder) { - var identityServerBuilder = builder.Services.AddIdentityServer() + builder.Services.AddTransient(); + var identityServerBuilder = builder.Services.AddIdentityServer(options => + { + options.Events.RaiseErrorEvents = true; + options.Events.RaiseInformationEvents = true; + options.Events.RaiseFailureEvents = true; + options.Events.RaiseSuccessEvents = true; + + // see https://IdentityServer8.readthedocs.io/en/latest/topics/resources.html + options.EmitStaticAudienceClaim = true; + }) .AddInMemoryIdentityResources(Config.IdentityResources) .AddInMemoryClients(Config.Clients) .AddInMemoryApiScopes(Config.ApiScopes) + .AddAspNetIdentity() - // .AddProfileService() - .AddJwtBearerClientAuthentication() + .AddProfileService() ; if (builder.Environment.IsDevelopment()) { @@ -381,7 +389,7 @@ public static class HostingExtensions } - public static WebApplication ConfigurePipeline(this WebApplication app) + internal static WebApplication ConfigurePipeline(this WebApplication app) { if (app.Environment.IsDevelopment()) @@ -398,13 +406,10 @@ public static class HostingExtensions app.UseIdentityServer(); app.UseAuthorization(); app.UseCors("default"); - app.MapControllerRoute( - name: "default", - pattern: "{controller=Home}/{action=Index}/{id?}"); - app.MapRazorPages() - .RequireAuthorization(); + app.MapDefaultControllerRoute(); + //pp.MapRazorPages(); app.MapHub("/chatHub"); - app.MapAreaControllerRoute("api", "api", "~/api/{controller}/{action}/{id?}"); + ConfigureWorkflow(); var services = app.Services; ILoggerFactory loggerFactory = services.GetRequiredService(); diff --git a/src/sampleWebAsWebApiClient/Program.cs b/src/sampleWebAsWebApiClient/Program.cs index 2aab156a..31426483 100644 --- a/src/sampleWebAsWebApiClient/Program.cs +++ b/src/sampleWebAsWebApiClient/Program.cs @@ -33,6 +33,8 @@ builder.Services options.ClientSecret = "49C1A7E1-0C79-4A89-A3D6-A37998FB86B0"; options.ResponseType = "code"; + options.Scope.Add("openid"); + options.Scope.Add("profile"); options.Scope.Add("scope2"); options.SaveTokens = true; From 45cc299866fc18decd358bfcc182957d5627832f Mon Sep 17 00:00:00 2001 From: Paul Schneider Date: Mon, 17 Feb 2025 23:56:28 +0000 Subject: [PATCH 9/9] Get User Id from Web API --- .../Blogspot/FileSystemApiController.cs | 2 + .../Controllers/Blogspot/FileSystemStream.cs | 1 + .../Business/ActivityApiController.cs | 2 +- .../Controllers/Business/BillingController.cs | 1 + .../accounting/AccountController.cs | 10 +--- .../Helpers/RequestHelpers.cs | 2 +- src/Api/Helpers/UserHelpers.cs | 17 ++++++ src/Api/Program.cs | 53 ++++++++++--------- .../Validation/ValidRemoteUserDirAttribute.cs | 2 +- .../FileSystem/AbstractFileSystemHelpers.cs | 2 +- .../FileSystem/FsOperationInfo.cs | 2 +- .../FileSystem/UserDirectoryInfo.cs | 2 +- src/Yavsc.Server/Helpers/BillingHelpers.cs | 5 +- src/Yavsc.Server/Helpers/FileSystemHelpers.cs | 5 +- src/Yavsc.Server/Helpers/UserHelpers.cs | 1 - .../ViewModels/LiveCastHandler.cs | 1 + .../Contracting/EstimateController.cs | 1 + .../Contracting/FrontOfficeController.cs | 1 + src/Yavsc/Controllers/FileSystemController.cs | 1 + src/Yavsc/Extensions/HostingExtensions.cs | 2 +- src/Yavsc/Helpers/UserHelpers.cs | 10 ++++ src/Yavsc/Startup.cs | 1 + src/Yavsc/ViewComponents/BillViewComponent.cs | 1 + .../ViewComponents/DirectoryViewComponent.cs | 1 + src/Yavsc/app.config | 11 ---- src/sampleWebAsWebApiClient/Program.cs | 6 ++- 26 files changed, 83 insertions(+), 60 deletions(-) rename src/{Yavsc.Server => Api}/Helpers/RequestHelpers.cs (96%) create mode 100644 src/Api/Helpers/UserHelpers.cs create mode 100644 src/Yavsc/Helpers/UserHelpers.cs delete mode 100644 src/Yavsc/app.config diff --git a/src/Api/Controllers/Blogspot/FileSystemApiController.cs b/src/Api/Controllers/Blogspot/FileSystemApiController.cs index e7b40dfe..2dc63d59 100644 --- a/src/Api/Controllers/Blogspot/FileSystemApiController.cs +++ b/src/Api/Controllers/Blogspot/FileSystemApiController.cs @@ -14,6 +14,8 @@ namespace Yavsc.ApiControllers using Yavsc.Attributes.Validation; using System.IO; using Yavsc.Exceptions; + using Yavsc.Server.Helpers; + using Yavsc.Abstract.Helpers; [Authorize,Route("api/fs")] public partial class FileSystemApiController : Controller diff --git a/src/Api/Controllers/Blogspot/FileSystemStream.cs b/src/Api/Controllers/Blogspot/FileSystemStream.cs index af80fe7d..e6b3c159 100644 --- a/src/Api/Controllers/Blogspot/FileSystemStream.cs +++ b/src/Api/Controllers/Blogspot/FileSystemStream.cs @@ -8,6 +8,7 @@ using Yavsc.Models; using Yavsc.Models.Messaging; using Yavsc.Services; using Microsoft.AspNetCore.SignalR; +using Yavsc.Server.Helpers; namespace Yavsc.ApiControllers { diff --git a/src/Api/Controllers/Business/ActivityApiController.cs b/src/Api/Controllers/Business/ActivityApiController.cs index c661857a..709fab7a 100644 --- a/src/Api/Controllers/Business/ActivityApiController.cs +++ b/src/Api/Controllers/Business/ActivityApiController.cs @@ -6,7 +6,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; using Microsoft.EntityFrameworkCore; -using Yavsc.Helpers; +using Yavsc.Api.Helpers; using Yavsc.Models; using Yavsc.Models.Workflow; diff --git a/src/Api/Controllers/Business/BillingController.cs b/src/Api/Controllers/Business/BillingController.cs index 041359a2..5ab4a332 100644 --- a/src/Api/Controllers/Business/BillingController.cs +++ b/src/Api/Controllers/Business/BillingController.cs @@ -15,6 +15,7 @@ namespace Yavsc.ApiControllers using Microsoft.Extensions.Options; using Microsoft.EntityFrameworkCore; using Yavsc.ViewModels.Auth; + using Yavsc.Server.Helpers; [Route("api/bill"), Authorize] public class BillingController : Controller diff --git a/src/Api/Controllers/accounting/AccountController.cs b/src/Api/Controllers/accounting/AccountController.cs index 5ae21995..c1bb811a 100644 --- a/src/Api/Controllers/accounting/AccountController.cs +++ b/src/Api/Controllers/accounting/AccountController.cs @@ -1,15 +1,11 @@ using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; -using System.Security.Claims; using Microsoft.EntityFrameworkCore; using Yavsc.Models; -using Yavsc.Models.Account; -using Yavsc.ViewModels.Account; -using Yavsc.Helpers; -using Yavsc.Abstract.Identity; -using System.Diagnostics; +using Yavsc.Api.Helpers; +using Yavsc.Server.Helpers; namespace Yavsc.WebApi.Controllers { @@ -27,8 +23,6 @@ namespace Yavsc.WebApi.Controllers _dbContext = dbContext; } - - [HttpGet("me")] public async Task Me() { diff --git a/src/Yavsc.Server/Helpers/RequestHelpers.cs b/src/Api/Helpers/RequestHelpers.cs similarity index 96% rename from src/Yavsc.Server/Helpers/RequestHelpers.cs rename to src/Api/Helpers/RequestHelpers.cs index 96f060c3..2c2fae27 100644 --- a/src/Yavsc.Server/Helpers/RequestHelpers.cs +++ b/src/Api/Helpers/RequestHelpers.cs @@ -8,7 +8,7 @@ using Yavsc.ViewModels; using Yavsc.Models; using System.Linq; -namespace Yavsc.Helpers +namespace Yavsc.Api.Helpers { public static class RequestHelpers { diff --git a/src/Api/Helpers/UserHelpers.cs b/src/Api/Helpers/UserHelpers.cs new file mode 100644 index 00000000..2d480ea1 --- /dev/null +++ b/src/Api/Helpers/UserHelpers.cs @@ -0,0 +1,17 @@ +using System.Security.Claims; +using System.Collections.Generic; +using System.Linq; +using Microsoft.EntityFrameworkCore; +using Yavsc.Models; +using Yavsc.Models.Blog; + +namespace Yavsc.Api.Helpers +{ + public static class UserHelpers + { + public static string GetUserId(this ClaimsPrincipal user) + { + return user.FindFirstValue("http://schemas.xmlsoap.org/ws/2005/05/identity/claims/nameidentifier"); + } + } +} diff --git a/src/Api/Program.cs b/src/Api/Program.cs index dd8a4606..5ef8afde 100644 --- a/src/Api/Program.cs +++ b/src/Api/Program.cs @@ -32,7 +32,7 @@ internal class Program // accepts any access token issued by identity server // adds an authorization policy for scope 'scope1' - + services .AddAuthorization(options => { @@ -40,7 +40,7 @@ internal class Program { policy .RequireAuthenticatedUser() - .RequireClaim(JwtClaimTypes.Scope, new string [] {"scope2"}); + .RequireClaim(JwtClaimTypes.Scope, new string[] { "scope2" }); }); }) .AddCors(options => @@ -63,21 +63,21 @@ internal class Program options.Authority = "https://localhost:5001"; options.TokenValidationParameters = new() { ValidateAudience = false }; - }); - - services.AddDbContext(options => - options.UseNpgsql(builder.Configuration.GetConnectionString("Default"))); - - services.AddTransient() - .AddTransient() - .AddTransient(); - /* - services.AddSingleton(); - services.AddSingleton(); - services.AddTransient(); - services.AddIdentityApiEndpoints(); - services.AddSession(); -*/ + }); + + services.AddDbContext(options => + options.UseNpgsql(builder.Configuration.GetConnectionString("DefaultConnection"))); + + services.AddTransient() + .AddTransient() + .AddTransient(); + /* + services.AddSingleton(); + services.AddSingleton(); + services.AddTransient(); + services.AddIdentityApiEndpoints(); + services.AddSession(); + */ using (var app = builder.Build()) { if (app.Environment.IsDevelopment()) @@ -88,22 +88,23 @@ internal class Program .UseAuthentication() .UseAuthorization() .UseCors("default") - /* .UseEndpoints(endpoints => - { - endpoints.MapDefaultControllerRoute() - .RequireAuthorization(); - })*/ - + /* .UseEndpoints(endpoints => + { + endpoints.MapDefaultControllerRoute() + .RequireAuthorization(); + })*/ + ; - // app.MapIdentityApi().RequireAuthorization("ApiScope"); + // app.MapIdentityApi().RequireAuthorization("ApiScope"); app.MapDefaultControllerRoute(); app.MapGet("/identity", (HttpContext context) => new JsonResult(context?.User?.Claims.Select(c => new { c.Type, c.Value })) ); - // app.UseSession(); + // app.UseSession(); await app.RunAsync(); - }; + } + ; diff --git a/src/Yavsc.Abstract/Attributes/Validation/ValidRemoteUserDirAttribute.cs b/src/Yavsc.Abstract/Attributes/Validation/ValidRemoteUserDirAttribute.cs index 2c59f689..43c44054 100644 --- a/src/Yavsc.Abstract/Attributes/Validation/ValidRemoteUserDirAttribute.cs +++ b/src/Yavsc.Abstract/Attributes/Validation/ValidRemoteUserDirAttribute.cs @@ -1,7 +1,7 @@ using System; using System.ComponentModel.DataAnnotations; -using Yavsc.Helpers; +using Yavsc.Server.Helpers; namespace Yavsc.Attributes.Validation { diff --git a/src/Yavsc.Abstract/FileSystem/AbstractFileSystemHelpers.cs b/src/Yavsc.Abstract/FileSystem/AbstractFileSystemHelpers.cs index 0b4aefbb..5e571e24 100644 --- a/src/Yavsc.Abstract/FileSystem/AbstractFileSystemHelpers.cs +++ b/src/Yavsc.Abstract/FileSystem/AbstractFileSystemHelpers.cs @@ -4,7 +4,7 @@ using System.Linq; using System.Text; using Yavsc.ViewModels.UserFiles; -namespace Yavsc.Helpers +namespace Yavsc.Server.Helpers { public static class AbstractFileSystemHelpers { diff --git a/src/Yavsc.Abstract/FileSystem/FsOperationInfo.cs b/src/Yavsc.Abstract/FileSystem/FsOperationInfo.cs index ba748fbd..63c69cb4 100644 --- a/src/Yavsc.Abstract/FileSystem/FsOperationInfo.cs +++ b/src/Yavsc.Abstract/FileSystem/FsOperationInfo.cs @@ -1,4 +1,4 @@ -namespace Yavsc.Helpers +namespace Yavsc.Abstract.Helpers { public enum ErrorCode { NotFound, diff --git a/src/Yavsc.Abstract/FileSystem/UserDirectoryInfo.cs b/src/Yavsc.Abstract/FileSystem/UserDirectoryInfo.cs index 77b7e6e4..cced9397 100644 --- a/src/Yavsc.Abstract/FileSystem/UserDirectoryInfo.cs +++ b/src/Yavsc.Abstract/FileSystem/UserDirectoryInfo.cs @@ -2,7 +2,7 @@ using System; using System.IO; using System.Linq; using Yavsc.Abstract.FileSystem; -using Yavsc.Helpers; +using Yavsc.Server.Helpers; namespace Yavsc.ViewModels.UserFiles { diff --git a/src/Yavsc.Server/Helpers/BillingHelpers.cs b/src/Yavsc.Server/Helpers/BillingHelpers.cs index 0a826447..c10a7615 100644 --- a/src/Yavsc.Server/Helpers/BillingHelpers.cs +++ b/src/Yavsc.Server/Helpers/BillingHelpers.cs @@ -1,10 +1,7 @@ -using System.Collections.Generic; using System.Globalization; -using System.IO; -using System.Linq; -using Yavsc.Abstract.FileSystem; using Yavsc.Billing; using Yavsc.Models.Billing; +using Yavsc.Server.Helpers; using Yavsc.Services; namespace Yavsc.Helpers diff --git a/src/Yavsc.Server/Helpers/FileSystemHelpers.cs b/src/Yavsc.Server/Helpers/FileSystemHelpers.cs index 28721815..f0d5782b 100644 --- a/src/Yavsc.Server/Helpers/FileSystemHelpers.cs +++ b/src/Yavsc.Server/Helpers/FileSystemHelpers.cs @@ -11,8 +11,9 @@ using SixLabors.ImageSharp; using SixLabors.ImageSharp.Processing; using Microsoft.AspNetCore.Http; using Yavsc.Exceptions; - -namespace Yavsc.Helpers +using Yavsc.Helpers; +using Yavsc.Abstract.Helpers; +namespace Yavsc.Server.Helpers { public static class FileSystemHelpers { diff --git a/src/Yavsc.Server/Helpers/UserHelpers.cs b/src/Yavsc.Server/Helpers/UserHelpers.cs index e6db8313..e319239d 100644 --- a/src/Yavsc.Server/Helpers/UserHelpers.cs +++ b/src/Yavsc.Server/Helpers/UserHelpers.cs @@ -9,7 +9,6 @@ namespace Yavsc.Helpers { public static class UserHelpers { - public static string GetUserId(this ClaimsPrincipal user) { return user.FindFirstValue("sub"); diff --git a/src/Yavsc.Server/ViewModels/LiveCastHandler.cs b/src/Yavsc.Server/ViewModels/LiveCastHandler.cs index fc71e760..e5e83506 100644 --- a/src/Yavsc.Server/ViewModels/LiveCastHandler.cs +++ b/src/Yavsc.Server/ViewModels/LiveCastHandler.cs @@ -10,6 +10,7 @@ using Newtonsoft.Json; using Yavsc.Helpers; using Yavsc.Models; using Yavsc.Models.FileSystem; +using Yavsc.Server.Helpers; namespace Yavsc.ViewModels.Streaming { diff --git a/src/Yavsc/Controllers/Contracting/EstimateController.cs b/src/Yavsc/Controllers/Contracting/EstimateController.cs index d68c3656..b81af756 100644 --- a/src/Yavsc/Controllers/Contracting/EstimateController.cs +++ b/src/Yavsc/Controllers/Contracting/EstimateController.cs @@ -12,6 +12,7 @@ namespace Yavsc.Controllers using Models.Billing; using Models.Workflow; using ViewModels.Auth; + using Yavsc.Server.Helpers; [Authorize] public class EstimateController : Controller diff --git a/src/Yavsc/Controllers/Contracting/FrontOfficeController.cs b/src/Yavsc/Controllers/Contracting/FrontOfficeController.cs index 55a04fb0..666fa501 100644 --- a/src/Yavsc/Controllers/Contracting/FrontOfficeController.cs +++ b/src/Yavsc/Controllers/Contracting/FrontOfficeController.cs @@ -10,6 +10,7 @@ namespace Yavsc.Controllers using Microsoft.Extensions.Localization; using Models; using ViewModels.FrontOffice; + using Yavsc.Server.Helpers; using Yavsc.Services; public class FrontOfficeController : Controller diff --git a/src/Yavsc/Controllers/FileSystemController.cs b/src/Yavsc/Controllers/FileSystemController.cs index 36ebcb04..84579675 100644 --- a/src/Yavsc/Controllers/FileSystemController.cs +++ b/src/Yavsc/Controllers/FileSystemController.cs @@ -1,6 +1,7 @@ using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Yavsc.Helpers; +using Yavsc.Server.Helpers; namespace Yavsc.Controllers { diff --git a/src/Yavsc/Extensions/HostingExtensions.cs b/src/Yavsc/Extensions/HostingExtensions.cs index d781de86..d86f8259 100644 --- a/src/Yavsc/Extensions/HostingExtensions.cs +++ b/src/Yavsc/Extensions/HostingExtensions.cs @@ -29,6 +29,7 @@ using Yavsc.Models.Workflow; using Yavsc.Services; using Yavsc.Settings; using Yavsc.ViewModels.Auth; +using Yavsc.Server.Helpers; namespace Yavsc.Extensions; @@ -335,7 +336,6 @@ public static class HostingExtensions .AddInMemoryIdentityResources(Config.IdentityResources) .AddInMemoryClients(Config.Clients) .AddInMemoryApiScopes(Config.ApiScopes) - .AddAspNetIdentity() .AddProfileService() ; diff --git a/src/Yavsc/Helpers/UserHelpers.cs b/src/Yavsc/Helpers/UserHelpers.cs new file mode 100644 index 00000000..ade8cac0 --- /dev/null +++ b/src/Yavsc/Helpers/UserHelpers.cs @@ -0,0 +1,10 @@ +using System.Security.Claims; + +namespace Yavsc.Helpers +{ + public static class UserHelpers + { + + + } +} diff --git a/src/Yavsc/Startup.cs b/src/Yavsc/Startup.cs index 1625debf..93cf5dcf 100644 --- a/src/Yavsc/Startup.cs +++ b/src/Yavsc/Startup.cs @@ -2,6 +2,7 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.Extensions.Localization; using Microsoft.Extensions.Options; using Yavsc.Helpers; +using Yavsc.Server.Helpers; using Yavsc.Settings; namespace Yavsc; diff --git a/src/Yavsc/ViewComponents/BillViewComponent.cs b/src/Yavsc/ViewComponents/BillViewComponent.cs index 4f7c3fc5..d0d0b9fe 100644 --- a/src/Yavsc/ViewComponents/BillViewComponent.cs +++ b/src/Yavsc/ViewComponents/BillViewComponent.cs @@ -8,6 +8,7 @@ using Yavsc.ViewModels; using Yavsc.ViewModels.Gen; using Yavsc.Services; using Microsoft.EntityFrameworkCore; +using Yavsc.Server.Helpers; namespace Yavsc.ViewComponents { diff --git a/src/Yavsc/ViewComponents/DirectoryViewComponent.cs b/src/Yavsc/ViewComponents/DirectoryViewComponent.cs index b5f5b902..af7f436b 100644 --- a/src/Yavsc/ViewComponents/DirectoryViewComponent.cs +++ b/src/Yavsc/ViewComponents/DirectoryViewComponent.cs @@ -3,6 +3,7 @@ using Microsoft.AspNetCore.Mvc; using System.Threading.Tasks; using Yavsc.Helpers; using Yavsc.Models; +using Yavsc.Server.Helpers; using Yavsc.ViewModels.UserFiles; namespace Yavsc.ViewComponents diff --git a/src/Yavsc/app.config b/src/Yavsc/app.config deleted file mode 100644 index 8460dd43..00000000 --- a/src/Yavsc/app.config +++ /dev/null @@ -1,11 +0,0 @@ - - - - - - - - - - - \ No newline at end of file diff --git a/src/sampleWebAsWebApiClient/Program.cs b/src/sampleWebAsWebApiClient/Program.cs index 31426483..5cc25c36 100644 --- a/src/sampleWebAsWebApiClient/Program.cs +++ b/src/sampleWebAsWebApiClient/Program.cs @@ -11,6 +11,7 @@ */ using System.IdentityModel.Tokens.Jwt; +using Microsoft.AspNetCore.Authentication; JwtSecurityTokenHandler.DefaultMapInboundClaims = false; @@ -36,7 +37,10 @@ builder.Services options.Scope.Add("openid"); options.Scope.Add("profile"); options.Scope.Add("scope2"); - + options.MapInboundClaims = true; + options.ClaimActions.MapUniqueJsonKey("preferred_username","preferred_username"); + options.ClaimActions.MapUniqueJsonKey("gender", "gender"); + options.SaveTokens = true; });