From 854e6bf11dfd49e56584b0dac61f6d3027b1f145 Mon Sep 17 00:00:00 2001 From: Haiping Chen Date: Thu, 29 May 2025 05:39:07 -0500 Subject: [PATCH] OnTicketReceivedContext --- .../Users/IAuthenticationHook.cs | 19 +++++++--- .../Users/Services/UserService.cs | 2 +- .../BotSharpOpenApiExtensions.cs | 36 +++++++++++++++---- 3 files changed, 44 insertions(+), 13 deletions(-) diff --git a/src/Infrastructure/BotSharp.Abstraction/Users/IAuthenticationHook.cs b/src/Infrastructure/BotSharp.Abstraction/Users/IAuthenticationHook.cs index 21522a57..a8403dfa 100644 --- a/src/Infrastructure/BotSharp.Abstraction/Users/IAuthenticationHook.cs +++ b/src/Infrastructure/BotSharp.Abstraction/Users/IAuthenticationHook.cs @@ -1,4 +1,5 @@ using BotSharp.Abstraction.Users.Models; +using Microsoft.AspNetCore.Authentication; using System.Security.Claims; namespace BotSharp.Abstraction.Users; @@ -11,7 +12,8 @@ public interface IAuthenticationHook /// /// /// - Task Authenticate(string id, string password); + Task Authenticate(string id, string password) + => Task.FromResult(new User()); /// /// Add extra claims to user @@ -30,31 +32,38 @@ public interface IAuthenticationHook bool UserAuthenticated(User user, Token token) => true; + Task OAuthCompleted(TicketReceivedContext context) + => Task.CompletedTask; + /// /// Bfore user updating /// /// /// - Task UserUpdating(User user); + Task UserUpdating(User user) + => Task.CompletedTask; /// /// After user created /// /// /// - Task UserCreated(User user); + Task UserCreated(User user) + => Task.CompletedTask; /// /// Reset password /// /// /// - Task SendVerificationCode(User user); + Task SendVerificationCode(User user) + => Task.CompletedTask; /// /// Delete users /// /// /// - Task DelUsers(List userIds); + Task DelUsers(List userIds) + => Task.CompletedTask; } diff --git a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs index e4ebe311..e076026b 100644 --- a/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs +++ b/src/Infrastructure/BotSharp.Core/Users/Services/UserService.cs @@ -254,7 +254,7 @@ public class UserService : IUserService foreach (var hook in hooks) { user = await hook.Authenticate(id, password); - if (user == null) + if (user == null || string.IsNullOrEmpty(user.Id)) { continue; } diff --git a/src/Infrastructure/BotSharp.OpenAPI/BotSharpOpenApiExtensions.cs b/src/Infrastructure/BotSharp.OpenAPI/BotSharpOpenApiExtensions.cs index a1a6dad2..6136fc6c 100644 --- a/src/Infrastructure/BotSharp.OpenAPI/BotSharpOpenApiExtensions.cs +++ b/src/Infrastructure/BotSharp.OpenAPI/BotSharpOpenApiExtensions.cs @@ -11,6 +11,8 @@ using Microsoft.Net.Http.Headers; using Microsoft.OpenApi.Models; using Microsoft.IdentityModel.JsonWebTokens; using BotSharp.OpenAPI.BackgroundServices; +using System.Text.Json.Serialization; +using Microsoft.AspNetCore.Authentication; namespace BotSharp.OpenAPI; @@ -61,6 +63,9 @@ public static class BotSharpOpenApiExtensions } }).AddCookie(options => { + // Add these lines for cross-origin cookie support + options.Cookie.SameSite = Microsoft.AspNetCore.Http.SameSiteMode.None; + options.Cookie.SecurePolicy = CookieSecurePolicy.Always; }).AddPolicyScheme(schema, "Mixed authentication", options => { // runs on each request @@ -82,15 +87,16 @@ public static class BotSharpOpenApiExtensions }; }); + #region OpenId // GitHub OAuth if (!string.IsNullOrWhiteSpace(config["OAuth:GitHub:ClientId"]) && !string.IsNullOrWhiteSpace(config["OAuth:GitHub:ClientSecret"])) { builder = builder.AddGitHub(options => - { - options.ClientId = config["OAuth:GitHub:ClientId"]; - options.ClientSecret = config["OAuth:GitHub:ClientSecret"]; - options.Scope.Add("user:email"); - }); + { + options.ClientId = config["OAuth:GitHub:ClientId"]; + options.ClientSecret = config["OAuth:GitHub:ClientSecret"]; + options.Events.OnTicketReceived = OnTicketReceivedContext; + }); } // Google Identiy OAuth @@ -100,6 +106,7 @@ public static class BotSharpOpenApiExtensions { options.ClientId = config["OAuth:Google:ClientId"]; options.ClientSecret = config["OAuth:Google:ClientSecret"]; + options.Events.OnTicketReceived = OnTicketReceivedContext; }); } @@ -113,8 +120,9 @@ public static class BotSharpOpenApiExtensions options.ClientId = config["OAuth:Keycloak:ClientId"]; options.ClientSecret = config["OAuth:Keycloak:ClientSecret"]; options.AccessType = AspNet.Security.OAuth.Keycloak.KeycloakAuthenticationAccessType.Confidential; - int version = Convert.ToInt32(config["OAuth:Keycloak:Version"]??"22") ; - options.Version = new Version(version,0); + int version = Convert.ToInt32(config["OAuth:Keycloak:Version"] ?? "22"); + options.Version = new Version(version, 0); + options.Events.OnTicketReceived = OnTicketReceivedContext; }); } @@ -129,13 +137,17 @@ public static class BotSharpOpenApiExtensions options.Backchannel = builder.Services.BuildServiceProvider() .GetRequiredService() .CreateClient(); + options.Events.OnTicketReceived = OnTicketReceivedContext; }); } + #endregion // Add services to the container. services.AddControllers() .AddJsonOptions(options => { + options.JsonSerializerOptions.PropertyNameCaseInsensitive = true; + options.JsonSerializerOptions.Converters.Add(new JsonStringEnumConverter()); options.JsonSerializerOptions.Converters.Add(new RichContentJsonConverter()); options.JsonSerializerOptions.Converters.Add(new TemplateMessageJsonConverter()); }); @@ -182,6 +194,16 @@ public static class BotSharpOpenApiExtensions return services; } + private static async Task OnTicketReceivedContext(TicketReceivedContext context) + { + var services = context.HttpContext.RequestServices; + var hooks = services.GetServices(); + foreach (var hook in hooks) + { + await hook.OAuthCompleted(context); + } + } + /// /// Use Swagger/OpenAPI ///