From 1c154a04fdab61612445bf806708e4879167c33b Mon Sep 17 00:00:00 2001 From: JT Date: Wed, 15 Nov 2023 11:17:56 +0800 Subject: [PATCH 1/6] WIP .NET 8 pass --- src/Alba.Testing/Alba.Testing.csproj | 2 +- src/Alba.Testing/StringExtensionsTests.cs | 46 ------- src/Alba/Alba.csproj | 11 +- src/Alba/AlbaHost.cs | 29 ---- src/Alba/CommaTokenParser.cs | 124 ------------------ src/Alba/DirectoryFinder.cs | 56 -------- src/Alba/FormDataExtensions.cs | 2 +- src/Alba/HttpContextExtensions.cs | 6 +- src/Alba/IAlbaHost.cs | 5 +- src/Alba/Internal/AlbaTracing.cs | 2 +- src/Alba/Internal/StreamExtensions.cs | 4 +- src/Alba/Internal/StringSyntaxAttribute.cs | 2 +- src/Alba/Scenario.cs | 11 -- .../Security/AuthenticationExtensionBase.cs | 2 +- src/Alba/SendExpression.cs | 6 +- src/Alba/StringExtensions.cs | 65 --------- .../MinimalApiWithOakton.csproj | 4 +- 17 files changed, 24 insertions(+), 353 deletions(-) delete mode 100644 src/Alba.Testing/StringExtensionsTests.cs delete mode 100644 src/Alba/CommaTokenParser.cs delete mode 100644 src/Alba/DirectoryFinder.cs delete mode 100644 src/Alba/StringExtensions.cs diff --git a/src/Alba.Testing/Alba.Testing.csproj b/src/Alba.Testing/Alba.Testing.csproj index 58161e9e..357e5141 100644 --- a/src/Alba.Testing/Alba.Testing.csproj +++ b/src/Alba.Testing/Alba.Testing.csproj @@ -1,6 +1,6 @@  - net6.0;net7.0 + net6.0;net8.0 portable Alba.Testing Alba.Testing diff --git a/src/Alba.Testing/StringExtensionsTests.cs b/src/Alba.Testing/StringExtensionsTests.cs deleted file mode 100644 index 74c5281e..00000000 --- a/src/Alba.Testing/StringExtensionsTests.cs +++ /dev/null @@ -1,46 +0,0 @@ -using System; -using Shouldly; -using Xunit; - -namespace Alba.Testing -{ - public class StringExtensionsTests - { - [Fact] - public void get_comma_separated_values_from_header() - { - new[] { "v1", "v2, v3", "\"v4, b\"", "v5, v6", "v7", } - .GetCommaSeparatedHeaderValues() - .ShouldHaveTheSameElementsAs("v1", "v2", "v3", "v4, b", "v5", "v6", "v7"); - - new[] { "v1,v2, v3,\"v4, b\",v5, v6,v7" } - .GetCommaSeparatedHeaderValues() - .ShouldHaveTheSameElementsAs("v1", "v2", "v3", "v4, b", "v5", "v6", "v7"); - } - - [Fact] - public void quoted_string() - { - "foo".Quoted().ShouldBe("\"foo\""); - } - - - [Fact] - public void try_parse_http_date() - { - var date = DateTime.Today.AddHours(3); - - var datestring = date.ToString("r"); - - datestring.TryParseHttpDate().ShouldBe(date); - } - - [Fact] - public void try_parse_http_date_with_empty_string() - { - "".TryParseHttpDate().ShouldBeNull(); - } - - - } -} \ No newline at end of file diff --git a/src/Alba/Alba.csproj b/src/Alba/Alba.csproj index 5d77901c..3afec04d 100644 --- a/src/Alba/Alba.csproj +++ b/src/Alba/Alba.csproj @@ -3,8 +3,8 @@ Supercharged integration testing for ASP.NET Core HTTP endpoints Alba - 7.4.1 - net6.0;net7.0 + 8.0.0-rc.1 + net6.0;net7.0;net8.0 Alba Alba http://jasperfx.github.io/alba/ @@ -21,7 +21,7 @@ - + @@ -35,4 +35,9 @@ + + + + + diff --git a/src/Alba/AlbaHost.cs b/src/Alba/AlbaHost.cs index 50f766da..15902a19 100644 --- a/src/Alba/AlbaHost.cs +++ b/src/Alba/AlbaHost.cs @@ -437,35 +437,6 @@ public async Task Invoke(Action setup) } } - /// - /// Create a SystemUnderTest using the designated "Startup" type - /// to configure the ASP.NET Core system - /// - /// - /// Optional configuration of the IHostBuilder to be applied *after* the call to - /// IWebHostBuilder.UseStartup() - /// - /// Specify the content root directory to be used by the host. - /// - /// The system under test - [Obsolete("We recommend using the WebApplicationFactory approach or bootstrapping from IHostBuilder. This will be removed in the future")] - public static AlbaHost ForStartup(Func? configure = null, - string? rootPath = null) where T : class - { - var builder = Host.CreateDefaultBuilder(); - builder.ConfigureWebHostDefaults(config => config.UseStartup()); - - if (configure != null) - { - builder = configure(builder); - } - - builder.UseContentRoot(rootPath ?? DirectoryFinder.FindParallelFolder(typeof(T).Assembly.GetName().Name) ?? - AppContext.BaseDirectory); - - return new AlbaHost(builder); - } - /// /// Creates a SystemUnderTest from a default HostBuilder using the provided IWebHostBuilder diff --git a/src/Alba/CommaTokenParser.cs b/src/Alba/CommaTokenParser.cs deleted file mode 100644 index 806ec60a..00000000 --- a/src/Alba/CommaTokenParser.cs +++ /dev/null @@ -1,124 +0,0 @@ -using System; -using System.Collections.Generic; - -namespace Alba -{ - [Obsolete] - internal class CommaTokenParser - { - private readonly List _tokens = new(); - private List _characters; - private IMode _mode; - - public CommaTokenParser() - { - _characters = new List(); - _mode = new Searching(this); - } - - public void Read(char c) - { - _mode.Read(c); - } - - private void addChar(char c) - { - _characters.Add(c); - } - - public IEnumerable Tokens => _tokens; - - private void startToken(IMode mode) - { - _mode = mode; - _characters = new List(); - } - - private void endToken() - { - var @string = new string(_characters.ToArray()); - _tokens.Add(@string); - - _mode = new Searching(this); - } - - - public interface IMode - { - void Read(char c); - } - - public class Searching : IMode - { - private readonly CommaTokenParser _parent; - - public Searching(CommaTokenParser parent) - { - _parent = parent; - } - - public void Read(char c) - { - if (c == ',') return; - - if (c == '"') - { - _parent.startToken(new InsideQuotedToken(_parent)); - } - else - { - var normalToken = new InsideNormalToken(_parent); - _parent.startToken(normalToken); - normalToken.Read(c); - } - } - } - - public class InsideQuotedToken : IMode - { - private readonly CommaTokenParser _parent; - - public InsideQuotedToken(CommaTokenParser parent) - { - _parent = parent; - } - - - public void Read(char c) - { - if (c == '"') - { - _parent.endToken(); - } - else - { - _parent.addChar(c); - } - } - } - - public class InsideNormalToken : IMode - { - private readonly CommaTokenParser _parent; - - public InsideNormalToken(CommaTokenParser parent) - { - _parent = parent; - } - - public void Read(char c) - { - if (c == ',') - { - _parent.endToken(); - } - else - { - _parent.addChar(c); - } - } - } - - - } -} \ No newline at end of file diff --git a/src/Alba/DirectoryFinder.cs b/src/Alba/DirectoryFinder.cs deleted file mode 100644 index 64e12fbe..00000000 --- a/src/Alba/DirectoryFinder.cs +++ /dev/null @@ -1,56 +0,0 @@ -using System; -using System.Collections.Generic; -using System.IO; -using System.Linq; - -namespace Alba -{ - // Delete this all in next semver - internal static class DirectoryFinder - { - /// - /// Tries to find the correct content path for a project that is parallel to the - /// testing project - /// - /// - /// - [Obsolete] - public static string? FindParallelFolder(string? folderName) - { - var starting = AppContext.BaseDirectory.ToFullPath(); - - // HACK ALERT!! but it does work - if (starting.Contains("dotnet-xunit")) - { - starting = Directory.GetCurrentDirectory(); - } - - -#pragma warning disable 8602 - while (starting.Contains(Path.DirectorySeparatorChar + "bin")) -#pragma warning restore 8602 - { - starting = starting.ParentDirectory(); - } - - -#pragma warning disable 8604 - var candidate = starting.ParentDirectory().AppendPath(folderName); -#pragma warning restore 8604 - - - return Directory.Exists(candidate) ? candidate : null; - } - - public static string ToFullPath(this string path) => Path.GetFullPath(path); - - public static string? ParentDirectory(this string path) => Path.GetDirectoryName(path.TrimEnd(Path.DirectorySeparatorChar)); - - public static string AppendPath(this string path, params string[] parts) - { - var stringList = new List { path }; - stringList.AddRange(parts); - return Combine(stringList.ToArray()); - } - public static string Combine(params string[] paths) => (paths).Aggregate(Path.Combine); } -} \ No newline at end of file diff --git a/src/Alba/FormDataExtensions.cs b/src/Alba/FormDataExtensions.cs index fc6d1fa1..e4823284 100644 --- a/src/Alba/FormDataExtensions.cs +++ b/src/Alba/FormDataExtensions.cs @@ -39,7 +39,7 @@ public static void WriteMultipartFormData(this HttpContext context, MultipartFor content.CopyTo(context.Request.Body, null, CancellationToken.None); foreach (var kv in content.Headers) { - context.Request.Headers.Add(kv.Key, kv.Value.ToArray()); + context.Request.Headers.Append(kv.Key, kv.Value.ToArray()); } } } diff --git a/src/Alba/HttpContextExtensions.cs b/src/Alba/HttpContextExtensions.cs index 26c2b381..25c4b1b3 100644 --- a/src/Alba/HttpContextExtensions.cs +++ b/src/Alba/HttpContextExtensions.cs @@ -15,7 +15,7 @@ public static void ContentType(this HttpRequest request, string mimeType) public static void ContentType(this HttpResponse response, string mimeType) { - response.Headers["content-type"] = mimeType; + response.Headers.ContentType = mimeType; } public static void RelativeUrl(this HttpContext context, [StringSyntax(StringSyntaxAttribute.Uri)]string? relativeUrl) @@ -43,12 +43,12 @@ public static void RelativeUrl(this HttpContext context, [StringSyntax(StringSyn /// public static void SetBearerToken(this HttpContext context, string jwt) { - context.Request.Headers["Authorization"] = $"Bearer {jwt}"; + context.Request.Headers.Authorization = $"Bearer {jwt}"; } public static void Accepts(this HttpContext context, string mimeType) { - context.Request.Headers["accept"] = mimeType; + context.Request.Headers.Accept = mimeType; } public static void HttpMethod(this HttpContext context, string method) diff --git a/src/Alba/IAlbaHost.cs b/src/Alba/IAlbaHost.cs index edc886a4..dfa3634b 100644 --- a/src/Alba/IAlbaHost.cs +++ b/src/Alba/IAlbaHost.cs @@ -15,10 +15,7 @@ public interface IAlbaHost : IHost, IAsyncDisposable /// /// /// - Task Scenario( - Action configure) - // ENDSAMPLE - ; + Task Scenario(Action configure); /// /// Execute some kind of action before each scenario. This is NOT additive diff --git a/src/Alba/Internal/AlbaTracing.cs b/src/Alba/Internal/AlbaTracing.cs index 48257015..db3bb287 100644 --- a/src/Alba/Internal/AlbaTracing.cs +++ b/src/Alba/Internal/AlbaTracing.cs @@ -9,7 +9,7 @@ namespace Alba.Internal; internal static class AlbaTracing { - public static readonly ActivitySource Source = new("Alba"); + private static readonly ActivitySource Source = new("Alba"); public const string HttpUrl = "http.url"; public const string HttpMethod = "http.method"; diff --git a/src/Alba/Internal/StreamExtensions.cs b/src/Alba/Internal/StreamExtensions.cs index 22b118ff..172f2ff7 100644 --- a/src/Alba/Internal/StreamExtensions.cs +++ b/src/Alba/Internal/StreamExtensions.cs @@ -19,10 +19,10 @@ public static byte[] ReadAllBytes(this Stream stream) return content.ToArray(); } - public static Task ReadAllTextAsync(this Stream stream) + public static async Task ReadAllTextAsync(this Stream stream) { using var sr = new StreamReader(stream, leaveOpen: true); - return sr.ReadToEndAsync(); + return await sr.ReadToEndAsync(); } public static async Task ReadAllBytesAsync(this Stream stream) diff --git a/src/Alba/Internal/StringSyntaxAttribute.cs b/src/Alba/Internal/StringSyntaxAttribute.cs index 6fc72587..ffb270d2 100644 --- a/src/Alba/Internal/StringSyntaxAttribute.cs +++ b/src/Alba/Internal/StringSyntaxAttribute.cs @@ -1,4 +1,4 @@ -#if !NET7_0 +#if !NET7_0_OR_GREATER // Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. diff --git a/src/Alba/Scenario.cs b/src/Alba/Scenario.cs index 90f8bc99..f6fe5f3d 100644 --- a/src/Alba/Scenario.cs +++ b/src/Alba/Scenario.cs @@ -346,17 +346,6 @@ internal void SetupHttpContext(HttpContext context) foreach (var setup in _setups) setup(context); } - /// - /// Set a value for a request header - /// - /// - /// - [Obsolete("Prefer the WithRequestHeader() method, and this will be removed in Alba v6")] - public void SetRequestHeader(string headerKey, string value) - { - WithRequestHeader(headerKey, value); - } - /// /// Set a value for a request header /// diff --git a/src/Alba/Security/AuthenticationExtensionBase.cs b/src/Alba/Security/AuthenticationExtensionBase.cs index a42d790d..7430dd16 100644 --- a/src/Alba/Security/AuthenticationExtensionBase.cs +++ b/src/Alba/Security/AuthenticationExtensionBase.cs @@ -11,7 +11,7 @@ namespace Alba.Security /// public abstract class AuthenticationExtensionBase : IHasClaims { - private readonly IList _baselineClaims = new List(); + private readonly List _baselineClaims = new(); void IHasClaims.AddClaim(Claim claim) diff --git a/src/Alba/SendExpression.cs b/src/Alba/SendExpression.cs index 1d35d9e2..8e3e2bc5 100644 --- a/src/Alba/SendExpression.cs +++ b/src/Alba/SendExpression.cs @@ -27,7 +27,7 @@ private Action modify /// public SendExpression ContentType(string contentType) { - modify = request => request.Headers["content-type"] = contentType; + modify = request => request.Headers.ContentType = contentType; return this; } @@ -38,7 +38,7 @@ public SendExpression ContentType(string contentType) /// public SendExpression Accepts(string accepts) { - modify = request => request.Headers["accept"] = accepts; + modify = request => request.Headers.Accept = accepts; return this; } @@ -49,7 +49,7 @@ public SendExpression Accepts(string accepts) /// public SendExpression Etag(string etag) { - modify = request => request.Headers["If-None-Match"] = etag; + modify = request => request.Headers.IfNoneMatch = etag; return this; } diff --git a/src/Alba/StringExtensions.cs b/src/Alba/StringExtensions.cs deleted file mode 100644 index 330f544b..00000000 --- a/src/Alba/StringExtensions.cs +++ /dev/null @@ -1,65 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Globalization; -using System.Net; - -namespace Alba -{ - public static class StringExtensions - { - /// - /// Helper to expand any comma separated values out into an enumerable of - /// all the string values - /// - /// - /// - [Obsolete("Use HeaderDictionary.GetCommaSeparatedHeaderValues instead")] - public static IEnumerable GetCommaSeparatedHeaderValues(this IEnumerable enumerable) - { - foreach (var content in enumerable) - { - var searchString = content.Trim(); - if (searchString.Length == 0) break; - - var parser = new CommaTokenParser(); - var array = content.ToCharArray(); - - foreach (var c in array) - { - parser.Read(c); - } - - // Gotta force the parser to know it's done - parser.Read(','); - - foreach (var token in parser.Tokens) - { - yield return token.Trim(); - } - } - - - } - - [Obsolete("Use WebUtility.UrlEncode directly")] - public static string UrlEncoded(this string value) - { - return WebUtility.UrlEncode(value); - } - - [Obsolete("Copy this extension into your own codebase if you wish to continue using it.")] - public static string Quoted(this string value) - { - return $"\"{value}\""; - } - - [Obsolete("Copy this extension into your own codebase if you wish to continue using it.")] - public static DateTime? TryParseHttpDate(this string dateString) - { - return DateTime.TryParseExact(dateString, "r", CultureInfo.InvariantCulture, DateTimeStyles.None, out var date) - ? date - : null; - } - - } -} \ No newline at end of file diff --git a/src/MinimalApiWithOakton/MinimalApiWithOakton.csproj b/src/MinimalApiWithOakton/MinimalApiWithOakton.csproj index 7603db8d..ab410677 100644 --- a/src/MinimalApiWithOakton/MinimalApiWithOakton.csproj +++ b/src/MinimalApiWithOakton/MinimalApiWithOakton.csproj @@ -7,8 +7,8 @@ - - + + From 039f87d2f085ceb90d83b855693b09b11b083b8e Mon Sep 17 00:00:00 2001 From: JT Date: Thu, 16 Nov 2023 21:50:21 +0800 Subject: [PATCH 2/6] Deal with general upgrade cruft/obsolete code --- .github/workflows/docs.yml | 6 ++-- .github/workflows/dotnet.yml | 7 +++- .../assertions_against_redirects.cs | 32 ++++++++---------- .../customize_before_each_and_after_each.cs | 13 ++++---- .../Acceptance/data_binding_in_mvc_app.cs | 4 +-- .../specs_against_aspnet_core_app.cs | 19 +++++++---- .../using_custom_service_registrations.cs | 33 +++++++++---------- src/Alba.Testing/Alba.Testing.csproj | 5 ++- .../Assertions/RedirectAssertionTests.cs | 1 - src/Alba.Testing/CrudeRouter.cs | 4 +-- src/Alba.Testing/FormDataExtensionsTests.cs | 2 +- src/Alba.Testing/Samples/Quickstart.cs | 2 +- src/Alba.Testing/SpecificationExtensions.cs | 2 +- .../reading_and_writing_xml_to_context.cs | 2 +- src/Alba/Alba.csproj | 2 +- src/Alba/Scenario.cs | 8 ++--- src/Alba/Security/TestAuthHandler.cs | 10 ++++++ .../MinimalApiWithOakton.csproj | 4 +-- src/WebApp/Controllers/FilesController.cs | 1 - src/WebApp/Controllers/JsonController.cs | 2 +- .../Controllers/QueryStringContoller.cs | 2 +- src/WebApp/WebApp.csproj | 2 +- 22 files changed, 87 insertions(+), 76 deletions(-) diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index f0ca9fb4..1cebf3bc 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -14,15 +14,15 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Install .NET Core 7.0.x + - name: Install .NET Core 8.0.x uses: actions/setup-dotnet@v3 with: - dotnet-version: 7.0.x + dotnet-version: 8.0.x - name: Install Node.js uses: actions/setup-node@v3 with: - node-version: 18 + node-version: 20 - name: Setup Pages uses: actions/configure-pages@v3 diff --git a/.github/workflows/dotnet.yml b/.github/workflows/dotnet.yml index c67dada1..56b8d304 100644 --- a/.github/workflows/dotnet.yml +++ b/.github/workflows/dotnet.yml @@ -19,7 +19,7 @@ jobs: steps: - uses: actions/checkout@v3 - - name: Setup .NET + - name: Setup .NET 6 uses: actions/setup-dotnet@v3 with: dotnet-version: 6.0.x @@ -28,6 +28,11 @@ jobs: uses: actions/setup-dotnet@v3 with: dotnet-version: 7.0.x + + - name: Setup .NET 8 + uses: actions/setup-dotnet@v3 + with: + dotnet-version: 8.0.x - name: Test run: ./build.ps1 test diff --git a/src/Alba.Testing/Acceptance/assertions_against_redirects.cs b/src/Alba.Testing/Acceptance/assertions_against_redirects.cs index ece74df5..b216b685 100644 --- a/src/Alba.Testing/Acceptance/assertions_against_redirects.cs +++ b/src/Alba.Testing/Acceptance/assertions_against_redirects.cs @@ -10,7 +10,7 @@ public class assertions_against_redirects [Fact] public async Task redirect() { - await using var system = AlbaHost.ForStartup(); + await using var system = await AlbaHost.For(); await system.Scenario(_ => { _.Get.Url("/auth/redirect"); @@ -24,15 +24,13 @@ public async Task not_redirected() { var result = await Exception.ShouldBeThrownBy(async () => { - using (var system = AlbaHost.ForStartup()) + await using var system = await AlbaHost.For(); + await system.Scenario(_ => { - await system.Scenario(_ => - { - _.Get.Url("/api/values"); + _.Get.Url("/api/values"); - _.RedirectShouldBe("/else"); - }); - } + _.RedirectShouldBe("/else"); + }); }); result.Message.ShouldContain("Expected to be redirected to '/else' but was ''."); @@ -43,7 +41,7 @@ public async Task redirect_wrong_value() { var result = await Exception.ShouldBeThrownBy(async () => { - await using var system = AlbaHost.ForStartup(); + await using var system = await AlbaHost.For(); await system.Scenario(_ => { _.Get.Url("/auth/redirect"); @@ -58,15 +56,13 @@ await system.Scenario(_ => [Fact] public async Task redirect_permanent() { - using (var system = AlbaHost.ForStartup()) + await using var system = await AlbaHost.For(); + await system.Scenario(_ => { - await system.Scenario(_ => - { - _.Get.Url("/auth/redirectpermanent"); + _.Get.Url("/auth/redirectpermanent"); - _.RedirectPermanentShouldBe("/api/values"); - }); - } + _.RedirectPermanentShouldBe("/api/values"); + }); } [Fact] @@ -74,7 +70,7 @@ public async Task redirect_permanent_wrong_value() { var result = await Exception.ShouldBeThrownBy(async () => { - await using var system = AlbaHost.ForStartup(); + await using var system = await AlbaHost.For(); await system.Scenario(_ => { _.Get.Url("/auth/redirectpermanent"); @@ -91,7 +87,7 @@ public async Task redirect_permanent_non_permanent_result() { var result = await Exception.ShouldBeThrownBy(async () => { - await using var system = AlbaHost.ForStartup(); + await using var system = await AlbaHost.For(); await system.Scenario(_ => { _.Get.Url("/auth/redirect"); diff --git a/src/Alba.Testing/Acceptance/customize_before_each_and_after_each.cs b/src/Alba.Testing/Acceptance/customize_before_each_and_after_each.cs index 0baba1ee..6f23879e 100644 --- a/src/Alba.Testing/Acceptance/customize_before_each_and_after_each.cs +++ b/src/Alba.Testing/Acceptance/customize_before_each_and_after_each.cs @@ -11,13 +11,12 @@ public class customize_before_each_and_after_each [Fact] public async Task before_each_and_after_each_is_called() { - await using var host = AlbaHost - .ForStartup() - .BeforeEach(c => - { - BeforeContext = c; - }) - .AfterEach(c => AfterContext = c); + await using var host = await AlbaHost.For(); + host.BeforeEach(c => + { + BeforeContext = c; + }) + .AfterEach(c => AfterContext = c); BeforeContext = AfterContext = null; diff --git a/src/Alba.Testing/Acceptance/data_binding_in_mvc_app.cs b/src/Alba.Testing/Acceptance/data_binding_in_mvc_app.cs index 043c7b56..baf5791a 100644 --- a/src/Alba.Testing/Acceptance/data_binding_in_mvc_app.cs +++ b/src/Alba.Testing/Acceptance/data_binding_in_mvc_app.cs @@ -13,7 +13,7 @@ public class data_binding_in_mvc_app [Fact] public async Task can_bind_to_form_data() { - await using var system = AlbaHost.ForStartup(); + await using var system = await AlbaHost.For(); var input = new InputModel { One = "one", @@ -40,7 +40,7 @@ await system.Scenario(_ => [Fact] public async Task can_bind_to_form_data_as_dictionary() { - await using var system = AlbaHost.ForStartup(); + await using var system = await AlbaHost.For(); var dict = new Dictionary {{"One", "one"}, {"Two", "two"}, {"Three", "three"}}; diff --git a/src/Alba.Testing/Acceptance/specs_against_aspnet_core_app.cs b/src/Alba.Testing/Acceptance/specs_against_aspnet_core_app.cs index 96f3d65b..e2a65d13 100644 --- a/src/Alba.Testing/Acceptance/specs_against_aspnet_core_app.cs +++ b/src/Alba.Testing/Acceptance/specs_against_aspnet_core_app.cs @@ -13,20 +13,15 @@ namespace Alba.Testing.Acceptance { - public class specs_against_aspnet_core_app : IDisposable + public class specs_against_aspnet_core_app : IAsyncLifetime { - private readonly AlbaHost _system; + private IAlbaHost _system; private Task run(Action configuration) { return _system.Scenario(configuration); } - public specs_against_aspnet_core_app() - { - _system = AlbaHost.ForStartup(); - } - public void Dispose() { _system?.Dispose(); @@ -386,5 +381,15 @@ public Task returns_successfully_when_passed_object_is_passed_to_Input() _.ContentShouldContain("somevalue"); }); } + + public async Task InitializeAsync() + { + _system = await AlbaHost.For(); + } + + public async Task DisposeAsync() + { + await _system.DisposeAsync(); + } } } \ No newline at end of file diff --git a/src/Alba.Testing/Acceptance/using_custom_service_registrations.cs b/src/Alba.Testing/Acceptance/using_custom_service_registrations.cs index 191462db..d2c1dfc3 100644 --- a/src/Alba.Testing/Acceptance/using_custom_service_registrations.cs +++ b/src/Alba.Testing/Acceptance/using_custom_service_registrations.cs @@ -14,36 +14,35 @@ public class using_custom_service_registrations [Fact] public async Task override_service_registration_in_bootstrapping() { - ValuesController.LastWidget = new IWidget[0]; + ValuesController.LastWidget = Array.Empty(); - using (var system = AlbaHost.ForStartup(builder => + using var system = await AlbaHost.For(builder => { - return builder.ConfigureServices((c, _) => + builder.ConfigureServices((c, _) => { _.AddTransient(); }); - })) - { - ValuesController.LastWidget = null; + }); - // The default registration is a GreenWidget + ValuesController.LastWidget = null; - await system.Scenario(_ => - { - - _.Put.Url("/api/values/foo").ContentType("application/json"); - }); + // The default registration is a GreenWidget + + await system.Scenario(_ => + { + + _.Put.Url("/api/values/foo").ContentType("application/json"); + }); - ValuesController.LastWidget.Length.ShouldBe(2); - } + ValuesController.LastWidget.Length.ShouldBe(2); } [Fact] - public void can_request_services() + public async Task can_request_services() { - using var system = AlbaHost.ForStartup(builder => + using var system = await AlbaHost.For(builder => { - return builder.ConfigureServices((c, _) => { _.AddHttpContextAccessor(); }); + builder.ConfigureServices((c, _) => { _.AddHttpContextAccessor(); }); }); var accessor1 = system.Services.GetService(); diff --git a/src/Alba.Testing/Alba.Testing.csproj b/src/Alba.Testing/Alba.Testing.csproj index 357e5141..cbace2b6 100644 --- a/src/Alba.Testing/Alba.Testing.csproj +++ b/src/Alba.Testing/Alba.Testing.csproj @@ -1,4 +1,4 @@ - + net6.0;net8.0 portable @@ -20,8 +20,7 @@ - - + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/Alba.Testing/Assertions/RedirectAssertionTests.cs b/src/Alba.Testing/Assertions/RedirectAssertionTests.cs index e4502a97..25cb7b43 100644 --- a/src/Alba.Testing/Assertions/RedirectAssertionTests.cs +++ b/src/Alba.Testing/Assertions/RedirectAssertionTests.cs @@ -1,6 +1,5 @@ using System.Linq; using Alba.Assertions; -using Baseline; using Shouldly; using Xunit; diff --git a/src/Alba.Testing/CrudeRouter.cs b/src/Alba.Testing/CrudeRouter.cs index 0618c367..b2b411df 100644 --- a/src/Alba.Testing/CrudeRouter.cs +++ b/src/Alba.Testing/CrudeRouter.cs @@ -4,8 +4,8 @@ using System.Linq.Expressions; using System.Reflection; using System.Threading.Tasks; -using Baseline; -using Baseline.Reflection; +using JasperFx.Core; +using JasperFx.Core.Reflection; using Microsoft.AspNetCore.Http; namespace Alba.Testing diff --git a/src/Alba.Testing/FormDataExtensionsTests.cs b/src/Alba.Testing/FormDataExtensionsTests.cs index 70fdd6ca..8b63eacb 100644 --- a/src/Alba.Testing/FormDataExtensionsTests.cs +++ b/src/Alba.Testing/FormDataExtensionsTests.cs @@ -1,7 +1,7 @@ using System.Collections.Generic; using System.IO; using System.Net; -using Baseline; +using JasperFx.Core; using Microsoft.AspNetCore.Http; using Shouldly; using Xunit; diff --git a/src/Alba.Testing/Samples/Quickstart.cs b/src/Alba.Testing/Samples/Quickstart.cs index 19ba5576..06ec93e5 100644 --- a/src/Alba.Testing/Samples/Quickstart.cs +++ b/src/Alba.Testing/Samples/Quickstart.cs @@ -1,7 +1,7 @@ using System; using System.IO; using System.Threading.Tasks; -using Baseline; +using JasperFx.Core; using Microsoft.AspNetCore; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; diff --git a/src/Alba.Testing/SpecificationExtensions.cs b/src/Alba.Testing/SpecificationExtensions.cs index 5b24372e..d574f43f 100644 --- a/src/Alba.Testing/SpecificationExtensions.cs +++ b/src/Alba.Testing/SpecificationExtensions.cs @@ -4,7 +4,7 @@ using System.Diagnostics; using System.Linq; using System.Threading.Tasks; -using Baseline; +using JasperFx.Core; using Shouldly; namespace Alba.Testing diff --git a/src/Alba.Testing/reading_and_writing_xml_to_context.cs b/src/Alba.Testing/reading_and_writing_xml_to_context.cs index 1f4b05f6..257f145d 100644 --- a/src/Alba.Testing/reading_and_writing_xml_to_context.cs +++ b/src/Alba.Testing/reading_and_writing_xml_to_context.cs @@ -1,7 +1,7 @@ using System.IO; using System.Xml; using System.Xml.Serialization; -using Baseline; +using JasperFx.Core; using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Http; diff --git a/src/Alba/Alba.csproj b/src/Alba/Alba.csproj index 3afec04d..b4e826cc 100644 --- a/src/Alba/Alba.csproj +++ b/src/Alba/Alba.csproj @@ -3,7 +3,7 @@ Supercharged integration testing for ASP.NET Core HTTP endpoints Alba - 8.0.0-rc.1 + 8.0.0 net6.0;net7.0;net8.0 Alba Alba diff --git a/src/Alba/Scenario.cs b/src/Alba/Scenario.cs index f6fe5f3d..201159b9 100644 --- a/src/Alba/Scenario.cs +++ b/src/Alba/Scenario.cs @@ -21,8 +21,8 @@ public class Scenario : IUrlExpression { private readonly ScenarioAssertionException _assertionRecords = new(); - private readonly IList _assertions = new List(); - private readonly IList> _setups = new List>(); + private readonly List _assertions = new(); + private readonly List> _setups = new(); private readonly AlbaHost _system; private int _expectedStatusCode = 200; private bool _ignoreStatusCode; @@ -130,7 +130,7 @@ SendExpression IUrlExpression.Url([StringSyntax(StringSyntaxAttribute.Uri)]strin return new SendExpression(this); } - SendExpression IUrlExpression.Json(T input, JsonStyle? jsonStyle = null) + SendExpression IUrlExpression.Json(T input, JsonStyle? jsonStyle) { WriteJson(input, jsonStyle); @@ -247,7 +247,7 @@ public void WriteJson(T input, JsonStyle? jsonStyle) ConfigureHttpContext(c => { - var stream = jsonStrategy.Write(input); + var stream = jsonStrategy!.Write(input); c.Request.ContentType = "application/json"; c.Request.Body = stream; diff --git a/src/Alba/Security/TestAuthHandler.cs b/src/Alba/Security/TestAuthHandler.cs index fd87add3..ca037cf2 100644 --- a/src/Alba/Security/TestAuthHandler.cs +++ b/src/Alba/Security/TestAuthHandler.cs @@ -13,6 +13,8 @@ internal class TestAuthHandler : AuthenticationHandler options, ILoggerFactory logger, UrlEncoder encoder, ISystemClock clock) : base(options, logger, encoder, clock) @@ -21,6 +23,14 @@ public TestAuthHandler(IHttpContextAccessor accessor, AuthenticationStub parent, _parent = parent; } +#else + public TestAuthHandler(IHttpContextAccessor accessor, AuthenticationStub parent, IOptionsMonitor options, ILoggerFactory logger, UrlEncoder encoder) : base(options, logger, encoder) + { + _context = accessor.HttpContext ?? throw new InvalidOperationException("HttpContext is missing"); + + _parent = parent; + } +#endif protected override Task HandleAuthenticateAsync() { diff --git a/src/MinimalApiWithOakton/MinimalApiWithOakton.csproj b/src/MinimalApiWithOakton/MinimalApiWithOakton.csproj index ab410677..9bbdf054 100644 --- a/src/MinimalApiWithOakton/MinimalApiWithOakton.csproj +++ b/src/MinimalApiWithOakton/MinimalApiWithOakton.csproj @@ -1,13 +1,13 @@  - net6.0;net7.0 + net6.0;net8.0 enable enable - + diff --git a/src/WebApp/Controllers/FilesController.cs b/src/WebApp/Controllers/FilesController.cs index 1a55dbae..94e66d4e 100644 --- a/src/WebApp/Controllers/FilesController.cs +++ b/src/WebApp/Controllers/FilesController.cs @@ -4,7 +4,6 @@ using System.Net.Mime; using System.Text; using System.Threading.Tasks; -using Baseline; using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Mvc; diff --git a/src/WebApp/Controllers/JsonController.cs b/src/WebApp/Controllers/JsonController.cs index 4c140c5a..644c4814 100644 --- a/src/WebApp/Controllers/JsonController.cs +++ b/src/WebApp/Controllers/JsonController.cs @@ -2,7 +2,7 @@ using System.IO; using System.Linq; using System.Threading.Tasks; -using Baseline; +using JasperFx.Core; using Microsoft.AspNetCore.Mvc; using Microsoft.AspNetCore.Mvc.Formatters; using Newtonsoft.Json; diff --git a/src/WebApp/Controllers/QueryStringContoller.cs b/src/WebApp/Controllers/QueryStringContoller.cs index 468ce4ae..68582bb6 100644 --- a/src/WebApp/Controllers/QueryStringContoller.cs +++ b/src/WebApp/Controllers/QueryStringContoller.cs @@ -1,5 +1,5 @@ using System.Linq; -using Baseline; +using JasperFx.Core; using Microsoft.AspNetCore.Mvc; namespace WebApp.Controllers diff --git a/src/WebApp/WebApp.csproj b/src/WebApp/WebApp.csproj index 195ee0b1..8c13c863 100644 --- a/src/WebApp/WebApp.csproj +++ b/src/WebApp/WebApp.csproj @@ -9,8 +9,8 @@ - + From 65cf9c8ca7224316231dc08bc4cc8067bd1d61c0 Mon Sep 17 00:00:00 2001 From: JT Date: Sat, 20 Jan 2024 23:20:00 +0800 Subject: [PATCH 3/6] More dependency updates --- src/Alba.Testing/Alba.Testing.csproj | 10 +++++----- src/MinimalApiWithOakton/MinimalApiWithOakton.csproj | 2 +- src/NUnitSamples/NUnitSamples.csproj | 10 +++------- src/NUnitSamples/UnitTest1.cs | 3 --- src/WebAppSecuredWithJwt/WebAppSecuredWithJwt.csproj | 2 +- 5 files changed, 10 insertions(+), 17 deletions(-) diff --git a/src/Alba.Testing/Alba.Testing.csproj b/src/Alba.Testing/Alba.Testing.csproj index cbace2b6..e84b82fc 100644 --- a/src/Alba.Testing/Alba.Testing.csproj +++ b/src/Alba.Testing/Alba.Testing.csproj @@ -17,11 +17,11 @@ - - - - - + + + + + all runtime; build; native; contentfiles; analyzers; buildtransitive diff --git a/src/MinimalApiWithOakton/MinimalApiWithOakton.csproj b/src/MinimalApiWithOakton/MinimalApiWithOakton.csproj index 9bbdf054..f644da1b 100644 --- a/src/MinimalApiWithOakton/MinimalApiWithOakton.csproj +++ b/src/MinimalApiWithOakton/MinimalApiWithOakton.csproj @@ -7,7 +7,7 @@ - + diff --git a/src/NUnitSamples/NUnitSamples.csproj b/src/NUnitSamples/NUnitSamples.csproj index 36dbffda..472124b6 100644 --- a/src/NUnitSamples/NUnitSamples.csproj +++ b/src/NUnitSamples/NUnitSamples.csproj @@ -7,13 +7,9 @@ - - - - - all - runtime; build; native; contentfiles; analyzers; buildtransitive - + + + diff --git a/src/NUnitSamples/UnitTest1.cs b/src/NUnitSamples/UnitTest1.cs index 13253c72..f4be29dd 100644 --- a/src/NUnitSamples/UnitTest1.cs +++ b/src/NUnitSamples/UnitTest1.cs @@ -1,9 +1,6 @@ -using System; -using System.Buffers; using System.Threading.Tasks; using Alba; using NUnit.Framework; -using WebApp; namespace NUnitSamples { diff --git a/src/WebAppSecuredWithJwt/WebAppSecuredWithJwt.csproj b/src/WebAppSecuredWithJwt/WebAppSecuredWithJwt.csproj index 2a48bef6..aecb40a7 100644 --- a/src/WebAppSecuredWithJwt/WebAppSecuredWithJwt.csproj +++ b/src/WebAppSecuredWithJwt/WebAppSecuredWithJwt.csproj @@ -6,7 +6,7 @@ - + From 690c440da6c26878cd8b1afd9c9711b97f7d926c Mon Sep 17 00:00:00 2001 From: JT Date: Sat, 20 Jan 2024 23:21:46 +0800 Subject: [PATCH 4/6] Adjust docs --- docs/guide/nunit.md | 4 ++-- docs/scenarios/formdata.md | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/guide/nunit.md b/docs/guide/nunit.md index 5b211737..e966d332 100644 --- a/docs/guide/nunit.md +++ b/docs/guide/nunit.md @@ -27,7 +27,7 @@ public class Application } } ``` -snippet source | anchor +snippet source | anchor Then reference the `AlbaHost` in tests like this sample: @@ -48,5 +48,5 @@ public class sample_integration_fixture } } ``` -snippet source | anchor +snippet source | anchor diff --git a/docs/scenarios/formdata.md b/docs/scenarios/formdata.md index 8efd6485..2d710a13 100644 --- a/docs/scenarios/formdata.md +++ b/docs/scenarios/formdata.md @@ -36,7 +36,7 @@ There's a second overload that attempts to use an object and its properties to p [Fact] public async Task can_bind_to_form_data() { - await using var system = AlbaHost.ForStartup(); + await using var system = await AlbaHost.For(); var input = new InputModel { One = "one", From 11b87052fbc6447d08fb09de47f4cee12c02261d Mon Sep 17 00:00:00 2001 From: JT Date: Sat, 20 Jan 2024 23:15:44 +0800 Subject: [PATCH 5/6] Update IdentityServer --- src/Alba.Testing/Alba.Testing.csproj | 2 +- .../Security/IdentityServerFixture.cs | 2 +- .../OpenConnectClientCredentialsTests.cs | 2 +- .../Security/OpenConnectUserPasswordTests.cs | 2 +- src/Alba.sln | 14 +- src/IdentityServer.New/Config.cs | 41 + src/IdentityServer.New/HostingExtensions.cs | 55 + .../IdentityServer.New.csproj | 13 + .../Pages/Account/AccessDenied.cshtml | 10 + .../Pages/Account/AccessDenied.cshtml.cs | 11 + .../Pages/Account/Create/Index.cshtml | 40 + .../Pages/Account/Create/Index.cshtml.cs | 121 + .../Pages/Account/Create/InputModel.cs | 24 + .../Pages/Account/Login/Index.cshtml} | 40 +- .../Pages/Account/Login/Index.cshtml.cs | 223 + .../Pages/Account/Login/InputModel.cs} | 9 +- .../Pages/Account/Login/LoginOptions.cs | 10 + .../Pages/Account/Login/ViewModel.cs | 23 + .../Pages/Account/Logout/Index.cshtml} | 8 +- .../Pages/Account/Logout/Index.cshtml.cs | 97 + .../Pages/Account/Logout/LoggedOut.cshtml | 30 + .../Pages/Account/Logout/LoggedOut.cshtml.cs | 34 + .../Account/Logout}/LoggedOutViewModel.cs | 8 +- .../Pages/Account/Logout/LogoutOptions.cs | 9 + src/IdentityServer.New/Pages/Ciba/All.cshtml | 48 + .../Pages/Ciba/All.cshtml.cs | 36 + .../Pages/Ciba/Consent.cshtml} | 58 +- .../Pages/Ciba/Consent.cshtml.cs | 219 + .../Pages/Ciba}/ConsentOptions.cs | 4 +- .../Pages/Ciba/Index.cshtml | 30 + .../Pages/Ciba/Index.cshtml.cs | 39 + .../Pages/Ciba/InputModel.cs | 13 + .../Pages/Ciba/ViewModel.cs | 35 + .../Pages/Ciba/_ScopeListItem.cshtml | 47 + .../Pages/Consent/ConsentOptions.cs | 16 + .../Pages}/Consent/Index.cshtml | 43 +- .../Pages/Consent/Index.cshtml.cs} | 167 +- .../Pages/Consent/InputModel.cs} | 9 +- .../Pages/Consent/ViewModel.cs | 34 + .../Pages/Consent/_ScopeListItem.cshtml | 47 + .../Pages/Device/DeviceOptions.cs | 17 + .../Pages/Device/Index.cshtml | 141 + .../Pages/Device/Index.cshtml.cs} | 145 +- .../Pages/Device/InputModel.cs | 12 + .../Pages}/Device/Success.cshtml | 5 + .../Pages/Device/Success.cshtml.cs | 14 + .../Pages/Device/ViewModel.cs | 23 + .../Pages/Device}/_ScopeListItem.cshtml | 5 +- .../Pages}/Diagnostics/Index.cshtml | 31 +- .../Pages/Diagnostics/Index.cshtml.cs} | 20 +- .../Pages/Diagnostics/ViewModel.cs} | 7 +- src/IdentityServer.New/Pages/Extensions.cs | 44 + .../Pages/ExternalLogin/Callback.cshtml | 19 + .../Pages/ExternalLogin/Callback.cshtml.cs} | 135 +- .../Pages/ExternalLogin/Challenge.cshtml | 19 + .../Pages/ExternalLogin/Challenge.cshtml.cs | 46 + .../Pages}/Grants/Index.cshtml | 11 +- .../Pages/Grants/Index.cshtml.cs} | 60 +- .../Pages/Grants/ViewModel.cs} | 11 +- .../Pages/Home/Error/Index.cshtml} | 21 +- .../Pages/Home/Error/Index.cshtml.cs | 40 + .../Pages/Home/Error/ViewModel.cs} | 11 +- .../Pages}/Index.cshtml | 15 +- src/IdentityServer.New/Pages/Index.cshtml.cs | 17 + .../Pages/Redirect/Index.cshtml} | 7 +- .../Pages/Redirect/Index.cshtml.cs | 23 + .../Pages}/SecurityHeadersAttribute.cs | 8 +- .../Pages/ServerSideSessions/Index.cshtml | 147 + .../Pages/ServerSideSessions/Index.cshtml.cs | 62 + .../Pages}/Shared/_Layout.cshtml | 1 + .../Pages}/Shared/_Nav.cshtml | 2 +- .../Pages}/Shared/_ValidationSummary.cshtml | 2 +- .../Pages}/TestUsers.cs | 13 +- .../Pages}/_ViewImports.cshtml | 2 +- .../Pages}/_ViewStart.cshtml | 2 +- src/IdentityServer.New/Program.cs | 44 + .../Properties/launchSettings.json | 12 + src/IdentityServer.New/wwwroot/css/site.css | 39 + .../wwwroot/css/site.min.css | 1 + src/IdentityServer.New/wwwroot/css/site.scss | 50 + .../wwwroot/duende-logo.svg | 0 .../wwwroot/favicon.ico | Bin .../wwwroot/js/signin-redirect.js | 0 .../wwwroot/js/signout-redirect.js | 2 +- .../wwwroot/lib/bootstrap/LICENSE | 0 .../wwwroot/lib/bootstrap/README.md | 0 .../lib/bootstrap/dist/css/bootstrap-grid.css | 0 .../bootstrap/dist/css/bootstrap-grid.css.map | 0 .../bootstrap/dist/css/bootstrap-grid.min.css | 0 .../dist/css/bootstrap-grid.min.css.map | 0 .../bootstrap/dist/css/bootstrap-reboot.css | 0 .../dist/css/bootstrap-reboot.css.map | 0 .../dist/css/bootstrap-reboot.min.css | 0 .../dist/css/bootstrap-reboot.min.css.map | 0 .../lib/bootstrap/dist/css/bootstrap.css | 0 .../lib/bootstrap/dist/css/bootstrap.css.map | 0 .../lib/bootstrap/dist/css/bootstrap.min.css | 0 .../bootstrap/dist/css/bootstrap.min.css.map | 0 .../lib/bootstrap/dist/js/bootstrap.bundle.js | 0 .../bootstrap/dist/js/bootstrap.bundle.js.map | 0 .../bootstrap/dist/js/bootstrap.bundle.min.js | 0 .../dist/js/bootstrap.bundle.min.js.map | 0 .../lib/bootstrap/dist/js/bootstrap.js | 0 .../lib/bootstrap/dist/js/bootstrap.js.map | 0 .../lib/bootstrap/dist/js/bootstrap.min.js | 0 .../bootstrap/dist/js/bootstrap.min.js.map | 0 .../wwwroot/lib/bootstrap4-glyphicons/LICENSE | 201 + .../css/bootstrap-glyphicons.css | 809 ++++ .../css/bootstrap-glyphicons.min.css | 6 + .../glyphicons-halflings-regular.eot | Bin 0 -> 20127 bytes .../glyphicons-halflings-regular.svg | 288 ++ .../glyphicons-halflings-regular.ttf | Bin 0 -> 45404 bytes .../glyphicons-halflings-regular.woff | Bin 0 -> 23424 bytes .../glyphicons-halflings-regular.woff2 | Bin 0 -> 18028 bytes .../maps/glyphicons-fontawesome.css | 2947 +++++++++++++ .../maps/glyphicons-fontawesome.less | 3891 +++++++++++++++++ .../maps/glyphicons-fontawesome.min.css | 1 + .../wwwroot/lib/jquery/LICENSE.txt | 0 .../wwwroot/lib/jquery/README.md | 0 .../wwwroot/lib/jquery/dist/jquery.js | 0 .../wwwroot/lib/jquery/dist/jquery.min.js | 0 .../wwwroot/lib/jquery/dist/jquery.min.map | 0 .../wwwroot/lib/jquery/dist/jquery.slim.js | 0 .../lib/jquery/dist/jquery.slim.min.js | 0 .../lib/jquery/dist/jquery.slim.min.map | 0 src/IdentityServer/Config.cs | 56 - src/IdentityServer/IdentityServer.csproj | 12 - src/IdentityServer/Program.cs | 27 - .../Properties/launchSettings.json | 28 - .../Quickstart/Account/AccountController.cs | 368 -- .../Quickstart/Account/AccountOptions.cs | 20 - .../Quickstart/Account/ExternalProvider.cs | 12 - .../Quickstart/Account/LoginViewModel.cs | 22 - .../Quickstart/Account/LogoutInputModel.cs | 11 - .../Quickstart/Account/LogoutViewModel.cs | 11 - .../Quickstart/Account/RedirectViewModel.cs | 12 - .../Quickstart/Consent/ConsentViewModel.cs | 19 - .../Consent/ProcessConsentResult.cs | 21 - .../Quickstart/Consent/ScopeViewModel.cs | 16 - .../Device/DeviceAuthorizationInputModel.cs | 11 - .../Device/DeviceAuthorizationViewModel.cs | 12 - src/IdentityServer/Quickstart/Extensions.cs | 31 - .../Quickstart/Home/HomeController.cs | 65 - src/IdentityServer/Startup.cs | 60 - .../Views/Account/AccessDenied.cshtml | 7 - .../Views/Account/LoggedOut.cshtml | 34 - .../Views/Device/UserCodeCapture.cshtml | 23 - .../appsettings.Development.json | 9 - src/IdentityServer/appsettings.json | 10 - ...-key-4651951E0D4226E5AD402EAEA2496564.json | 1 - src/IdentityServer/wwwroot/css/site.css | 30 - src/IdentityServer/wwwroot/css/site.min.css | 1 - src/IdentityServer/wwwroot/css/site.scss | 51 - 153 files changed, 10590 insertions(+), 1492 deletions(-) create mode 100644 src/IdentityServer.New/Config.cs create mode 100644 src/IdentityServer.New/HostingExtensions.cs create mode 100644 src/IdentityServer.New/IdentityServer.New.csproj create mode 100644 src/IdentityServer.New/Pages/Account/AccessDenied.cshtml create mode 100644 src/IdentityServer.New/Pages/Account/AccessDenied.cshtml.cs create mode 100644 src/IdentityServer.New/Pages/Account/Create/Index.cshtml create mode 100644 src/IdentityServer.New/Pages/Account/Create/Index.cshtml.cs create mode 100644 src/IdentityServer.New/Pages/Account/Create/InputModel.cs rename src/{IdentityServer/Views/Account/Login.cshtml => IdentityServer.New/Pages/Account/Login/Index.cshtml} (66%) create mode 100644 src/IdentityServer.New/Pages/Account/Login/Index.cshtml.cs rename src/{IdentityServer/Quickstart/Account/LoginInputModel.cs => IdentityServer.New/Pages/Account/Login/InputModel.cs} (77%) create mode 100644 src/IdentityServer.New/Pages/Account/Login/LoginOptions.cs create mode 100644 src/IdentityServer.New/Pages/Account/Login/ViewModel.cs rename src/{IdentityServer/Views/Account/Logout.cshtml => IdentityServer.New/Pages/Account/Logout/Index.cshtml} (75%) create mode 100644 src/IdentityServer.New/Pages/Account/Logout/Index.cshtml.cs create mode 100644 src/IdentityServer.New/Pages/Account/Logout/LoggedOut.cshtml create mode 100644 src/IdentityServer.New/Pages/Account/Logout/LoggedOut.cshtml.cs rename src/{IdentityServer/Quickstart/Account => IdentityServer.New/Pages/Account/Logout}/LoggedOutViewModel.cs (62%) create mode 100644 src/IdentityServer.New/Pages/Account/Logout/LogoutOptions.cs create mode 100644 src/IdentityServer.New/Pages/Ciba/All.cshtml create mode 100644 src/IdentityServer.New/Pages/Ciba/All.cshtml.cs rename src/{IdentityServer/Views/Device/UserCodeConfirmation.cshtml => IdentityServer.New/Pages/Ciba/Consent.cshtml} (59%) create mode 100644 src/IdentityServer.New/Pages/Ciba/Consent.cshtml.cs rename src/{IdentityServer/Quickstart/Consent => IdentityServer.New/Pages/Ciba}/ConsentOptions.cs (93%) create mode 100644 src/IdentityServer.New/Pages/Ciba/Index.cshtml create mode 100644 src/IdentityServer.New/Pages/Ciba/Index.cshtml.cs create mode 100644 src/IdentityServer.New/Pages/Ciba/InputModel.cs create mode 100644 src/IdentityServer.New/Pages/Ciba/ViewModel.cs create mode 100644 src/IdentityServer.New/Pages/Ciba/_ScopeListItem.cshtml create mode 100644 src/IdentityServer.New/Pages/Consent/ConsentOptions.cs rename src/{IdentityServer/Views => IdentityServer.New/Pages}/Consent/Index.cshtml (71%) rename src/{IdentityServer/Quickstart/Consent/ConsentController.cs => IdentityServer.New/Pages/Consent/Index.cshtml.cs} (58%) rename src/{IdentityServer/Quickstart/Consent/ConsentInputModel.cs => IdentityServer.New/Pages/Consent/InputModel.cs} (67%) create mode 100644 src/IdentityServer.New/Pages/Consent/ViewModel.cs create mode 100644 src/IdentityServer.New/Pages/Consent/_ScopeListItem.cshtml create mode 100644 src/IdentityServer.New/Pages/Device/DeviceOptions.cs create mode 100644 src/IdentityServer.New/Pages/Device/Index.cshtml rename src/{IdentityServer/Quickstart/Device/DeviceController.cs => IdentityServer.New/Pages/Device/Index.cshtml.cs} (55%) create mode 100644 src/IdentityServer.New/Pages/Device/InputModel.cs rename src/{IdentityServer/Views => IdentityServer.New/Pages}/Device/Success.cshtml (71%) create mode 100644 src/IdentityServer.New/Pages/Device/Success.cshtml.cs create mode 100644 src/IdentityServer.New/Pages/Device/ViewModel.cs rename src/{IdentityServer/Views/Shared => IdentityServer.New/Pages/Device}/_ScopeListItem.cshtml (86%) rename src/{IdentityServer/Views => IdentityServer.New/Pages}/Diagnostics/Index.cshtml (63%) rename src/{IdentityServer/Quickstart/Diagnostics/DiagnosticsController.cs => IdentityServer.New/Pages/Diagnostics/Index.cshtml.cs} (52%) rename src/{IdentityServer/Quickstart/Diagnostics/DiagnosticsViewModel.cs => IdentityServer.New/Pages/Diagnostics/ViewModel.cs} (81%) create mode 100644 src/IdentityServer.New/Pages/Extensions.cs create mode 100644 src/IdentityServer.New/Pages/ExternalLogin/Callback.cshtml rename src/{IdentityServer/Quickstart/Account/ExternalController.cs => IdentityServer.New/Pages/ExternalLogin/Callback.cshtml.cs} (60%) create mode 100644 src/IdentityServer.New/Pages/ExternalLogin/Challenge.cshtml create mode 100644 src/IdentityServer.New/Pages/ExternalLogin/Challenge.cshtml.cs rename src/{IdentityServer/Views => IdentityServer.New/Pages}/Grants/Index.cshtml (93%) rename src/{IdentityServer/Quickstart/Grants/GrantsController.cs => IdentityServer.New/Pages/Grants/Index.cshtml.cs} (63%) rename src/{IdentityServer/Quickstart/Grants/GrantsViewModel.cs => IdentityServer.New/Pages/Grants/ViewModel.cs} (70%) rename src/{IdentityServer/Views/Shared/Error.cshtml => IdentityServer.New/Pages/Home/Error/Index.cshtml} (53%) create mode 100644 src/IdentityServer.New/Pages/Home/Error/Index.cshtml.cs rename src/{IdentityServer/Quickstart/Home/ErrorViewModel.cs => IdentityServer.New/Pages/Home/Error/ViewModel.cs} (55%) rename src/{IdentityServer/Views/Home => IdentityServer.New/Pages}/Index.cshtml (71%) create mode 100644 src/IdentityServer.New/Pages/Index.cshtml.cs rename src/{IdentityServer/Views/Shared/Redirect.cshtml => IdentityServer.New/Pages/Redirect/Index.cshtml} (60%) create mode 100644 src/IdentityServer.New/Pages/Redirect/Index.cshtml.cs rename src/{IdentityServer/Quickstart => IdentityServer.New/Pages}/SecurityHeadersAttribute.cs (95%) create mode 100644 src/IdentityServer.New/Pages/ServerSideSessions/Index.cshtml create mode 100644 src/IdentityServer.New/Pages/ServerSideSessions/Index.cshtml.cs rename src/{IdentityServer/Views => IdentityServer.New/Pages}/Shared/_Layout.cshtml (89%) rename src/{IdentityServer/Views => IdentityServer.New/Pages}/Shared/_Nav.cshtml (88%) rename src/{IdentityServer/Views => IdentityServer.New/Pages}/Shared/_ValidationSummary.cshtml (74%) rename src/{IdentityServer/Quickstart => IdentityServer.New/Pages}/TestUsers.cs (92%) rename src/{IdentityServer/Views => IdentityServer.New/Pages}/_ViewImports.cshtml (56%) rename src/{IdentityServer/Views => IdentityServer.New/Pages}/_ViewStart.cshtml (81%) create mode 100644 src/IdentityServer.New/Program.cs create mode 100644 src/IdentityServer.New/Properties/launchSettings.json create mode 100644 src/IdentityServer.New/wwwroot/css/site.css create mode 100644 src/IdentityServer.New/wwwroot/css/site.min.css create mode 100644 src/IdentityServer.New/wwwroot/css/site.scss rename src/{IdentityServer => IdentityServer.New}/wwwroot/duende-logo.svg (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/favicon.ico (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/js/signin-redirect.js (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/js/signout-redirect.js (71%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/bootstrap/LICENSE (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/bootstrap/README.md (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.css.map (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/bootstrap/dist/css/bootstrap-grid.min.css.map (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.css.map (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/bootstrap/dist/css/bootstrap-reboot.min.css.map (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/bootstrap/dist/css/bootstrap.css (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/bootstrap/dist/css/bootstrap.css.map (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/bootstrap/dist/css/bootstrap.min.css.map (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.js.map (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/bootstrap/dist/js/bootstrap.bundle.min.js.map (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/bootstrap/dist/js/bootstrap.js (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/bootstrap/dist/js/bootstrap.js.map (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/bootstrap/dist/js/bootstrap.min.js.map (100%) create mode 100644 src/IdentityServer.New/wwwroot/lib/bootstrap4-glyphicons/LICENSE create mode 100644 src/IdentityServer.New/wwwroot/lib/bootstrap4-glyphicons/css/bootstrap-glyphicons.css create mode 100644 src/IdentityServer.New/wwwroot/lib/bootstrap4-glyphicons/css/bootstrap-glyphicons.min.css create mode 100644 src/IdentityServer.New/wwwroot/lib/bootstrap4-glyphicons/fonts/glyphicons/glyphicons-halflings-regular.eot create mode 100644 src/IdentityServer.New/wwwroot/lib/bootstrap4-glyphicons/fonts/glyphicons/glyphicons-halflings-regular.svg create mode 100644 src/IdentityServer.New/wwwroot/lib/bootstrap4-glyphicons/fonts/glyphicons/glyphicons-halflings-regular.ttf create mode 100644 src/IdentityServer.New/wwwroot/lib/bootstrap4-glyphicons/fonts/glyphicons/glyphicons-halflings-regular.woff create mode 100644 src/IdentityServer.New/wwwroot/lib/bootstrap4-glyphicons/fonts/glyphicons/glyphicons-halflings-regular.woff2 create mode 100644 src/IdentityServer.New/wwwroot/lib/bootstrap4-glyphicons/maps/glyphicons-fontawesome.css create mode 100644 src/IdentityServer.New/wwwroot/lib/bootstrap4-glyphicons/maps/glyphicons-fontawesome.less create mode 100644 src/IdentityServer.New/wwwroot/lib/bootstrap4-glyphicons/maps/glyphicons-fontawesome.min.css rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/jquery/LICENSE.txt (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/jquery/README.md (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/jquery/dist/jquery.js (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/jquery/dist/jquery.min.js (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/jquery/dist/jquery.min.map (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/jquery/dist/jquery.slim.js (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/jquery/dist/jquery.slim.min.js (100%) rename src/{IdentityServer => IdentityServer.New}/wwwroot/lib/jquery/dist/jquery.slim.min.map (100%) delete mode 100644 src/IdentityServer/Config.cs delete mode 100644 src/IdentityServer/IdentityServer.csproj delete mode 100644 src/IdentityServer/Program.cs delete mode 100644 src/IdentityServer/Properties/launchSettings.json delete mode 100644 src/IdentityServer/Quickstart/Account/AccountController.cs delete mode 100644 src/IdentityServer/Quickstart/Account/AccountOptions.cs delete mode 100644 src/IdentityServer/Quickstart/Account/ExternalProvider.cs delete mode 100644 src/IdentityServer/Quickstart/Account/LoginViewModel.cs delete mode 100644 src/IdentityServer/Quickstart/Account/LogoutInputModel.cs delete mode 100644 src/IdentityServer/Quickstart/Account/LogoutViewModel.cs delete mode 100644 src/IdentityServer/Quickstart/Account/RedirectViewModel.cs delete mode 100644 src/IdentityServer/Quickstart/Consent/ConsentViewModel.cs delete mode 100644 src/IdentityServer/Quickstart/Consent/ProcessConsentResult.cs delete mode 100644 src/IdentityServer/Quickstart/Consent/ScopeViewModel.cs delete mode 100644 src/IdentityServer/Quickstart/Device/DeviceAuthorizationInputModel.cs delete mode 100644 src/IdentityServer/Quickstart/Device/DeviceAuthorizationViewModel.cs delete mode 100644 src/IdentityServer/Quickstart/Extensions.cs delete mode 100644 src/IdentityServer/Quickstart/Home/HomeController.cs delete mode 100644 src/IdentityServer/Startup.cs delete mode 100644 src/IdentityServer/Views/Account/AccessDenied.cshtml delete mode 100644 src/IdentityServer/Views/Account/LoggedOut.cshtml delete mode 100644 src/IdentityServer/Views/Device/UserCodeCapture.cshtml delete mode 100644 src/IdentityServer/appsettings.Development.json delete mode 100644 src/IdentityServer/appsettings.json delete mode 100644 src/IdentityServer/keys/is-signing-key-4651951E0D4226E5AD402EAEA2496564.json delete mode 100644 src/IdentityServer/wwwroot/css/site.css delete mode 100644 src/IdentityServer/wwwroot/css/site.min.css delete mode 100644 src/IdentityServer/wwwroot/css/site.scss diff --git a/src/Alba.Testing/Alba.Testing.csproj b/src/Alba.Testing/Alba.Testing.csproj index e84b82fc..a6fe8c98 100644 --- a/src/Alba.Testing/Alba.Testing.csproj +++ b/src/Alba.Testing/Alba.Testing.csproj @@ -8,7 +8,7 @@ - + diff --git a/src/Alba.Testing/Security/IdentityServerFixture.cs b/src/Alba.Testing/Security/IdentityServerFixture.cs index ea8cfc50..aa933197 100644 --- a/src/Alba.Testing/Security/IdentityServerFixture.cs +++ b/src/Alba.Testing/Security/IdentityServerFixture.cs @@ -20,7 +20,7 @@ public class IdentityServerFixture : IAsyncLifetime public TestServer IdentityServer { get; set; } public Task InitializeAsync() { - IdentityServer = new WebApplicationFactory().Server; + IdentityServer = new WebApplicationFactory().Server; return Task.CompletedTask; } diff --git a/src/Alba.Testing/Security/OpenConnectClientCredentialsTests.cs b/src/Alba.Testing/Security/OpenConnectClientCredentialsTests.cs index 84f588ca..5ec01f14 100644 --- a/src/Alba.Testing/Security/OpenConnectClientCredentialsTests.cs +++ b/src/Alba.Testing/Security/OpenConnectClientCredentialsTests.cs @@ -1,7 +1,7 @@ using System; using System.Threading.Tasks; using Alba.Security; -using IdentityServer; +using IdentityServer.New; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.Extensions.DependencyInjection; using Shouldly; diff --git a/src/Alba.Testing/Security/OpenConnectUserPasswordTests.cs b/src/Alba.Testing/Security/OpenConnectUserPasswordTests.cs index 73593d92..d218325e 100644 --- a/src/Alba.Testing/Security/OpenConnectUserPasswordTests.cs +++ b/src/Alba.Testing/Security/OpenConnectUserPasswordTests.cs @@ -1,7 +1,7 @@ using System; using System.Threading.Tasks; using Alba.Security; -using IdentityServer; +using IdentityServer.New; using Microsoft.AspNetCore.Authentication.JwtBearer; using Microsoft.Extensions.DependencyInjection; using Shouldly; diff --git a/src/Alba.sln b/src/Alba.sln index 4c9216e2..bc012264 100644 --- a/src/Alba.sln +++ b/src/Alba.sln @@ -12,20 +12,22 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebApiStartupHostingModel", EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebAppSecuredWithJwt", "WebAppSecuredWithJwt\WebAppSecuredWithJwt.csproj", "{91CA83AA-73DB-44B0-8A5D-5BB38532B897}" EndProject -Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "IdentityServer", "IdentityServer\IdentityServer.csproj", "{0E04B4E3-8183-4516-A1E2-768C425C98FE}" -EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "NUnitSamples", "NUnitSamples\NUnitSamples.csproj", "{EAE558C3-9759-4F7F-845B-D00056EE65DC}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WebApiNet6", "WebApiNet6\WebApiNet6.csproj", "{C2D01782-E9BC-4E61-A4B7-76FA48292386}" EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MinimalApiWithOakton", "MinimalApiWithOakton\MinimalApiWithOakton.csproj", "{2BD68525-60F2-4253-BFA7-12476F374EE9}" EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "IdentityServer.New", "IdentityServer.New\IdentityServer.New.csproj", "{B7AB5313-B55C-4AFF-940B-F17DC913AFB6}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Any CPU = Debug|Any CPU Release|Any CPU = Release|Any CPU EndGlobalSection GlobalSection(ProjectConfigurationPlatforms) = postSolution + {7509E7DF-DB3D-49A9-B3DA-862998D9F435}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {7509E7DF-DB3D-49A9-B3DA-862998D9F435}.Release|Any CPU.ActiveCfg = Release|Any CPU {81D9EFA5-F846-40F3-B36C-8E82111EDDF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {81D9EFA5-F846-40F3-B36C-8E82111EDDF6}.Debug|Any CPU.Build.0 = Debug|Any CPU {81D9EFA5-F846-40F3-B36C-8E82111EDDF6}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -46,10 +48,6 @@ Global {91CA83AA-73DB-44B0-8A5D-5BB38532B897}.Debug|Any CPU.Build.0 = Debug|Any CPU {91CA83AA-73DB-44B0-8A5D-5BB38532B897}.Release|Any CPU.ActiveCfg = Release|Any CPU {91CA83AA-73DB-44B0-8A5D-5BB38532B897}.Release|Any CPU.Build.0 = Release|Any CPU - {0E04B4E3-8183-4516-A1E2-768C425C98FE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {0E04B4E3-8183-4516-A1E2-768C425C98FE}.Debug|Any CPU.Build.0 = Debug|Any CPU - {0E04B4E3-8183-4516-A1E2-768C425C98FE}.Release|Any CPU.ActiveCfg = Release|Any CPU - {0E04B4E3-8183-4516-A1E2-768C425C98FE}.Release|Any CPU.Build.0 = Release|Any CPU {EAE558C3-9759-4F7F-845B-D00056EE65DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU {EAE558C3-9759-4F7F-845B-D00056EE65DC}.Debug|Any CPU.Build.0 = Debug|Any CPU {EAE558C3-9759-4F7F-845B-D00056EE65DC}.Release|Any CPU.ActiveCfg = Release|Any CPU @@ -62,6 +60,10 @@ Global {2BD68525-60F2-4253-BFA7-12476F374EE9}.Debug|Any CPU.Build.0 = Debug|Any CPU {2BD68525-60F2-4253-BFA7-12476F374EE9}.Release|Any CPU.ActiveCfg = Release|Any CPU {2BD68525-60F2-4253-BFA7-12476F374EE9}.Release|Any CPU.Build.0 = Release|Any CPU + {B7AB5313-B55C-4AFF-940B-F17DC913AFB6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {B7AB5313-B55C-4AFF-940B-F17DC913AFB6}.Debug|Any CPU.Build.0 = Debug|Any CPU + {B7AB5313-B55C-4AFF-940B-F17DC913AFB6}.Release|Any CPU.ActiveCfg = Release|Any CPU + {B7AB5313-B55C-4AFF-940B-F17DC913AFB6}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/IdentityServer.New/Config.cs b/src/IdentityServer.New/Config.cs new file mode 100644 index 00000000..95bb2e42 --- /dev/null +++ b/src/IdentityServer.New/Config.cs @@ -0,0 +1,41 @@ +using Duende.IdentityServer.Models; + +namespace IdentityServer.New +{ + public static class Config + { + + public static IEnumerable IdentityResources => + new IdentityResource[] + { + new IdentityResources.OpenId(), + new IdentityResources.Profile(), + }; + public const string ClientId = "spa"; + public const string ApiScope = "api"; + public const string ClientSecret = "secret"; + + public static IEnumerable ApiScopes => + new ApiScope[] + { + new ApiScope(ApiScope, new[] { "name" }), + }; + + + public static IEnumerable Clients => + new Client[] + { + // m2m client credentials flow client + new Client + { + ClientId = ClientId, + ClientName = "Client Credentials Client", + + AllowedGrantTypes = GrantTypes.ResourceOwnerPasswordAndClientCredentials, + ClientSecrets = { new Secret(ClientSecret.Sha256()) }, + + AllowedScopes = { "openid", "profile", ApiScope } + }, + }; + } +} diff --git a/src/IdentityServer.New/HostingExtensions.cs b/src/IdentityServer.New/HostingExtensions.cs new file mode 100644 index 00000000..0932d2a5 --- /dev/null +++ b/src/IdentityServer.New/HostingExtensions.cs @@ -0,0 +1,55 @@ +using Duende.IdentityServer; +using IdentityServer.New; +using Microsoft.AspNetCore.Mvc.RazorPages; +using Serilog; + +namespace IdentityServer.New +{ + internal static class HostingExtensions + { + public static WebApplication ConfigureServices(this WebApplicationBuilder builder) + { + builder.Services.AddRazorPages(); + + var isBuilder = builder.Services.AddIdentityServer(options => + { + options.Events.RaiseErrorEvents = true; + options.Events.RaiseInformationEvents = true; + options.Events.RaiseFailureEvents = true; + options.Events.RaiseSuccessEvents = true; + + // see https://docs.duendesoftware.com/identityserver/v6/fundamentals/resources/ + options.EmitStaticAudienceClaim = true; + }) + .AddTestUsers(TestUsers.Users); + + isBuilder.AddInMemoryIdentityResources(Config.IdentityResources); + isBuilder.AddInMemoryApiScopes(Config.ApiScopes); + isBuilder.AddInMemoryClients(Config.Clients); + + builder.Services.AddAuthentication(); + + return builder.Build(); + } + + public static WebApplication ConfigurePipeline(this WebApplication app) + { + app.UseSerilogRequestLogging(); + + if (app.Environment.IsDevelopment()) + { + app.UseDeveloperExceptionPage(); + } + + app.UseStaticFiles(); + app.UseRouting(); + app.UseIdentityServer(); + app.UseAuthorization(); + + app.MapRazorPages() + .RequireAuthorization(); + + return app; + } + } +} \ No newline at end of file diff --git a/src/IdentityServer.New/IdentityServer.New.csproj b/src/IdentityServer.New/IdentityServer.New.csproj new file mode 100644 index 00000000..9d4a949b --- /dev/null +++ b/src/IdentityServer.New/IdentityServer.New.csproj @@ -0,0 +1,13 @@ + + + + net6.0 + enable + + + + + + + + \ No newline at end of file diff --git a/src/IdentityServer.New/Pages/Account/AccessDenied.cshtml b/src/IdentityServer.New/Pages/Account/AccessDenied.cshtml new file mode 100644 index 00000000..5ede1a3a --- /dev/null +++ b/src/IdentityServer.New/Pages/Account/AccessDenied.cshtml @@ -0,0 +1,10 @@ +@page +@model IdentityServer.New.Pages.Account.AccessDeniedModel +@{ +} +
+
+

Access Denied

+

You do not have permission to access that resource.

+
+
\ No newline at end of file diff --git a/src/IdentityServer.New/Pages/Account/AccessDenied.cshtml.cs b/src/IdentityServer.New/Pages/Account/AccessDenied.cshtml.cs new file mode 100644 index 00000000..acca4e14 --- /dev/null +++ b/src/IdentityServer.New/Pages/Account/AccessDenied.cshtml.cs @@ -0,0 +1,11 @@ +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace IdentityServer.New.Pages.Account +{ + public class AccessDeniedModel : PageModel + { + public void OnGet() + { + } + } +} \ No newline at end of file diff --git a/src/IdentityServer.New/Pages/Account/Create/Index.cshtml b/src/IdentityServer.New/Pages/Account/Create/Index.cshtml new file mode 100644 index 00000000..51b0ffab --- /dev/null +++ b/src/IdentityServer.New/Pages/Account/Create/Index.cshtml @@ -0,0 +1,40 @@ +@page +@model IdentityServer.New.Pages.Create.Index + + \ No newline at end of file diff --git a/src/IdentityServer.New/Pages/Account/Create/Index.cshtml.cs b/src/IdentityServer.New/Pages/Account/Create/Index.cshtml.cs new file mode 100644 index 00000000..037e4fba --- /dev/null +++ b/src/IdentityServer.New/Pages/Account/Create/Index.cshtml.cs @@ -0,0 +1,121 @@ +using Duende.IdentityServer; +using Duende.IdentityServer.Events; +using Duende.IdentityServer.Models; +using Duende.IdentityServer.Services; +using Duende.IdentityServer.Stores; +using Duende.IdentityServer.Test; +using Microsoft.AspNetCore.Authentication; +using Microsoft.AspNetCore.Authorization; +using Microsoft.AspNetCore.Mvc; +using Microsoft.AspNetCore.Mvc.RazorPages; + +namespace IdentityServer.New.Pages.Create +{ + [SecurityHeaders] + [AllowAnonymous] + public class Index : PageModel + { + private readonly TestUserStore _users; + private readonly IIdentityServerInteractionService _interaction; + + [BindProperty] + public InputModel Input { get; set; } + + public Index( + IIdentityServerInteractionService interaction, + TestUserStore users = null) + { + // this is where you would plug in your own custom identity management library (e.g. ASP.NET Identity) + _users = users ?? throw new Exception("Please call 'AddTestUsers(TestUsers.Users)' on the IIdentityServerBuilder in Startup or remove the TestUserStore from the AccountController."); + + _interaction = interaction; + } + + public IActionResult OnGet(string returnUrl) + { + Input = new InputModel { ReturnUrl = returnUrl }; + return Page(); + } + + public async Task OnPost() + { + // check if we are in the context of an authorization request + var context = await _interaction.GetAuthorizationContextAsync(Input.ReturnUrl); + + // the user clicked the "cancel" button + if (Input.Button != "create") + { + if (context != null) + { + // if the user cancels, send a result back into IdentityServer as if they + // denied the consent (even if this client does not require consent). + // this will send back an access denied OIDC error response to the client. + await _interaction.DenyAuthorizationAsync(context, AuthorizationError.AccessDenied); + + // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null + if (context.IsNativeClient()) + { + // The client is native, so this change in how to + // return the response is for better UX for the end user. + return this.LoadingPage(Input.ReturnUrl); + } + + return Redirect(Input.ReturnUrl); + } + else + { + // since we don't have a valid context, then we just go back to the home page + return Redirect("~/"); + } + } + + if (_users.FindByUsername(Input.Username) != null) + { + ModelState.AddModelError("Input.Username", "Invalid username"); + } + + if (ModelState.IsValid) + { + var user = _users.CreateUser(Input.Username, Input.Password, Input.Name, Input.Email); + + // issue authentication cookie with subject ID and username + var isuser = new IdentityServerUser(user.SubjectId) + { + DisplayName = user.Username + }; + + await HttpContext.SignInAsync(isuser); + + if (context != null) + { + if (context.IsNativeClient()) + { + // The client is native, so this change in how to + // return the response is for better UX for the end user. + return this.LoadingPage(Input.ReturnUrl); + } + + // we can trust model.ReturnUrl since GetAuthorizationContextAsync returned non-null + return Redirect(Input.ReturnUrl); + } + + // request for a local page + if (Url.IsLocalUrl(Input.ReturnUrl)) + { + return Redirect(Input.ReturnUrl); + } + else if (string.IsNullOrEmpty(Input.ReturnUrl)) + { + return Redirect("~/"); + } + else + { + // user might have clicked on a malicious link - should be logged + throw new Exception("invalid return URL"); + } + } + + return Page(); + } + } +} \ No newline at end of file diff --git a/src/IdentityServer.New/Pages/Account/Create/InputModel.cs b/src/IdentityServer.New/Pages/Account/Create/InputModel.cs new file mode 100644 index 00000000..a51a7c75 --- /dev/null +++ b/src/IdentityServer.New/Pages/Account/Create/InputModel.cs @@ -0,0 +1,24 @@ +// Copyright (c) Duende Software. All rights reserved. +// See LICENSE in the project root for license information. + + +using System.ComponentModel.DataAnnotations; + +namespace IdentityServer.New.Pages.Create +{ + public class InputModel + { + [Required] + public string Username { get; set; } + + [Required] + public string Password { get; set; } + + public string Name { get; set; } + public string Email { get; set; } + + public string ReturnUrl { get; set; } + + public string Button { get; set; } + } +} \ No newline at end of file diff --git a/src/IdentityServer/Views/Account/Login.cshtml b/src/IdentityServer.New/Pages/Account/Login/Index.cshtml similarity index 66% rename from src/IdentityServer/Views/Account/Login.cshtml rename to src/IdentityServer.New/Pages/Account/Login/Index.cshtml index 28dbeec8..f7a18055 100644 --- a/src/IdentityServer/Views/Account/Login.cshtml +++ b/src/IdentityServer.New/Pages/Account/Login/Index.cshtml @@ -1,4 +1,5 @@ -@model LoginViewModel +@page +@model IdentityServer.New.Pages.Login.Index