From 84698ed2439961ba66d68a1fb96c7e6f4b1eba69 Mon Sep 17 00:00:00 2001
From: arthuridea w <2337583+arthuridea@users.noreply.github.com>
Date: Wed, 27 Dec 2023 16:56:58 +0800
Subject: [PATCH] fix:alter project structure.add oidc support.
---
NetCore.AIGC.sln | 10 +-
.../ChatService/ChatServiceBase.cs | 4 +-
.../Controllers/AccountController.cs | 126 ++++++++++++++++++
.../Pages/Account/SignedOut.cshtml | 2 +
.../Pages/Account/SignedOut.cshtml.cs | 33 +++++
src/LLMServiceHub/Common/AppConsts.cs | 12 ++
.../Common/AppRuntimeExtensions.cs | 27 ++++
.../v1_0/BaiduApiController.cs | 2 +-
.../v1_0/ChatGPTApiController.cs | 2 +-
src/LLMServiceHub/LLMServiceHub.csproj | 5 +
src/LLMServiceHub/Pages/Index.cshtml | 32 ++---
src/LLMServiceHub/Pages/Index.cshtml.cs | 34 +++--
src/LLMServiceHub/Pages/SignOut.cshtml.cs | 15 ++-
src/LLMServiceHub/Program.cs | 11 +-
src/LLMServiceHub/Startup.cs | 20 ++-
src/LLMServiceHub/appsettings.json | 4 +
.../wwwroot/images/Microsoft_logo.svg | 1 +
.../wwwroot/images/github-mark.svg | 1 +
18 files changed, 301 insertions(+), 40 deletions(-)
create mode 100644 src/LLMServiceHub/Areas/GitHubIdentity/Controllers/AccountController.cs
create mode 100644 src/LLMServiceHub/Areas/GitHubIdentity/Pages/Account/SignedOut.cshtml
create mode 100644 src/LLMServiceHub/Areas/GitHubIdentity/Pages/Account/SignedOut.cshtml.cs
create mode 100644 src/LLMServiceHub/Common/AppRuntimeExtensions.cs
rename src/LLMServiceHub/{Controller => Controllers}/v1_0/BaiduApiController.cs (98%)
rename src/LLMServiceHub/{Controller => Controllers}/v1_0/ChatGPTApiController.cs (96%)
create mode 100644 src/LLMServiceHub/wwwroot/images/Microsoft_logo.svg
create mode 100644 src/LLMServiceHub/wwwroot/images/github-mark.svg
diff --git a/NetCore.AIGC.sln b/NetCore.AIGC.sln
index cfdbf46..430b9bc 100644
--- a/NetCore.AIGC.sln
+++ b/NetCore.AIGC.sln
@@ -23,9 +23,17 @@ EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LLMService.Baidu.ErnieVilg", "src\LLMService.Baidu.ErnieVilg\LLMService.Baidu.ErnieVilg.csproj", "{E3AE89E4-31A0-4EDA-9154-2D089E1FD8A4}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "03.Docs", "03.Docs", "{7E5E6C28-ABB2-4564-AF1B-D9FCC81B8353}"
+ ProjectSection(SolutionItems) = preProject
+ docs\build.cmd = docs\build.cmd
+ docs\docfx.json = docs\docfx.json
+ docs\index.md = docs\index.md
+ docs\toc.yml = docs\toc.yml
+ EndProjectSection
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "LLMService.OpenAI.ChatGPT", "src\LLMService.OpenAI.ChatGPT\LLMService.OpenAI.ChatGPT.csproj", "{09322116-1405-47CE-BBB5-35E02167905D}"
EndProject
+Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "02.Sample", "02.Sample", "{0B000384-47E8-4013-A1CE-59A465017EF2}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -57,7 +65,7 @@ Global
HideSolutionNode = FALSE
EndGlobalSection
GlobalSection(NestedProjects) = preSolution
- {3CA26111-12C9-4AF1-966F-45019EA52385} = {01705FE5-59E6-4B65-B545-5DFD3AFB1F16}
+ {3CA26111-12C9-4AF1-966F-45019EA52385} = {0B000384-47E8-4013-A1CE-59A465017EF2}
{DC8A11BE-3268-4F1E-B83F-27958041ABF1} = {01705FE5-59E6-4B65-B545-5DFD3AFB1F16}
{E73CB18F-26D3-4A6C-8AA2-E89FF17B65C5} = {01705FE5-59E6-4B65-B545-5DFD3AFB1F16}
{E3AE89E4-31A0-4EDA-9154-2D089E1FD8A4} = {01705FE5-59E6-4B65-B545-5DFD3AFB1F16}
diff --git a/src/LLMService.Shared/ChatService/ChatServiceBase.cs b/src/LLMService.Shared/ChatService/ChatServiceBase.cs
index c222c4d..2b25385 100644
--- a/src/LLMService.Shared/ChatService/ChatServiceBase.cs
+++ b/src/LLMService.Shared/ChatService/ChatServiceBase.cs
@@ -13,8 +13,8 @@ namespace LLMService.Shared.ChatService
///
///
///
- /// The type of the request dto.
- /// The type of the response dto.
+ /// The type of the request dto.
+ /// The type of the response dto.
/// The type of the backend request dto.
/// The type of the backend response dto.
/// The type of the chat message.
diff --git a/src/LLMServiceHub/Areas/GitHubIdentity/Controllers/AccountController.cs b/src/LLMServiceHub/Areas/GitHubIdentity/Controllers/AccountController.cs
new file mode 100644
index 0000000..7443277
--- /dev/null
+++ b/src/LLMServiceHub/Areas/GitHubIdentity/Controllers/AccountController.cs
@@ -0,0 +1,126 @@
+using Microsoft.AspNetCore.Authentication.Cookies;
+using Microsoft.AspNetCore.Authentication.OAuth;
+using Microsoft.AspNetCore.Authentication.OpenIdConnect;
+using Microsoft.AspNetCore.Authentication;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.Identity.Web;
+using Microsoft.AspNetCore.Authorization;
+using LLMServiceHub.Common;
+
+#nullable enable
+namespace LLMServiceHub.Areas.GitHubIdentity.Controllers
+{
+ ///
+ ///
+ ///
+ ///
+ //[NonController]
+ [AllowAnonymous]
+ [Area("GitHubIdentity")]
+ [Route("[area]/[controller]/[action]")]
+ public class AccountController : Controller
+ {
+ ///
+ /// Handles user sign in.
+ ///
+ /// Authentication scheme.
+ /// Redirect URI.
+ /// Challenge generating a redirect to Azure AD to sign in the user.
+ [HttpGet("{scheme?}")]
+ public IActionResult SignIn(
+ [FromRoute] string scheme,
+ [FromQuery] string redirectUri)
+ {
+ scheme ??= AppConsts.GitHubAuthScheme;
+ string redirect;
+ if (!string.IsNullOrEmpty(redirectUri) && Url.IsLocalUrl(redirectUri))
+ {
+ redirect = redirectUri;
+ }
+ else
+ {
+ redirect = Url.Content("~/")!;
+ }
+
+ return Challenge(
+ new AuthenticationProperties { RedirectUri = redirect },
+ scheme);
+ }
+
+ ///
+ /// Challenges the user.
+ ///
+ /// Redirect URI.
+ /// Scopes to request.
+ /// Login hint.
+ /// Domain hint.
+ /// Claims.
+ /// AAD B2C policy.
+ /// Authentication scheme.
+ /// Challenge generating a redirect to Azure AD to sign in the user.
+ [HttpGet("{scheme?}")]
+ public IActionResult Challenge(
+ string redirectUri,
+ string scope,
+ string loginHint,
+ string domainHint,
+ string claims,
+ string policy,
+ [FromRoute] string scheme)
+ {
+ scheme ??= AppConsts.GitHubAuthScheme;
+ Dictionary items = new Dictionary
+ {
+ { Constants.Claims, claims },
+ { Constants.Policy, policy },
+ };
+ Dictionary parameters = new Dictionary
+ {
+ { Constants.LoginHint, loginHint },
+ { Constants.DomainHint, domainHint },
+ };
+
+ OAuthChallengeProperties oAuthChallengeProperties = new OAuthChallengeProperties(items, parameters);
+ if (scope != null)
+ {
+ oAuthChallengeProperties.Scope = scope.Split(" ");
+ }
+ oAuthChallengeProperties.RedirectUri = redirectUri;
+
+ return Challenge(
+ oAuthChallengeProperties,
+ scheme);
+ }
+
+ ///
+ /// Handles the user sign-out.
+ ///
+ /// Authentication scheme.
+ /// Sign out result.
+ [HttpGet("{scheme?}")]
+ public IActionResult SignOut(
+ [FromRoute] string scheme)
+ {
+ if (AppServicesAuthenticationInformation.IsAppServicesAadAuthenticationEnabled)
+ {
+ if (AppServicesAuthenticationInformation.LogoutUrl != null)
+ {
+ return LocalRedirect(AppServicesAuthenticationInformation.LogoutUrl);
+ }
+ return Ok();
+ }
+ else
+ {
+ scheme ??= AppConsts.GitHubAuthScheme;
+ var callbackUrl = Url.Page("/Account/SignedOut", pageHandler: null, values: null, protocol: Request.Scheme);
+ return SignOut(
+ new AuthenticationProperties
+ {
+ RedirectUri = callbackUrl,
+ },
+ CookieAuthenticationDefaults.AuthenticationScheme);
+ }
+ }
+ }
+}
+#nullable disable
\ No newline at end of file
diff --git a/src/LLMServiceHub/Areas/GitHubIdentity/Pages/Account/SignedOut.cshtml b/src/LLMServiceHub/Areas/GitHubIdentity/Pages/Account/SignedOut.cshtml
new file mode 100644
index 0000000..e1aa0e3
--- /dev/null
+++ b/src/LLMServiceHub/Areas/GitHubIdentity/Pages/Account/SignedOut.cshtml
@@ -0,0 +1,2 @@
+@page
+@model LLMServiceHub.Areas.GitHubIdentity.Pages.Account.SignedOutModel
diff --git a/src/LLMServiceHub/Areas/GitHubIdentity/Pages/Account/SignedOut.cshtml.cs b/src/LLMServiceHub/Areas/GitHubIdentity/Pages/Account/SignedOut.cshtml.cs
new file mode 100644
index 0000000..d7f78f9
--- /dev/null
+++ b/src/LLMServiceHub/Areas/GitHubIdentity/Pages/Account/SignedOut.cshtml.cs
@@ -0,0 +1,33 @@
+using Microsoft.AspNetCore.Authorization;
+using Microsoft.AspNetCore.Mvc;
+using Microsoft.AspNetCore.Mvc.RazorPages;
+
+namespace LLMServiceHub.Areas.GitHubIdentity.Pages.Account
+{
+ ///
+ /// Model for the SignOut page.
+ ///
+ [AllowAnonymous]
+ public class SignedOutModel : PageModel
+ {
+ ///
+ /// Method handling the HTTP GET method.
+ ///
+ /// A Sign Out page or Home page.
+ public IActionResult OnGet()
+ {
+ if (User?.Identity?.IsAuthenticated ?? false)
+ {
+ //return LocalRedirect("~/");
+ }
+
+ //return Page();
+ var returnUrl = HttpContext.Request.Query["returnUrl"];
+ if(string.IsNullOrEmpty(returnUrl))
+ {
+ returnUrl = "~/";
+ }
+ return LocalRedirect(returnUrl);
+ }
+ }
+}
diff --git a/src/LLMServiceHub/Common/AppConsts.cs b/src/LLMServiceHub/Common/AppConsts.cs
index f2f2f80..0bd664a 100644
--- a/src/LLMServiceHub/Common/AppConsts.cs
+++ b/src/LLMServiceHub/Common/AppConsts.cs
@@ -13,5 +13,17 @@ public static class AppConsts
/// The authentication cookie name
///
public const string AuthCookieName = "LLMService.Auth";
+ ///
+ /// The antiforgery cookie name
+ ///
+ public const string AntiforgeryCookieName = "LLMService.Antiforgery";
+ ///
+ /// The microsoft authentication scheme
+ ///
+ public const string MicrosoftAuthScheme = "Microsoft";
+ ///
+ /// The git hub authentication scheme
+ ///
+ public const string GitHubAuthScheme = "GitHub";
}
}
diff --git a/src/LLMServiceHub/Common/AppRuntimeExtensions.cs b/src/LLMServiceHub/Common/AppRuntimeExtensions.cs
new file mode 100644
index 0000000..e488718
--- /dev/null
+++ b/src/LLMServiceHub/Common/AppRuntimeExtensions.cs
@@ -0,0 +1,27 @@
+using Microsoft.AspNetCore.Authentication;
+
+namespace LLMServiceHub.Common
+{
+ ///
+ ///
+ ///
+ public static class AppRuntimeExtensions
+ {
+ ///
+ /// Gets the external providers asynchronous.
+ ///
+ /// The context.
+ ///
+ ///
+ public static async Task GetExternalProvidersAsync(this HttpContext context)
+ {
+ ArgumentNullException.ThrowIfNull(context);
+
+ var schemes = context.RequestServices.GetRequiredService();
+
+ return (from scheme in await schemes.GetAllSchemesAsync()
+ where !string.IsNullOrEmpty(scheme.DisplayName)
+ select scheme).ToArray();
+ }
+ }
+}
diff --git a/src/LLMServiceHub/Controller/v1_0/BaiduApiController.cs b/src/LLMServiceHub/Controllers/v1_0/BaiduApiController.cs
similarity index 98%
rename from src/LLMServiceHub/Controller/v1_0/BaiduApiController.cs
rename to src/LLMServiceHub/Controllers/v1_0/BaiduApiController.cs
index 8debb5f..33b00e7 100644
--- a/src/LLMServiceHub/Controller/v1_0/BaiduApiController.cs
+++ b/src/LLMServiceHub/Controllers/v1_0/BaiduApiController.cs
@@ -9,7 +9,7 @@
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
-namespace LLMServiceHub.Controller.v1_0
+namespace LLMServiceHub.Controllers.v1_0
{
///
/// 集成百度AI类api
diff --git a/src/LLMServiceHub/Controller/v1_0/ChatGPTApiController.cs b/src/LLMServiceHub/Controllers/v1_0/ChatGPTApiController.cs
similarity index 96%
rename from src/LLMServiceHub/Controller/v1_0/ChatGPTApiController.cs
rename to src/LLMServiceHub/Controllers/v1_0/ChatGPTApiController.cs
index 8daaf99..543b527 100644
--- a/src/LLMServiceHub/Controller/v1_0/ChatGPTApiController.cs
+++ b/src/LLMServiceHub/Controllers/v1_0/ChatGPTApiController.cs
@@ -5,7 +5,7 @@
using LLMServiceHub.Common;
using Microsoft.AspNetCore.Mvc;
-namespace LLMServiceHub.Controller.v1_0
+namespace LLMServiceHub.Controllers.v1_0
{
///
///
diff --git a/src/LLMServiceHub/LLMServiceHub.csproj b/src/LLMServiceHub/LLMServiceHub.csproj
index b6fea9c..4fcf696 100644
--- a/src/LLMServiceHub/LLMServiceHub.csproj
+++ b/src/LLMServiceHub/LLMServiceHub.csproj
@@ -40,6 +40,7 @@
+
@@ -51,6 +52,7 @@
+
@@ -71,6 +73,9 @@
+
+
+
diff --git a/src/LLMServiceHub/Pages/Index.cshtml b/src/LLMServiceHub/Pages/Index.cshtml
index 9397bd5..632927a 100644
--- a/src/LLMServiceHub/Pages/Index.cshtml
+++ b/src/LLMServiceHub/Pages/Index.cshtml
@@ -360,34 +360,28 @@
or
-
diff --git a/src/LLMServiceHub/Pages/Index.cshtml.cs b/src/LLMServiceHub/Pages/Index.cshtml.cs
index 30b0d28..9eac365 100644
--- a/src/LLMServiceHub/Pages/Index.cshtml.cs
+++ b/src/LLMServiceHub/Pages/Index.cshtml.cs
@@ -47,6 +47,14 @@ public class IndexModel : PageModel
[TempData]
public string ErrorMessage { get; set; }
+ ///
+ /// Gets or sets the OAuth schemes.
+ ///
+ ///
+ /// The OAuth schemes.
+ ///
+ public AuthenticationScheme[] OAuthSchemes { get; set; }
+
///
/// This API supports the ASP.NET Core Identity default UI infrastructure and is not intended to be used
/// directly from your code. This API may change or be removed in future releases.
@@ -101,17 +109,12 @@ public async Task OnGet(string returnUrl = null)
ModelState.AddModelError(string.Empty, ErrorMessage);
}
+ OAuthSchemes = await HttpContext.GetExternalProvidersAsync();
+
returnUrl ??= Url.Content("~/");
- if(!User.Identity.IsAuthenticated)
- {
- var result = await HttpContext.AuthenticateAsync(OpenIdConnectDefaults.AuthenticationScheme);
- if (result.Succeeded)
- {
- await ExecSignIn(AppConsts.DefaultAuthScheme, result.Principal.Identity.Name, true, returnUrl);
- Redirect(returnUrl);
- }
- }
+ await ChallengeExternal(AppConsts.MicrosoftAuthScheme, returnUrl);
+ await ChallengeExternal(AppConsts.GitHubAuthScheme, returnUrl);
ReturnUrl = returnUrl;
}
@@ -148,6 +151,19 @@ public async Task OnPostAsync(string returnUrl = null)
return Page();
}
+ private async Task ChallengeExternal(string scheme, string returnUrl)
+ {
+ if (!User.Identity.IsAuthenticated)
+ {
+ var result = await HttpContext.AuthenticateAsync(scheme);
+ if (result.Succeeded)
+ {
+ await ExecSignIn(AppConsts.DefaultAuthScheme, result.Principal.Identity.Name, true, returnUrl);
+ Redirect(returnUrl);
+ }
+ }
+ }
+
private async Task ExecSignIn(string scheme, string identityUserName, bool rememberme, string returnUrl)
{
// set authentication cookie
diff --git a/src/LLMServiceHub/Pages/SignOut.cshtml.cs b/src/LLMServiceHub/Pages/SignOut.cshtml.cs
index 8109c97..26f832d 100644
--- a/src/LLMServiceHub/Pages/SignOut.cshtml.cs
+++ b/src/LLMServiceHub/Pages/SignOut.cshtml.cs
@@ -23,12 +23,19 @@ public async Task OnGetAsync(string returnUrl = null)
// Clear the existing external cookie to ensure a clean login process
await HttpContext.SignOutAsync();
- var oauthResult = await HttpContext.AuthenticateAsync(OpenIdConnectDefaults.AuthenticationScheme);
- if (oauthResult.Succeeded)
+ return await SignOutExternal([AppConsts.MicrosoftAuthScheme, AppConsts.GitHubAuthScheme], returnUrl);
+ }
+
+ private async Task SignOutExternal(string[] schemes, string returnUrl = null)
+ {
+ foreach (var scheme in schemes)
{
- return RedirectToAction("SignOut", "Account", new { Area = "MicrosoftIdentity", returnUrl });
+ var oauthResult = await HttpContext.AuthenticateAsync(scheme);
+ if (oauthResult.Succeeded)
+ {
+ return RedirectToAction("SignOut", "Account", new { Area = $"{scheme}Identity", scheme, returnUrl });
+ }
}
-
return LocalRedirect(returnUrl);
}
}
diff --git a/src/LLMServiceHub/Program.cs b/src/LLMServiceHub/Program.cs
index 7caf18e..02d3137 100644
--- a/src/LLMServiceHub/Program.cs
+++ b/src/LLMServiceHub/Program.cs
@@ -43,6 +43,7 @@ public static int Main(string[] args)
///
public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaultBuilder(args)
.UseSerilog()
+ .ConfigureDefaults(args)
.ConfigureAppConfiguration((hostingContext, config) =>
{
config = _loadConfig(args, hostingContext, config);
@@ -50,10 +51,18 @@ public static IHostBuilder CreateHostBuilder(string[] args) => Host.CreateDefaul
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder
+ .UseDefaultServiceProvider(conf =>
+ {
+ })
.UseContentRoot(Directory.GetCurrentDirectory())
.UseIISIntegration()
.UseStartup();
- });
+ })
+ .ConfigureWebHost(config =>
+ {
+ })
+ ;
+
private static IConfigurationBuilder _loadConfig(string[] args, HostBuilderContext hostingContext, IConfigurationBuilder config = null)
{
diff --git a/src/LLMServiceHub/Startup.cs b/src/LLMServiceHub/Startup.cs
index 3b518dc..ec512bb 100644
--- a/src/LLMServiceHub/Startup.cs
+++ b/src/LLMServiceHub/Startup.cs
@@ -74,6 +74,12 @@ public void ConfigureServices(IServiceCollection services)
options.HandleSameSiteCookieCompatibility();
});
+ services.AddAntiforgery(options =>
+ {
+ options.Cookie.Name = AppConsts.AntiforgeryCookieName;
+ });
+
+ services.AddRouting();
// Ensure HttpContext injected. It will be accessed in Chat service.
services.AddHttpContextAccessor();
@@ -94,6 +100,7 @@ public void ConfigureServices(IServiceCollection services)
/********************************************* End Dependency Injection **********************************************/
+ services.AddControllers();
services.AddMvc().AddMicrosoftIdentityUI();
//services.AddControllersWithViews().AddMicrosoftIdentityUI();
@@ -154,10 +161,18 @@ public void ConfigureServices(IServiceCollection services)
options.RequireHttpsMetadata = appSettings.RequireHttpsMetadata;
options.Audience = appSettings.OidcApiName;
})
+ .AddGitHub(AppConsts.GitHubAuthScheme, options =>
+ {
+ options.ClientId = Configuration["GitHub:ClientId"] ?? string.Empty;
+ options.ClientSecret = Configuration["GitHub:ClientSecret"] ?? string.Empty;
+ options.EnterpriseDomain = Configuration["GitHub:EnterpriseDomain"] ?? string.Empty;
+ options.Scope.Add("user:email");
+ //options.CallbackPath = new PathString("/signin-github");
+ })
//.AddMicrosoftIdentityWebApp(options => Configuration.Bind("AzureAd", options));
;
- services.AddMicrosoftIdentityWebAppAuthentication(configuration: Configuration);
+ services.AddMicrosoftIdentityWebAppAuthentication(configuration: Configuration, openIdConnectScheme: AppConsts.MicrosoftAuthScheme);
services.AddAuthorization(options =>
{
@@ -453,7 +468,8 @@ public void Configure(IApplicationBuilder app, IWebHostEnvironment env, AppSetti
app.UseEndpoints(endpoints =>
{
- //endpoints.MapControllers();
+ endpoints.MapControllers();
+ endpoints.MapDefaultControllerRoute();
endpoints.MapRazorPages();
endpoints.MapControllerRoute(
name: "area-route",
diff --git a/src/LLMServiceHub/appsettings.json b/src/LLMServiceHub/appsettings.json
index 1198f89..560870c 100644
--- a/src/LLMServiceHub/appsettings.json
+++ b/src/LLMServiceHub/appsettings.json
@@ -35,6 +35,10 @@
"ClientSecret": "",
"TokenEndpoint": ""
},
+ "GitHub": {
+ "ClientId": "",
+ "ClientSecret": ""
+ },
"Users": [
{
"UserName": "",
diff --git a/src/LLMServiceHub/wwwroot/images/Microsoft_logo.svg b/src/LLMServiceHub/wwwroot/images/Microsoft_logo.svg
new file mode 100644
index 0000000..5334aa7
--- /dev/null
+++ b/src/LLMServiceHub/wwwroot/images/Microsoft_logo.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/src/LLMServiceHub/wwwroot/images/github-mark.svg b/src/LLMServiceHub/wwwroot/images/github-mark.svg
new file mode 100644
index 0000000..37fa923
--- /dev/null
+++ b/src/LLMServiceHub/wwwroot/images/github-mark.svg
@@ -0,0 +1 @@
+
\ No newline at end of file