diff --git a/.vscode/settings.json b/.vscode/settings.json index 16bbe483..6e22cb5e 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -12,10 +12,8 @@ "DOTNET", "ecdsa", "envsubst", - "Hsts", "Newtonsoft", "Npgsql", - "PKCE", "postit", "pschneider", "SLNDIR", diff --git a/src/PostIt/PostIt/ViewModels/Settings.cs b/src/PostIt/PostIt/ViewModels/Settings.cs index 890ca15c..9d556712 100644 --- a/src/PostIt/PostIt/ViewModels/Settings.cs +++ b/src/PostIt/PostIt/ViewModels/Settings.cs @@ -179,7 +179,7 @@ public partial class Settings : ViewModelBase RedirectUri = Authentication.RedirectUri, Scope = string.Join(' ', MergeScopes(this.Authentication.Scopes)), TokenClientCredentialStyle = IdentityModel.Client.ClientCredentialStyle.PostBody, - PostLogoutRedirectUri = Authentication.Authority, + PostLogoutRedirectUri = "https//yavsc.pschneider.fr", // PKCE is enabled by default when no client_secret is provided. }; diff --git a/src/Yavsc.Org/Controllers/Accounting/AccountController.cs b/src/Yavsc.Org/Controllers/Accounting/AccountController.cs index 43565442..e8a63163 100644 --- a/src/Yavsc.Org/Controllers/Accounting/AccountController.cs +++ b/src/Yavsc.Org/Controllers/Accounting/AccountController.cs @@ -791,12 +791,12 @@ IHtmlLocalizerFactory htmlLocalizerFactory, { if (userId == null || code == null) { - return this.ErrorView("Error: userId or code is null."); + return View("Error"); } var user = await _userManager.FindByIdAsync(userId); if (user == null) { - return this.ErrorView("Error: user not found."); + return View("Error"); } IdentityResult result = null; try @@ -819,12 +819,12 @@ IHtmlLocalizerFactory htmlLocalizerFactory, { if (userId == null || code == null) { - return this.ErrorView("Error: userId or code is null."); + return View("Error"); } var user = await _userManager.FindByIdAsync(userId); if (user == null) { - return this.ErrorView("Error: user not found."); + return View("Error"); } bool result = false; try @@ -837,7 +837,7 @@ IHtmlLocalizerFactory htmlLocalizerFactory, _logger.LogError(ex.StackTrace); _logger.LogError(ex.Message); } - return result ? View("EmailConfirmed") : this.ErrorView("Error confirming two factor token."); + return View(result ? "EmailConfirmed" : "Error"); } // diff --git a/src/Yavsc.Org/Controllers/Accounting/ManageController.cs b/src/Yavsc.Org/Controllers/Accounting/ManageController.cs index 43e11cd2..7419c889 100644 --- a/src/Yavsc.Org/Controllers/Accounting/ManageController.cs +++ b/src/Yavsc.Org/Controllers/Accounting/ManageController.cs @@ -1,5 +1,6 @@ using System.Security.Claims; +using System.IO; using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Localization; @@ -489,7 +490,12 @@ namespace Yavsc.Controllers : message == ManageMessageId.Error ? "An error has occurred." : ""; var user = await GetCurrentUserAsync(); + if (user == null) + { + return View("Error"); + } var userLogins = await _userManager.GetLoginsAsync(user); + ViewBag.ShowRemoveButton = user.PasswordHash != null || userLogins.Count > 1; return View(new ManageLoginsViewModel @@ -516,7 +522,15 @@ namespace Yavsc.Controllers public async Task LinkLoginCallback() { var user = await GetCurrentUserAsync(); + if (user == null) + { + return View("Error"); + } var info = await _signInManager.GetExternalLoginInfoAsync(User.GetUserId()); + if (info == null) + { + return RedirectToAction(nameof(ManageLogins), new { Message = ManageMessageId.Error }); + } var result = await _userManager.AddLoginAsync(user, info); var message = result.Succeeded ? ManageMessageId.AddLoginSuccess : ManageMessageId.Error; return RedirectToAction(nameof(ManageLogins), new { Message = message }); diff --git a/src/Yavsc.Org/Controllers/Consent/ConsentController.cs b/src/Yavsc.Org/Controllers/Consent/ConsentController.cs index b7b6eff8..15c4a93b 100644 --- a/src/Yavsc.Org/Controllers/Consent/ConsentController.cs +++ b/src/Yavsc.Org/Controllers/Consent/ConsentController.cs @@ -16,7 +16,6 @@ using System.Collections.Generic; using System; using Yavsc; using Yavsc.Extensions; -using Yavsc.Models; namespace IdentityServerHost.Quickstart.UI { @@ -54,10 +53,9 @@ namespace IdentityServerHost.Quickstart.UI { return View("Index", vm); } - return this.ErrorView("No consent request matching request: " + returnUrl); - } - + return View("Error"); + } /// /// Handles the consent screen postback @@ -90,8 +88,8 @@ namespace IdentityServerHost.Quickstart.UI { return View("Index", result.ViewModel); } - return this.ErrorView($"ReturnUrl: {model}, result: {result}" ); - + + return View("Error"); } /*****************************************/ @@ -172,6 +170,11 @@ namespace IdentityServerHost.Quickstart.UI { return CreateConsentViewModel(model, returnUrl, request); } + else + { + _logger.LogError("No consent request matching request: {0}", returnUrl); + } + return null; } @@ -196,7 +199,7 @@ namespace IdentityServerHost.Quickstart.UI vm.IdentityScopes = request.ValidatedResources.Resources.IdentityResources.Select(x => CreateScopeViewModel(x, vm.ScopesConsented.Contains(x.Name) || model == null)).ToArray(); var apiScopes = new List(); - foreach (var parsedScope in request.ValidatedResources.ParsedScopes) + foreach(var parsedScope in request.ValidatedResources.ParsedScopes) { var apiScope = request.ValidatedResources.Resources.FindApiScope(parsedScope.ParsedName); if (apiScope != null) diff --git a/src/Yavsc.Org/Controllers/Device/DeviceController.cs b/src/Yavsc.Org/Controllers/Device/DeviceController.cs index 2e516aa6..5e0c7780 100644 --- a/src/Yavsc.Org/Controllers/Device/DeviceController.cs +++ b/src/Yavsc.Org/Controllers/Device/DeviceController.cs @@ -16,7 +16,6 @@ using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; -using Yavsc.Models; using Yavsc.Models.Access; namespace Yavsc.Controllers @@ -50,7 +49,7 @@ namespace Yavsc.Controllers if (string.IsNullOrWhiteSpace(userCode)) return View("UserCodeCapture"); var vm = await BuildViewModelAsync(userCode); - if (vm == null) return this.ErrorView($"ViewModel is null! userCodeParamName: {userCodeParamName}, userCode: {userCode}" );; + if (vm == null) return View("Error"); vm.ConfirmUserCode = true; return View("UserCodeConfirmation", vm); @@ -61,7 +60,7 @@ namespace Yavsc.Controllers public async Task UserCodeCapture(string userCode) { var vm = await BuildViewModelAsync(userCode); - if (vm == null) return this.ErrorView($"UserCodeCapture: ViewModel is null! userCode: {userCode}" ); + if (vm == null) return View("Error"); return View("UserCodeConfirmation", vm); } @@ -73,20 +72,7 @@ namespace Yavsc.Controllers if (model == null) throw new ArgumentNullException(nameof(model)); var result = await ProcessConsent(model); - if (result.HasValidationError) - { - if (HttpContext.RequestServices.GetRequiredService().IsDevelopment()) - { - throw new InvalidOperationException("Device Authorization Input validation error: " + result.ValidationError); - } - - return View("Error", - new ErrorViewModel { - RequestId = HttpContext.TraceIdentifier, - Description = "Device Authorization Input validation error: " + result.ValidationError - } - ); - } + if (result.HasValidationError) return View("Error"); return View("Success"); } diff --git a/src/Yavsc.Org/Controllers/HomeController.cs b/src/Yavsc.Org/Controllers/HomeController.cs index 67c19fed..2602a1a3 100644 --- a/src/Yavsc.Org/Controllers/HomeController.cs +++ b/src/Yavsc.Org/Controllers/HomeController.cs @@ -15,24 +15,18 @@ namespace Yavsc.Controllers public class HomeController : Controller { readonly ApplicationDbContext _dbContext; - readonly ILogger _logger; - private readonly bool _isDevelopment; + readonly IHtmlLocalizer _localizer; private SiteSettings siteSettings; public HomeController(ILogger logger, IHtmlLocalizer localizer, ApplicationDbContext context, - IOptions settingsOptions, - IWebHostEnvironment env - ) + IOptions settingsOptions) { _localizer = localizer; _dbContext = context; siteSettings = settingsOptions.Value; - _logger = logger; - _isDevelopment = env.IsDevelopment(); - } public async Task Index(string id) @@ -105,44 +99,18 @@ namespace Yavsc.Controllers public IActionResult Error() { - if (_isDevelopment) + var feature = this.HttpContext.Features.Get(); + if (feature == null) return View(); + var errorType = feature?.Error; + if (errorType == null) return View(); + if (errorType is NotSupportedException notSupported) { - _logger.LogInformation( - "Home/Error requested in Development. This endpoint is disabled because DeveloperExceptionPage should handle unhandled exceptions."); - - return NotFound( - "In Development, /Home/Error is disabled. Unhandled exceptions are rendered by DeveloperExceptionPage."); + return View(new ErrorViewModel { + Description = notSupported.Message, + RequestId = this.HttpContext.TraceIdentifier + }); } - - var errorViewModel = new ErrorViewModel - { - RequestId = HttpContext.TraceIdentifier - }; - - var exceptionHandlerPathFeature = - HttpContext.Features.Get(); - - if (exceptionHandlerPathFeature is null) - { - _logger.LogWarning( - "Home/Error called without IExceptionHandlerPathFeature in non-development environment."); - - return View("~/Views/Shared/Error.cshtml", errorViewModel); - } - - if (exceptionHandlerPathFeature?.Error is FileNotFoundException) - { - errorViewModel.Description = "The file was not found."; - } - - if (exceptionHandlerPathFeature?.Path == "/") - { - errorViewModel.Description ??= string.Empty; - errorViewModel.Description += " Page: Home."; - } - - - return View("~/Views/Shared/Error.cshtml", errorViewModel); + return View("~/Views/Shared/Error.cshtml", feature?.Error); } public IActionResult Status(int id) { diff --git a/src/Yavsc.Org/Extensions/HostingExtensions.cs b/src/Yavsc.Org/Extensions/HostingExtensions.cs index b3f90639..a494a05b 100644 --- a/src/Yavsc.Org/Extensions/HostingExtensions.cs +++ b/src/Yavsc.Org/Extensions/HostingExtensions.cs @@ -967,12 +967,12 @@ public static class HostingExtensions if (app.Environment.IsDevelopment()) { app.UseDeveloperExceptionPage(); + await app.MigrateDatabaseAsync(); } else { app.UseExceptionHandler("/Home/Error"); - app.UseHsts(); - logger.LogInformation("⨝ Running in production mode. Ensure the database is migrated."); + logger.LogInformation("Running in production mode. Ensure the database is migrated."); await app.MigrateDatabaseAsync(); } diff --git a/src/Yavsc.Org/Helpers/ErrorViewHelpers.cs b/src/Yavsc.Org/Helpers/ErrorViewHelpers.cs deleted file mode 100644 index 3d038c3f..00000000 --- a/src/Yavsc.Org/Helpers/ErrorViewHelpers.cs +++ /dev/null @@ -1,52 +0,0 @@ -using Microsoft.AspNetCore.Mvc; -using Yavsc.Models; - -public static class ErrorViewHelpers -{ - public static IActionResult ErrorView(this Controller controller, string message) - { - var logger = controller.HttpContext.RequestServices.GetRequiredService() - .CreateLogger(); - - logger.LogError(message); - Dictionary dictionary = new Dictionary(); - - if (!controller.ModelState.IsValid) - { - foreach (var modelState in controller.ModelState.Values) - { - foreach (var error in modelState.Errors) - { - logger.LogError("ModelState error: {0}", error.ErrorMessage); - foreach (var key in controller.ModelState.Keys) - { - logger.LogError("ModelState key: {0}", key); - dictionary.Add(key, - string.Join("\n", - controller.ModelState[key].Errors.Select( e => e.ErrorMessage).ToArray())); - } - } - } - } - - if (controller.HttpContext.Request.Headers.ContainsKey("Accept") - && controller.HttpContext.Request.Headers["Accept"].ToString().Contains("application/json")) - { - return controller.Json(new - { - RequestId = controller.HttpContext.TraceIdentifier, - Description = message, - ModelErrors = dictionary - }); - } - - return controller.View("Error", - new ErrorViewModel - { - RequestId = controller.HttpContext.TraceIdentifier, - Description = message, - ModelErrors = dictionary - } - ); - } -} \ No newline at end of file diff --git a/src/Yavsc.Server/Models/ErrorViewModel.cs b/src/Yavsc.Server/Models/ErrorViewModel.cs index 17819476..1b779ead 100644 --- a/src/Yavsc.Server/Models/ErrorViewModel.cs +++ b/src/Yavsc.Server/Models/ErrorViewModel.cs @@ -7,5 +7,4 @@ public class ErrorViewModel public bool ShowRequestId => !string.IsNullOrEmpty(RequestId); - public Dictionary ModelErrors { get; set; } }