Browse Source

feat(account): 账户模块增加OAuth扩展

- 增加OAuth模块 **AbpAccountOAuthModule** ,用于定义OAuth相关设置、功能.
- 重写登录视图页第三方登录区域组件
- 增加扩展登录提供者服务接口
- 增加账户模块OAuth实现模块 **AbpAccountWebOAuthModule**
- 重写OAuthHandler以实现从设置系统中读取客户端配置项 **AccountAuthenticationRequestHandler**、**IOAuthHandlerOptionsProvider**
- 增加默认第三方登录实现: GitHub、QQ、微信、企业微信、Bilibili
pull/1224/head
colin 8 months ago
parent
commit
36f268c970
  1. 3
      aspnet-core/modules/account/LINGYUN.Abp.Account.OAuth/FodyWeavers.xml
  2. 30
      aspnet-core/modules/account/LINGYUN.Abp.Account.OAuth/FodyWeavers.xsd
  3. 26
      aspnet-core/modules/account/LINGYUN.Abp.Account.OAuth/LINGYUN.Abp.Account.OAuth.csproj
  4. 28
      aspnet-core/modules/account/LINGYUN.Abp.Account.OAuth/LINGYUN/Abp/Account/OAuth/AbpAccountOAuthModule.cs
  5. 52
      aspnet-core/modules/account/LINGYUN.Abp.Account.OAuth/LINGYUN/Abp/Account/OAuth/Features/AccountOAuthFeatureDefinitionProvider.cs
  6. 46
      aspnet-core/modules/account/LINGYUN.Abp.Account.OAuth/LINGYUN/Abp/Account/OAuth/Features/AccountOAuthFeatureNames.cs
  7. 8
      aspnet-core/modules/account/LINGYUN.Abp.Account.OAuth/LINGYUN/Abp/Account/OAuth/Localization/AccountOAuthResource.cs
  8. 36
      aspnet-core/modules/account/LINGYUN.Abp.Account.OAuth/LINGYUN/Abp/Account/OAuth/Localization/Resources/en.json
  9. 36
      aspnet-core/modules/account/LINGYUN.Abp.Account.OAuth/LINGYUN/Abp/Account/OAuth/Localization/Resources/zh-Hans.json
  10. 77
      aspnet-core/modules/account/LINGYUN.Abp.Account.OAuth/LINGYUN/Abp/Account/OAuth/Settings/AccountOAuthSettingDefinitionProvider.cs
  11. 30
      aspnet-core/modules/account/LINGYUN.Abp.Account.OAuth/LINGYUN/Abp/Account/OAuth/Settings/AccountOAuthSettingNames.cs
  12. 105
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/AbpAccountWebOAuthModule.cs
  13. 81
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/ExternalProviders/AccountAuthenticationRequestHandler.cs
  14. 29
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/ExternalProviders/Bilibili/BilibiliAuthHandlerOptionsProvider.cs
  15. 29
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/ExternalProviders/GitHub/GitHubAuthHandlerOptionsProvider.cs
  16. 10
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/ExternalProviders/IOAuthHandlerOptionsProvider.cs
  17. 68
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/ExternalProviders/OAuthExternalProviderService.cs
  18. 18
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/ExternalProviders/OAuthHandlerOptionsProvider.cs
  19. 29
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/ExternalProviders/QQ/QQAuthHandlerOptionsProvider.cs
  20. 29
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/ExternalProviders/WeChat/WeChatAuthHandlerOptionsProvider.cs
  21. 34
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/ExternalProviders/WeCom/WeComAuthHandlerOptionsProvider.cs
  22. 3
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/FodyWeavers.xml
  23. 30
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/FodyWeavers.xsd
  24. 44
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/LINGYUN.Abp.Account.Web.OAuth.csproj
  25. 32
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/Microsoft/Extensions/DependencyInjection/AuthenticationBuilderExtensions.cs
  26. 14
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/Pages/Account/Components/ExternalProviders/Bilibili/Default.cshtml
  27. 13
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/Pages/Account/Components/ExternalProviders/ExternalProviderViewComponent.cs
  28. 14
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/Pages/Account/Components/ExternalProviders/GitHub/Default.cshtml
  29. 14
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/Pages/Account/Components/ExternalProviders/QQ/Default.cshtml
  30. 14
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/Pages/Account/Components/ExternalProviders/Weixin/Default.cshtml
  31. 13
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/Pages/Account/Components/ExternalProviders/WorkWeixin/Default.cshtml
  32. 12
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/Properties/launchSettings.json
  33. BIN
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/wwwroot/images/bilibili_logo_18x18.png
  34. BIN
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/wwwroot/images/qq_logo_15x18.png
  35. BIN
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/wwwroot/images/wecom_logo_77x18.png
  36. 10
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web/ExternalProviders/IExternalProviderService.cs
  37. 11
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web/Models/ExternalLoginProviderModel.cs
  38. 5
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web/Pages/Account/ChangePassword.cshtml.cs
  39. 15
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web/Pages/Account/Login.cshtml
  40. 325
      aspnet-core/modules/account/LINGYUN.Abp.Account.Web/Pages/Account/Login.cshtml.cs
  41. 23
      aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.WeChat/LINGYUN/Abp/OpenIddict/WeChat/WeChatOffcialTokenExtensionGrant.cs
  42. 1
      aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN.Abp.SettingManagement.Application.csproj
  43. 10
      aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN/Abp/SettingManagement/AbpSettingManagementApplicationModule.cs
  44. 46
      aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN/Abp/SettingManagement/SettingAppService.cs

3
aspnet-core/modules/account/LINGYUN.Abp.Account.OAuth/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
aspnet-core/modules/account/LINGYUN.Abp.Account.OAuth/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

26
aspnet-core/modules/account/LINGYUN.Abp.Account.OAuth/LINGYUN.Abp.Account.OAuth.csproj

@ -0,0 +1,26 @@
<Project Sdk="Microsoft.NET.Sdk">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0;net9.0</TargetFrameworks>
<AssemblyName>LINGYUN.Abp.Account.OAuth</AssemblyName>
<PackageId>LINGYUN.Abp.Account.OAuth</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace />
</PropertyGroup>
<ItemGroup>
<None Remove="LINGYUN\Abp\Account\OAuth\Localization\Resources\*.json" />
<EmbeddedResource Include="LINGYUN\Abp\Account\OAuth\Localization\Resources\*.json" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Volo.Abp.Features" />
<PackageReference Include="Volo.Abp.Settings" />
</ItemGroup>
</Project>

28
aspnet-core/modules/account/LINGYUN.Abp.Account.OAuth/LINGYUN/Abp/Account/OAuth/AbpAccountOAuthModule.cs

@ -0,0 +1,28 @@
using LINGYUN.Abp.Account.OAuth.Localization;
using Volo.Abp.Features;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.Settings;
using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.Account.OAuth;
[DependsOn(typeof(AbpFeaturesModule))]
[DependsOn(typeof(AbpSettingsModule))]
public class AbpAccountOAuthModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpAccountOAuthModule>();
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Add<AccountOAuthResource>()
.AddVirtualJson("/LINGYUN/Abp/Account/OAuth/Localization/Resources");
});
}
}

52
aspnet-core/modules/account/LINGYUN.Abp.Account.OAuth/LINGYUN/Abp/Account/OAuth/Features/AccountOAuthFeatureDefinitionProvider.cs

@ -0,0 +1,52 @@
using LINGYUN.Abp.Account.OAuth.Localization;
using Volo.Abp.Features;
using Volo.Abp.Localization;
using Volo.Abp.Validation.StringValues;
namespace LINGYUN.Abp.Account.OAuth.Features;
public class AccountOAuthFeatureDefinitionProvider : FeatureDefinitionProvider
{
public override void Define(IFeatureDefinitionContext context)
{
var group = context.AddGroup(
name: AccountOAuthFeatureNames.GroupName,
displayName: L("Features:ExternalOAuthLogin"));
group.AddFeature(
name: AccountOAuthFeatureNames.GitHub.Enable,
defaultValue: "false",
displayName: L("Features:GithubOAuthEnable"),
description: L("Features:GithubOAuthEnableDesc"),
valueType: new ToggleStringValueType(new BooleanValueValidator()));
group.AddFeature(
name: AccountOAuthFeatureNames.QQ.Enable,
defaultValue: "false",
displayName: L("Features:QQOAuthEnable"),
description: L("Features:QQOAuthEnableDesc"),
valueType: new ToggleStringValueType(new BooleanValueValidator()));
group.AddFeature(
name: AccountOAuthFeatureNames.WeChat.Enable,
defaultValue: "false",
displayName: L("Features:WeChatOAuthEnable"),
description: L("Features:WeChatOAuthEnableDesc"),
valueType: new ToggleStringValueType(new BooleanValueValidator()));
group.AddFeature(
name: AccountOAuthFeatureNames.WeCom.Enable,
defaultValue: "false",
displayName: L("Features:WeComOAuthEnable"),
description: L("Features:WeComOAuthEnableDesc"),
valueType: new ToggleStringValueType(new BooleanValueValidator()));
group.AddFeature(
name: AccountOAuthFeatureNames.Bilibili.Enable,
defaultValue: "false",
displayName: L("Features:BilibiliOAuthEnable"),
description: L("Features:BilibiliOAuthEnableDesc"),
valueType: new ToggleStringValueType(new BooleanValueValidator()));
}
private static LocalizableString L(string name)
{
return LocalizableString.Create<AccountOAuthResource>(name);
}
}

46
aspnet-core/modules/account/LINGYUN.Abp.Account.OAuth/LINGYUN/Abp/Account/OAuth/Features/AccountOAuthFeatureNames.cs

@ -0,0 +1,46 @@
namespace LINGYUN.Abp.Account.OAuth.Features;
public static class AccountOAuthFeatureNames
{
public const string GroupName = "Abp.Account.OAuth";
public static class GitHub
{
public const string Prefix = GroupName + ".GitHub";
/// <summary>
/// 启用Github认证登录
/// </summary>
public const string Enable = Prefix + ".Enable";
}
public static class QQ
{
public const string Prefix = GroupName + ".QQ";
/// <summary>
/// 启用QQ认证登录
/// </summary>
public const string Enable = Prefix + ".Enable";
}
public static class WeChat
{
public const string Prefix = GroupName + ".WeChat";
/// <summary>
/// 启用微信认证登录
/// </summary>
public const string Enable = Prefix + ".Enable";
}
public static class WeCom
{
public const string Prefix = GroupName + ".WeCom";
/// <summary>
/// 启用企业微信认证登录
/// </summary>
public const string Enable = Prefix + ".Enable";
}
public static class Bilibili
{
public const string Prefix = GroupName + ".Bilibili";
/// <summary>
/// 启用Bilibili认证登录
/// </summary>
public const string Enable = Prefix + ".Enable";
}
}

8
aspnet-core/modules/account/LINGYUN.Abp.Account.OAuth/LINGYUN/Abp/Account/OAuth/Localization/AccountOAuthResource.cs

@ -0,0 +1,8 @@
using Volo.Abp.Localization;
namespace LINGYUN.Abp.Account.OAuth.Localization;
[LocalizationResourceName("AbpAccountOAuth")]
public class AccountOAuthResource
{
}

36
aspnet-core/modules/account/LINGYUN.Abp.Account.OAuth/LINGYUN/Abp/Account/OAuth/Localization/Resources/en.json

@ -0,0 +1,36 @@
{
"culture": "en",
"texts": {
"Permission:ExternalOAuthLogin": "External Oauth Login",
"Features:ExternalOAuthLogin": "External Oauth Login",
"Features:GithubOAuthEnable": "GitHub",
"Features:GithubOAuthEnableDesc": "Enable to enable the application to support login via a GitHub account.",
"Features:QQOAuthEnable": "QQ",
"Features:QQOAuthEnableDesc": "Enable to enable the application to support login via QQ account.",
"Features:WeChatOAuthEnable": "WeChat",
"Features:WeChatOAuthEnableDesc": "Enable to enable the application to support login via the wechat official account.",
"Features:WeComOAuthEnable": "WeCom",
"Features:WeComOAuthEnableDesc": "Enable to enable the application to support login via wecom.",
"Features:BilibiliOAuthEnable": "Bilibili",
"Features:BilibiliOAuthEnableDesc": "Enable to allow the application to support login via a Bilibili account.",
"Settings:ExternalOAuthLogin": "External Oauth Login",
"Settings:GitHubAuth": "GitHub",
"Settings:GitHubClientId": "Client Id",
"Settings:GitHubClientIdDesc": "The client ID received from GitHub during registration. for details: https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps",
"Settings:GitHubClientSecret": "Client Secret",
"Settings:GitHubClientSecretDesc": "The client key of the OAuth application that you received from GitHub. for details: https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps",
"Settings:BilibiliAuth": "Bilibili",
"Settings:BilibiliClientId": "Client Id",
"Settings:BilibiliClientIdDesc": "Client Id, for details: https://open.bilibili.com/doc/4/eaf0e2b5-bde9-b9a0-9be1-019bb455701c#h1-u7B80u4ECB",
"Settings:BilibiliClientSecret": "Client Secret",
"Settings:BilibiliClientSecretDesc": "Client Secret, for details: https://open.bilibili.com/doc/4/eaf0e2b5-bde9-b9a0-9be1-019bb455701c#h1-u7B80u4ECB",
"OAuth:Microsoft": "Microsoft",
"OAuth:Twitter": "Twitter",
"OAuth:GitHub": "GitHub",
"OAuth:Google": "Google",
"OAuth:QQ": "QQ",
"OAuth:Weixin": "WeChat",
"OAuth:WorkWeixin": "WeCom",
"OAuth:Bilibili": "Bilibili"
}
}

36
aspnet-core/modules/account/LINGYUN.Abp.Account.OAuth/LINGYUN/Abp/Account/OAuth/Localization/Resources/zh-Hans.json

@ -0,0 +1,36 @@
{
"culture": "zh-Hans",
"texts": {
"Permission:ExternalOAuthLogin": "外部登录",
"Features:ExternalOAuthLogin": "外部登录",
"Features:GithubOAuthEnable": "GitHub认证",
"Features:GithubOAuthEnableDesc": "启用以使应用程序支持通过GitHub账号登录.",
"Features:QQOAuthEnable": "QQ认证",
"Features:QQOAuthEnableDesc": "启用以使应用程序支持通过QQ账号登录.",
"Features:WeChatOAuthEnable": "微信认证",
"Features:WeChatOAuthEnableDesc": "启用以使应用程序支持通过微信公众号登录.",
"Features:WeComOAuthEnable": "企业微信认证",
"Features:WeComOAuthEnableDesc": "启用以使应用程序支持通过企业微信登录.",
"Features:BilibiliOAuthEnable": "Bilibili认证",
"Features:BilibiliOAuthEnableDesc": "启用以使应用程序支持通过Bilibili账号登录.",
"Settings:ExternalOAuthLogin": "外部登录",
"Settings:GitHubAuth": "GitHub登录",
"Settings:GitHubClientId": "Client Id",
"Settings:GitHubClientIdDesc": "注册时从 GitHub 收到的客户端 ID.详见: https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps",
"Settings:GitHubClientSecret": "Client Secret",
"Settings:GitHubClientSecretDesc": "您从 GitHub 收到的 OAuth 应用程序的客户端密钥.详见: https://docs.github.com/en/apps/oauth-apps/building-oauth-apps/authorizing-oauth-apps",
"Settings:BilibiliAuth": "Bilibili登录",
"Settings:BilibiliClientId": "Client Id",
"Settings:BilibiliClientIdDesc": "应用Id, 详见: https://open.bilibili.com/doc/4/eaf0e2b5-bde9-b9a0-9be1-019bb455701c#h1-u7B80u4ECB",
"Settings:BilibiliClientSecret": "Client Secret",
"Settings:BilibiliClientSecretDesc": "应用密钥, 详见: https://open.bilibili.com/doc/4/eaf0e2b5-bde9-b9a0-9be1-019bb455701c#h1-u7B80u4ECB",
"OAuth:Microsoft": "Microsoft",
"OAuth:Twitter": "Twitter",
"OAuth:GitHub": "GitHub",
"OAuth:Google": "Google",
"OAuth:QQ": "QQ",
"OAuth:Weixin": "微信",
"OAuth:WorkWeixin": "企业微信",
"OAuth:Bilibili": "Bilibili"
}
}

77
aspnet-core/modules/account/LINGYUN.Abp.Account.OAuth/LINGYUN/Abp/Account/OAuth/Settings/AccountOAuthSettingDefinitionProvider.cs

@ -0,0 +1,77 @@
using LINGYUN.Abp.Account.OAuth.Localization;
using Volo.Abp.Localization;
using Volo.Abp.Settings;
namespace LINGYUN.Abp.Account.OAuth.Settings;
public class AccountOAuthSettingDefinitionProvider : SettingDefinitionProvider
{
public override void Define(ISettingDefinitionContext context)
{
context.Add(GetGitHubSettings());
context.Add(GetBilibiliSettings());
}
private SettingDefinition[] GetGitHubSettings()
{
return new SettingDefinition[]
{
new SettingDefinition(
AccountOAuthSettingNames.GitHub.ClientId,
displayName: L("Settings:GitHubClientId"),
description: L("Settings:GitHubClientIdDesc"),
isVisibleToClients: false,
isEncrypted: true)
.WithProviders(
DefaultValueSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName,
GlobalSettingValueProvider.ProviderName,
TenantSettingValueProvider.ProviderName),
new SettingDefinition(
AccountOAuthSettingNames.GitHub.ClientSecret,
displayName: L("Settings:GitHubClientSecret"),
description: L("Settings:GitHubClientSecretDesc"),
isVisibleToClients: false,
isEncrypted: true)
.WithProviders(
DefaultValueSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName,
GlobalSettingValueProvider.ProviderName,
TenantSettingValueProvider.ProviderName),
};
}
private SettingDefinition[] GetBilibiliSettings()
{
return new SettingDefinition[]
{
new SettingDefinition(
AccountOAuthSettingNames.Bilibili.ClientId,
displayName: L("Settings:BilibiliClientId"),
description: L("Settings:BilibiliClientIdDesc"),
isVisibleToClients: false,
isEncrypted: true)
.WithProviders(
DefaultValueSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName,
GlobalSettingValueProvider.ProviderName,
TenantSettingValueProvider.ProviderName),
new SettingDefinition(
AccountOAuthSettingNames.Bilibili.ClientSecret,
displayName: L("Settings:BilibiliClientSecret"),
description: L("Settings:BilibiliClientSecretDesc"),
isVisibleToClients: false,
isEncrypted: true)
.WithProviders(
DefaultValueSettingValueProvider.ProviderName,
ConfigurationSettingValueProvider.ProviderName,
GlobalSettingValueProvider.ProviderName,
TenantSettingValueProvider.ProviderName),
};
}
protected ILocalizableString L(string name)
{
return LocalizableString.Create<AccountOAuthResource>(name);
}
}

30
aspnet-core/modules/account/LINGYUN.Abp.Account.OAuth/LINGYUN/Abp/Account/OAuth/Settings/AccountOAuthSettingNames.cs

@ -0,0 +1,30 @@
namespace LINGYUN.Abp.Account.OAuth.Settings;
public static class AccountOAuthSettingNames
{
public const string GroupName = "Abp.Account.OAuth";
public static class GitHub
{
public const string Prefix = GroupName + ".GitHub";
/// <summary>
/// ClientId
/// </summary>
public const string ClientId = Prefix + ".ClientId";
/// <summary>
/// ClientSecret
/// </summary>
public const string ClientSecret = Prefix + ".ClientSecret";
}
public static class Bilibili
{
public const string Prefix = GroupName + ".Bilibili";
/// <summary>
/// ClientId
/// </summary>
public const string ClientId = Prefix + ".ClientId";
/// <summary>
/// ClientSecret
/// </summary>
public const string ClientSecret = Prefix + ".ClientSecret";
}
}

105
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/AbpAccountWebOAuthModule.cs

@ -0,0 +1,105 @@
using AspNet.Security.OAuth.Bilibili;
using AspNet.Security.OAuth.GitHub;
using AspNet.Security.OAuth.QQ;
using AspNet.Security.OAuth.Weixin;
using AspNet.Security.OAuth.WorkWeixin;
using LINGYUN.Abp.Account.OAuth;
using LINGYUN.Abp.Account.OAuth.Localization;
using LINGYUN.Abp.Account.Web.OAuth.ExternalProviders.Bilibili;
using LINGYUN.Abp.Account.Web.OAuth.ExternalProviders.GitHub;
using LINGYUN.Abp.Account.Web.OAuth.ExternalProviders.QQ;
using LINGYUN.Abp.Account.Web.OAuth.ExternalProviders.WeChat;
using LINGYUN.Abp.Account.Web.OAuth.ExternalProviders.WeCom;
using LINGYUN.Abp.Account.Web.OAuth.Microsoft.Extensions.DependencyInjection;
using LINGYUN.Abp.Tencent.QQ;
using LINGYUN.Abp.WeChat.Official;
using LINGYUN.Abp.WeChat.Work;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Account.Localization;
using Volo.Abp.AspNetCore.Mvc.Localization;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
using Volo.Abp.VirtualFileSystem;
namespace LINGYUN.Abp.Account.Web.OAuth;
[DependsOn(typeof(AbpAccountWebModule))]
[DependsOn(typeof(AbpAccountOAuthModule))]
[DependsOn(typeof(AbpTencentQQModule))]
[DependsOn(typeof(AbpWeChatOfficialModule))]
[DependsOn(typeof(AbpWeChatWorkModule))]
public class AbpAccountWebOAuthModule : AbpModule
{
public override void PreConfigureServices(ServiceConfigurationContext context)
{
context.Services.PreConfigure<AbpMvcDataAnnotationsLocalizationOptions>(options =>
{
options.AddAssemblyResource(typeof(AccountResource), typeof(AbpAccountWebOAuthModule).Assembly);
});
PreConfigure<IMvcBuilder>(mvcBuilder =>
{
mvcBuilder.AddApplicationPartIfNotExists(typeof(AbpAccountWebOAuthModule).Assembly);
});
}
public override void ConfigureServices(ServiceConfigurationContext context)
{
Configure<AbpVirtualFileSystemOptions>(options =>
{
options.FileSets.AddEmbedded<AbpAccountWebOAuthModule>("LINGYUN.Abp.Account.Web.OAuth");
});
Configure<AbpLocalizationOptions>(options =>
{
options.Resources
.Get<AccountResource>()
.AddBaseTypes(typeof(AccountOAuthResource));
});
context.Services
.AddAuthentication()
.AddGitHub(options =>
{
options.ClientId = "ClientId";
options.ClientSecret = "ClientSecret";
options.Scope.Add("user:email");
}).UseSettingProvider<
GitHubAuthenticationOptions,
GitHubAuthenticationHandler,
GitHubAuthHandlerOptionsProvider>()
.AddQQ(options =>
{
options.ClientId = "ClientId";
options.ClientSecret = "ClientSecret";
}).UseSettingProvider<
QQAuthenticationOptions,
QQAuthenticationHandler,
QQAuthHandlerOptionsProvider>()
.AddWeixin(options =>
{
options.ClientId = "ClientId";
options.ClientSecret = "ClientSecret";
}).UseSettingProvider<
WeixinAuthenticationOptions,
WeixinAuthenticationHandler,
WeChatAuthHandlerOptionsProvider>()
.AddWorkWeixin(options =>
{
options.ClientId = "ClientId";
options.ClientSecret = "ClientSecret";
}).UseSettingProvider<
WorkWeixinAuthenticationOptions,
WorkWeixinAuthenticationHandler,
WeComAuthHandlerOptionsProvider>()
.AddBilibili(options =>
{
options.ClientId = "ClientId";
options.ClientSecret = "ClientSecret";
}).UseSettingProvider<
BilibiliAuthenticationOptions,
BilibiliAuthenticationHandler,
BilibiliAuthHandlerOptionsProvider>();
}
}

81
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/ExternalProviders/AccountAuthenticationRequestHandler.cs

@ -0,0 +1,81 @@
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Http;
using System;
using System.Security.Claims;
using System.Threading.Tasks;
namespace LINGYUN.Abp.Account.Web.OAuth.ExternalProviders;
public class AccountAuthenticationRequestHandler<TOptions, THandler> : IAuthenticationRequestHandler
where TOptions : RemoteAuthenticationOptions, new()
where THandler : RemoteAuthenticationHandler<TOptions>
{
protected THandler InnerHandler { get; }
protected IOAuthHandlerOptionsProvider<TOptions> OptionsProvider { get; }
public AccountAuthenticationRequestHandler(
THandler innerHandler,
IOAuthHandlerOptionsProvider<TOptions> optionsProvider)
{
InnerHandler = innerHandler;
OptionsProvider = optionsProvider;
}
public virtual async Task InitializeAsync(AuthenticationScheme scheme, HttpContext context)
{
await InnerHandler.InitializeAsync(scheme, context);
}
public virtual async Task<AuthenticateResult> AuthenticateAsync()
{
return await InnerHandler.AuthenticateAsync();
}
public virtual async Task ChallengeAsync(AuthenticationProperties? properties)
{
await InitializeOptionsAsync();
await InnerHandler.ChallengeAsync(properties);
}
public virtual async Task ForbidAsync(AuthenticationProperties? properties)
{
await InnerHandler.ForbidAsync(properties);
}
public async Task SignOutAsync(AuthenticationProperties properties)
{
if (!(InnerHandler is IAuthenticationSignOutHandler signOutHandler))
{
throw new InvalidOperationException($"The authentication handler registered for scheme '{InnerHandler.Scheme}' is '{InnerHandler.GetType().Name}' which cannot be used for SignOutAsync");
}
await InitializeOptionsAsync();
await signOutHandler.SignOutAsync(properties);
}
public async Task SignInAsync(ClaimsPrincipal user, AuthenticationProperties properties)
{
if (!(InnerHandler is IAuthenticationSignInHandler signInHandler))
{
throw new InvalidOperationException($"The authentication handler registered for scheme '{InnerHandler.Scheme}' is '{InnerHandler.GetType().Name}' which cannot be used for SignInAsync");
}
await InitializeOptionsAsync();
await signInHandler.SignInAsync(user, properties);
}
public virtual async Task<bool> HandleRequestAsync()
{
if (await InnerHandler.ShouldHandleRequestAsync())
{
await InitializeOptionsAsync();
}
return await InnerHandler.HandleRequestAsync();
}
protected async virtual Task InitializeOptionsAsync()
{
await OptionsProvider.SetOptionsAsync(InnerHandler.Options);
}
}

29
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/ExternalProviders/Bilibili/BilibiliAuthHandlerOptionsProvider.cs

@ -0,0 +1,29 @@
using AspNet.Security.OAuth.Bilibili;
using LINGYUN.Abp.Account.OAuth.Settings;
using System;
using System.Threading.Tasks;
using Volo.Abp.Settings;
namespace LINGYUN.Abp.Account.Web.OAuth.ExternalProviders.Bilibili;
public class BilibiliAuthHandlerOptionsProvider : OAuthHandlerOptionsProvider<BilibiliAuthenticationOptions>
{
public BilibiliAuthHandlerOptionsProvider(ISettingProvider settingProvider) : base(settingProvider)
{
}
public async override Task SetOptionsAsync(BilibiliAuthenticationOptions options)
{
var clientId = await SettingProvider.GetOrNullAsync(AccountOAuthSettingNames.Bilibili.ClientId);
var clientSecret = await SettingProvider.GetOrNullAsync(AccountOAuthSettingNames.Bilibili.ClientSecret);
if (!clientId.IsNullOrWhiteSpace())
{
options.ClientId = clientId;
}
if (!clientSecret.IsNullOrWhiteSpace())
{
options.ClientSecret = clientSecret;
}
}
}

29
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/ExternalProviders/GitHub/GitHubAuthHandlerOptionsProvider.cs

@ -0,0 +1,29 @@
using AspNet.Security.OAuth.GitHub;
using LINGYUN.Abp.Account.OAuth.Settings;
using System;
using System.Threading.Tasks;
using Volo.Abp.Settings;
namespace LINGYUN.Abp.Account.Web.OAuth.ExternalProviders.GitHub;
public class GitHubAuthHandlerOptionsProvider : OAuthHandlerOptionsProvider<GitHubAuthenticationOptions>
{
public GitHubAuthHandlerOptionsProvider(ISettingProvider settingProvider) : base(settingProvider)
{
}
public async override Task SetOptionsAsync(GitHubAuthenticationOptions options)
{
var clientId = await SettingProvider.GetOrNullAsync(AccountOAuthSettingNames.GitHub.ClientId);
var clientSecret = await SettingProvider.GetOrNullAsync(AccountOAuthSettingNames.GitHub.ClientSecret);
if (!clientId.IsNullOrWhiteSpace())
{
options.ClientId = clientId;
}
if (!clientSecret.IsNullOrWhiteSpace())
{
options.ClientSecret = clientSecret;
}
}
}

10
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/ExternalProviders/IOAuthHandlerOptionsProvider.cs

@ -0,0 +1,10 @@
using Microsoft.AspNetCore.Authentication;
using System.Threading.Tasks;
namespace LINGYUN.Abp.Account.Web.OAuth.ExternalProviders;
public interface IOAuthHandlerOptionsProvider<TOptions>
where TOptions : RemoteAuthenticationOptions, new()
{
Task SetOptionsAsync(TOptions options);
}

68
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/ExternalProviders/OAuthExternalProviderService.cs

@ -0,0 +1,68 @@
using AspNet.Security.OAuth.Bilibili;
using AspNet.Security.OAuth.GitHub;
using AspNet.Security.OAuth.QQ;
using AspNet.Security.OAuth.Weixin;
using AspNet.Security.OAuth.WorkWeixin;
using LINGYUN.Abp.Account.OAuth.Features;
using LINGYUN.Abp.Account.Web.ExternalProviders;
using LINGYUN.Abp.Account.Web.Models;
using LINGYUN.Abp.Account.Web.OAuth.Pages.Account.Components.ExternalProviders;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.Localization;
using System.Collections.Generic;
using System.Threading.Tasks;
using Volo.Abp.Account.Localization;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Features;
namespace LINGYUN.Abp.Account.Web.OAuth.ExternalProviders;
public class OAuthExternalProviderService : IExternalProviderService, ITransientDependency
{
private static readonly Dictionary<string, string> _providerFeaturesMap = new Dictionary<string, string>
{
[GitHubAuthenticationDefaults.AuthenticationScheme] = AccountOAuthFeatureNames.GitHub.Enable,
[QQAuthenticationDefaults.AuthenticationScheme] = AccountOAuthFeatureNames.QQ.Enable,
[WeixinAuthenticationDefaults.AuthenticationScheme] = AccountOAuthFeatureNames.WeChat.Enable,
[WorkWeixinAuthenticationDefaults.AuthenticationScheme] = AccountOAuthFeatureNames.WeCom.Enable,
[BilibiliAuthenticationDefaults.AuthenticationScheme] = AccountOAuthFeatureNames.Bilibili.Enable
};
private readonly IFeatureChecker _featureChecker;
private readonly IStringLocalizer<AccountResource> _stringLocalizer;
private readonly IAuthenticationSchemeProvider _authenticationSchemeProvider;
public OAuthExternalProviderService(
IFeatureChecker featureChecker,
IStringLocalizer<AccountResource> stringLocalizer,
IAuthenticationSchemeProvider authenticationSchemeProvider)
{
_featureChecker = featureChecker;
_stringLocalizer = stringLocalizer;
_authenticationSchemeProvider = authenticationSchemeProvider;
}
public async virtual Task<List<ExternalLoginProviderModel>> GetAllAsync()
{
var models = new List<ExternalLoginProviderModel>();
var schemas = await _authenticationSchemeProvider.GetAllSchemesAsync();
foreach (var schema in schemas)
{
if (_providerFeaturesMap.TryGetValue(schema.Name, out var schemaFeature))
{
if (await _featureChecker.IsEnabledAsync(schemaFeature))
{
models.Add(new ExternalLoginProviderModel
{
Name = schema.Name,
AuthenticationScheme = schema.Name,
DisplayName = _stringLocalizer[$"OAuth:{schema.Name}"],
ComponentType = typeof(ExternalProviderViewComponent),
});
}
}
}
return models;
}
}

18
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/ExternalProviders/OAuthHandlerOptionsProvider.cs

@ -0,0 +1,18 @@
using Microsoft.AspNetCore.Authentication;
using System.Threading.Tasks;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Settings;
namespace LINGYUN.Abp.Account.Web.OAuth.ExternalProviders;
public abstract class OAuthHandlerOptionsProvider<TOptions> : IOAuthHandlerOptionsProvider<TOptions>, ITransientDependency
where TOptions : RemoteAuthenticationOptions, new()
{
protected ISettingProvider SettingProvider { get; }
public OAuthHandlerOptionsProvider(ISettingProvider settingProvider)
{
SettingProvider = settingProvider;
}
public abstract Task SetOptionsAsync(TOptions options);
}

29
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/ExternalProviders/QQ/QQAuthHandlerOptionsProvider.cs

@ -0,0 +1,29 @@
using AspNet.Security.OAuth.QQ;
using LINGYUN.Abp.Tencent.QQ.Settings;
using System;
using System.Threading.Tasks;
using Volo.Abp.Settings;
namespace LINGYUN.Abp.Account.Web.OAuth.ExternalProviders.QQ;
public class QQAuthHandlerOptionsProvider : OAuthHandlerOptionsProvider<QQAuthenticationOptions>
{
public QQAuthHandlerOptionsProvider(ISettingProvider settingProvider) : base(settingProvider)
{
}
public async override Task SetOptionsAsync(QQAuthenticationOptions options)
{
var clientId = await SettingProvider.GetOrNullAsync(TencentQQSettingNames.QQConnect.AppId);
var clientSecret = await SettingProvider.GetOrNullAsync(TencentQQSettingNames.QQConnect.AppKey);
if (!clientId.IsNullOrWhiteSpace())
{
options.ClientId = clientId;
}
if (!clientSecret.IsNullOrWhiteSpace())
{
options.ClientSecret = clientSecret;
}
}
}

29
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/ExternalProviders/WeChat/WeChatAuthHandlerOptionsProvider.cs

@ -0,0 +1,29 @@
using AspNet.Security.OAuth.Weixin;
using LINGYUN.Abp.WeChat.Official.Settings;
using System;
using System.Threading.Tasks;
using Volo.Abp.Settings;
namespace LINGYUN.Abp.Account.Web.OAuth.ExternalProviders.WeChat;
public class WeChatAuthHandlerOptionsProvider : OAuthHandlerOptionsProvider<WeixinAuthenticationOptions>
{
public WeChatAuthHandlerOptionsProvider(ISettingProvider settingProvider) : base(settingProvider)
{
}
public async override Task SetOptionsAsync(WeixinAuthenticationOptions options)
{
var clientId = await SettingProvider.GetOrNullAsync(WeChatOfficialSettingNames.AppId);
var clientSecret = await SettingProvider.GetOrNullAsync(WeChatOfficialSettingNames.AppSecret);
if (!clientId.IsNullOrWhiteSpace())
{
options.ClientId = clientId;
}
if (!clientSecret.IsNullOrWhiteSpace())
{
options.ClientSecret = clientSecret;
}
}
}

34
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/ExternalProviders/WeCom/WeComAuthHandlerOptionsProvider.cs

@ -0,0 +1,34 @@
using AspNet.Security.OAuth.WorkWeixin;
using LINGYUN.Abp.WeChat.Work.Settings;
using System;
using System.Threading.Tasks;
using Volo.Abp.Settings;
namespace LINGYUN.Abp.Account.Web.OAuth.ExternalProviders.WeCom;
public class WeComAuthHandlerOptionsProvider : OAuthHandlerOptionsProvider<WorkWeixinAuthenticationOptions>
{
public WeComAuthHandlerOptionsProvider(ISettingProvider settingProvider) : base(settingProvider)
{
}
public async override Task SetOptionsAsync(WorkWeixinAuthenticationOptions options)
{
var clientId = await SettingProvider.GetOrNullAsync(WeChatWorkSettingNames.Connection.CorpId);
var clientSecret = await SettingProvider.GetOrNullAsync(WeChatWorkSettingNames.Connection.Secret);
var agentId = await SettingProvider.GetOrNullAsync(WeChatWorkSettingNames.Connection.AgentId);
if (!clientId.IsNullOrWhiteSpace())
{
options.ClientId = clientId;
}
if (!clientSecret.IsNullOrWhiteSpace())
{
options.ClientSecret = clientSecret;
}
if (!agentId.IsNullOrWhiteSpace())
{
options.AgentId = agentId;
}
}
}

3
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/FodyWeavers.xml

@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<ConfigureAwait ContinueOnCapturedContext="false" />
</Weavers>

30
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/FodyWeavers.xsd

@ -0,0 +1,30 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" />
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

44
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/LINGYUN.Abp.Account.Web.OAuth.csproj

@ -0,0 +1,44 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Import Project="..\..\..\..\configureawait.props" />
<Import Project="..\..\..\..\common.props" />
<PropertyGroup>
<TargetFramework>net9.0</TargetFramework>
<AssemblyName>LINGYUN.Abp.Account.Web.OAuth</AssemblyName>
<PackageId>LINGYUN.Abp.Account.Web.OAuth</PackageId>
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute>
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute>
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute>
<RootNamespace>LINGYUN.Abp.Account.Web.OAuth</RootNamespace>
<OutputType>Library</OutputType>
<IsPackable>true</IsPackable>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<EmbeddedResource Include="wwwroot\**\*.js" />
<EmbeddedResource Include="wwwroot\**\*.css" />
<EmbeddedResource Include="wwwroot\**\*.png" />
<Content Remove="wwwroot\**\*.js" />
<Content Remove="wwwroot\**\*.css" />
<Content Remove="wwwroot\**\*.png" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="AspNet.Security.OAuth.Bilibili" />
<PackageReference Include="AspNet.Security.OAuth.GitHub" />
<PackageReference Include="AspNet.Security.OAuth.QQ" />
<PackageReference Include="AspNet.Security.OAuth.Weixin" />
<PackageReference Include="AspNet.Security.OAuth.WorkWeixin" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\..\framework\cloud-tencent\LINGYUN.Abp.Tencent.QQ\LINGYUN.Abp.Tencent.QQ.csproj" />
<ProjectReference Include="..\..\..\framework\wechat\LINGYUN.Abp.WeChat.Official\LINGYUN.Abp.WeChat.Official.csproj" />
<ProjectReference Include="..\..\..\framework\wechat\LINGYUN.Abp.WeChat.Work\LINGYUN.Abp.WeChat.Work.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.Account.OAuth\LINGYUN.Abp.Account.OAuth.csproj" />
<ProjectReference Include="..\LINGYUN.Abp.Account.Web\LINGYUN.Abp.Account.Web.csproj" />
</ItemGroup>
</Project>

32
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/Microsoft/Extensions/DependencyInjection/AuthenticationBuilderExtensions.cs

@ -0,0 +1,32 @@
using JetBrains.Annotations;
using LINGYUN.Abp.Account.Web.OAuth.ExternalProviders;
using Microsoft.AspNetCore.Authentication;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using System;
using System.Linq;
using Volo.Abp;
namespace LINGYUN.Abp.Account.Web.OAuth.Microsoft.Extensions.DependencyInjection;
public static class AuthenticationBuilderExtensions
{
public static AuthenticationBuilder UseSettingProvider<TOptions, THandler, TOptionsProvider>(
[NotNull] this AuthenticationBuilder authenticationBuilder)
where TOptions : RemoteAuthenticationOptions, new()
where THandler : RemoteAuthenticationHandler<TOptions>
where TOptionsProvider : IOAuthHandlerOptionsProvider<TOptions>
{
Check.NotNull(authenticationBuilder, nameof(authenticationBuilder));
var handler = authenticationBuilder.Services.LastOrDefault(x => x.ServiceType == typeof(THandler));
authenticationBuilder.Services.Replace(new ServiceDescriptor(
typeof(THandler),
provider => new AccountAuthenticationRequestHandler<TOptions, THandler>(
(THandler)ActivatorUtilities.CreateInstance(provider, typeof(THandler)),
provider.GetRequiredService<TOptionsProvider>()),
handler?.Lifetime ?? ServiceLifetime.Transient));
return authenticationBuilder;
}
}

14
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/Pages/Account/Components/ExternalProviders/Bilibili/Default.cshtml

@ -0,0 +1,14 @@
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.Account.Localization
@inject IHtmlLocalizer<AccountResource> L
@model LINGYUN.Abp.Account.Web.Models.ExternalLoginProviderModel
<button
type="submit"
class="btn btn-outline-secondary m-1"
name="provider"
value="@Model.AuthenticationScheme"
title="@L["LogInUsingYourProviderAccount", @Model.DisplayName]">
<img src="~/images/bilibili_logo_18x18.png" />
<span>@Model.DisplayName</span>
</button>

13
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/Pages/Account/Components/ExternalProviders/ExternalProviderViewComponent.cs

@ -0,0 +1,13 @@
using LINGYUN.Abp.Account.Web.Models;
using Microsoft.AspNetCore.Mvc;
using Volo.Abp.AspNetCore.Mvc;
namespace LINGYUN.Abp.Account.Web.OAuth.Pages.Account.Components.ExternalProviders;
public class ExternalProviderViewComponent : AbpViewComponent
{
public virtual IViewComponentResult Invoke(ExternalLoginProviderModel model)
{
return View($"~/Pages/Account/Components/ExternalProviders/{model.AuthenticationScheme}/Default.cshtml", model);
}
}

14
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/Pages/Account/Components/ExternalProviders/GitHub/Default.cshtml

@ -0,0 +1,14 @@
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.Account.Localization
@inject IHtmlLocalizer<AccountResource> L
@model LINGYUN.Abp.Account.Web.Models.ExternalLoginProviderModel
<button
type="submit"
class="btn btn-outline-secondary m-1"
name="provider"
value="@Model.AuthenticationScheme"
title="@L["LogInUsingYourProviderAccount", @Model.DisplayName]">
<i class="fa fa-github"></i>
<span>@Model.DisplayName</span>
</button>

14
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/Pages/Account/Components/ExternalProviders/QQ/Default.cshtml

@ -0,0 +1,14 @@
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.Account.Localization
@inject IHtmlLocalizer<AccountResource> L
@model LINGYUN.Abp.Account.Web.Models.ExternalLoginProviderModel
<button
type="submit"
class="btn btn-outline-secondary m-1"
name="provider"
value="@Model.AuthenticationScheme"
title="@L["LogInUsingYourProviderAccount", @Model.DisplayName]">
<img src="~/images/qq_logo_15x18.png" />
<span>@Model.DisplayName</span>
</button>

14
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/Pages/Account/Components/ExternalProviders/Weixin/Default.cshtml

@ -0,0 +1,14 @@
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.Account.Localization
@inject IHtmlLocalizer<AccountResource> L
@model LINGYUN.Abp.Account.Web.Models.ExternalLoginProviderModel
<button
type="submit"
class="btn btn-outline-secondary m-1"
name="provider"
value="@Model.AuthenticationScheme"
title="@L["LogInUsingYourProviderAccount", @Model.DisplayName]">
<i class="fa fa-weixin"></i>
<span>@Model.DisplayName</span>
</button>

13
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/Pages/Account/Components/ExternalProviders/WorkWeixin/Default.cshtml

@ -0,0 +1,13 @@
@using Microsoft.AspNetCore.Mvc.Localization
@using Volo.Abp.Account.Localization
@inject IHtmlLocalizer<AccountResource> L
@model LINGYUN.Abp.Account.Web.Models.ExternalLoginProviderModel
<button
type="submit"
class="btn btn-outline-secondary m-1"
name="provider"
value="@Model.AuthenticationScheme"
title="@L["LogInUsingYourProviderAccount", @Model.DisplayName]">
<img src="~/images/wecom_logo_77x18.png" />
</button>

12
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/Properties/launchSettings.json

@ -0,0 +1,12 @@
{
"profiles": {
"LINGYUN.Abp.Account.Web.OAuth": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:50897;http://localhost:50898"
}
}
}

BIN
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/wwwroot/images/bilibili_logo_18x18.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.0 KiB

BIN
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/wwwroot/images/qq_logo_15x18.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 628 B

BIN
aspnet-core/modules/account/LINGYUN.Abp.Account.Web.OAuth/wwwroot/images/wecom_logo_77x18.png

Binary file not shown.

After

Width:  |  Height:  |  Size: 1022 B

10
aspnet-core/modules/account/LINGYUN.Abp.Account.Web/ExternalProviders/IExternalProviderService.cs

@ -0,0 +1,10 @@
using LINGYUN.Abp.Account.Web.Models;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace LINGYUN.Abp.Account.Web.ExternalProviders;
public interface IExternalProviderService
{
Task<List<ExternalLoginProviderModel>> GetAllAsync();
}

11
aspnet-core/modules/account/LINGYUN.Abp.Account.Web/Models/ExternalLoginProviderModel.cs

@ -0,0 +1,11 @@
using System;
namespace LINGYUN.Abp.Account.Web.Models;
public class ExternalLoginProviderModel
{
public Type ComponentType { get; set; }
public string Name { get; set; }
public string DisplayName { get; set; }
public string AuthenticationScheme { get; set; }
}

5
aspnet-core/modules/account/LINGYUN.Abp.Account.Web/Pages/Account/ChangePassword.cshtml.cs

@ -90,6 +90,11 @@ public class ChangePasswordModel : AccountPageModel
Alerts.Warning(L["NewPasswordSameAsOld"]);
return Page();
}
if (Input.NewPassword != Input.NewPasswordConfirm)
{
Alerts.Warning(L["NewPasswordConfirmFailed"]);
return Page();
}
var userInfo = await GetCurrentUser();
if (userInfo != null)

15
aspnet-core/modules/account/LINGYUN.Abp.Account.Web/Pages/Account/Login.cshtml

@ -74,7 +74,20 @@
<form asp-page="./Login" asp-page-handler="ExternalLogin" asp-route-returnUrl="@Model.ReturnUrl" asp-route-returnUrlHash="@Model.ReturnUrlHash" method="post">
@foreach (var provider in Model.VisibleExternalProviders)
{
<button type="submit" class="btn btn-primary m-1" name="provider" value="@provider.AuthenticationScheme" title="@L["LogInUsingYourProviderAccount", provider.DisplayName]">@provider.DisplayName</button>
@* <button
type="submit"
class="btn btn-primary m-1"
name="provider"
value="@provider.AuthenticationScheme"
title="@L["LogInUsingYourProviderAccount", provider.DisplayName]"
>
@if (provider.Icon != null)
{
<i class="@provider.Icon"></i>
}
<span>@provider.DisplayName</span>
</button> *@
@await Component.InvokeAsync(provider.ComponentType, provider);
}
</form>
</div>

325
aspnet-core/modules/account/LINGYUN.Abp.Account.Web/Pages/Account/Login.cshtml.cs

@ -1,6 +1,9 @@
using LINGYUN.Abp.Account.Web.ExternalProviders;
using LINGYUN.Abp.Account.Web.Models;
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Identity;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using System;
using System.Collections.Generic;
@ -8,30 +11,81 @@ using System.Diagnostics;
using System.Linq;
using System.Security.Claims;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Account.Settings;
using Volo.Abp.Account.Web;
using Volo.Abp.Account.Web.Pages.Account;
using Volo.Abp.DependencyInjection;
using Volo.Abp.Identity;
using Volo.Abp.Identity.AspNetCore;
using Volo.Abp.Reflection;
using Volo.Abp.Security.Claims;
using Volo.Abp.Settings;
using Volo.Abp.Validation;
using static Volo.Abp.Account.Web.Pages.Account.LoginModel;
using IdentityUser = Volo.Abp.Identity.IdentityUser;
namespace LINGYUN.Abp.Account.Web.Pages.Account;
[ExposeServices(typeof(Volo.Abp.Account.Web.Pages.Account.LoginModel))]
public class LoginModel : Volo.Abp.Account.Web.Pages.Account.LoginModel
//[ExposeServices(typeof(Volo.Abp.Account.Web.Pages.Account.LoginModel))]
public class LoginModel : AccountPageModel
{
[HiddenInput]
[BindProperty(SupportsGet = true)]
public string ReturnUrl { get; set; }
[HiddenInput]
[BindProperty(SupportsGet = true)]
public string ReturnUrlHash { get; set; }
[BindProperty]
public LoginInputModel LoginInput { get; set; }
public bool EnableLocalLogin { get; set; }
public bool ShowCancelButton { get; set; }
public bool IsExternalLoginOnly => EnableLocalLogin == false && ExternalProviders?.Count() == 1;
public string ExternalLoginScheme => IsExternalLoginOnly ? ExternalProviders?.SingleOrDefault()?.AuthenticationScheme : null;
public IEnumerable<ExternalLoginProviderModel> ExternalProviders { get; set; }
public IEnumerable<ExternalLoginProviderModel> VisibleExternalProviders => ExternalProviders.Where(x => !x.DisplayName.IsNullOrWhiteSpace());
protected IExternalProviderService ExternalProviderService { get; }
protected IAuthenticationSchemeProvider SchemeProvider { get; }
protected AbpAccountOptions AccountOptions { get; }
protected IdentityDynamicClaimsPrincipalContributorCache IdentityDynamicClaimsPrincipalContributorCache { get; }
public LoginModel(
IExternalProviderService externalProviderService,
IAuthenticationSchemeProvider schemeProvider,
IOptions<AbpAccountOptions> accountOptions,
IOptions<IdentityOptions> identityOptions,
IdentityDynamicClaimsPrincipalContributorCache identityDynamicClaimsPrincipalContributorCache)
: base(schemeProvider, accountOptions, identityOptions, identityDynamicClaimsPrincipalContributorCache)
{
ExternalProviderService = externalProviderService;
SchemeProvider = schemeProvider;
IdentityOptions = identityOptions;
AccountOptions = accountOptions.Value;
IdentityDynamicClaimsPrincipalContributorCache = identityDynamicClaimsPrincipalContributorCache;
}
public async override Task<IActionResult> OnPostAsync(string action)
public virtual async Task<IActionResult> OnGetAsync()
{
LoginInput = new LoginInputModel();
ExternalProviders = await GetExternalProviders();
EnableLocalLogin = await SettingProvider.IsTrueAsync(AccountSettingNames.EnableLocalLogin);
if (IsExternalLoginOnly)
{
return await OnPostExternalLogin(ExternalProviders.First().AuthenticationScheme);
}
return Page();
}
public async virtual Task<IActionResult> OnPostAsync(string action)
{
await CheckLocalLoginAsync();
@ -66,44 +120,17 @@ public class LoginModel : Volo.Abp.Account.Web.Pages.Account.LoginModel
if (result.IsLockedOut)
{
Alerts.Warning(L["UserLockedOutMessage"]);
return Page();
return await HandleUserLockedOut();
}
if (result.IsNotAllowed)
{
var notAllowedUser = await GetIdentityUserAsync(LoginInput.UserNameOrEmailAddress);
if (await UserManager.CheckPasswordAsync(notAllowedUser, LoginInput.Password))
{
// Óû§±ØÐëÐÞ¸ÄÃÜÂë
if (notAllowedUser.ShouldChangePasswordOnNextLogin || await UserManager.ShouldPeriodicallyChangePasswordAsync(notAllowedUser))
{
var changePwdIdentity = new ClaimsIdentity(AbpAccountAuthenticationTypes.ShouldChangePassword);
changePwdIdentity.AddClaim(new Claim(AbpClaimTypes.UserId, notAllowedUser.Id.ToString()));
if (notAllowedUser.TenantId.HasValue)
{
changePwdIdentity.AddClaim(new Claim(AbpClaimTypes.TenantId, notAllowedUser.TenantId.ToString()));
}
await HttpContext.SignInAsync(AbpAccountAuthenticationTypes.ShouldChangePassword, new ClaimsPrincipal(changePwdIdentity));
return RedirectToPage("ChangePassword", new
{
returnUrl = ReturnUrl,
returnUrlHash = ReturnUrlHash,
rememberMe = LoginInput.RememberMe
});
}
}
Alerts.Warning(L["LoginIsNotAllowed"]);
return Page();
return await HandleUserNotAllowed();
}
if (!result.Succeeded)
{
Alerts.Danger(L["InvalidUserNameOrPassword"]);
return Page();
return await HandleUserNameOrPasswordInvalid();
}
//TODO: Find a way of getting user's id from the logged in user and do not query it again like that!
@ -117,7 +144,123 @@ public class LoginModel : Volo.Abp.Account.Web.Pages.Account.LoginModel
return await RedirectSafelyAsync(ReturnUrl, ReturnUrlHash);
}
protected override Task<IActionResult> TwoFactorLoginResultAsync()
public virtual async Task<IActionResult> OnPostExternalLogin(string provider)
{
var redirectUrl = Url.Page("./Login", pageHandler: "ExternalLoginCallback", values: new { ReturnUrl, ReturnUrlHash });
var properties = SignInManager.ConfigureExternalAuthenticationProperties(provider, redirectUrl);
properties.Items["scheme"] = provider;
return await Task.FromResult(Challenge(properties, provider));
}
public virtual async Task<IActionResult> OnGetExternalLoginCallbackAsync(string returnUrl = "", string returnUrlHash = "", string remoteError = null)
{
//TODO: Did not implemented Identity Server 4 sample for this method (see ExternalLoginCallback in Quickstart of IDS4 sample)
/* Also did not implement these:
* - Logout(string logoutId)
*/
if (remoteError != null)
{
Logger.LogWarning($"External login callback error: {remoteError}");
return RedirectToPage("./Login");
}
await IdentityOptions.SetAsync();
var loginInfo = await SignInManager.GetExternalLoginInfoAsync();
if (loginInfo == null)
{
Logger.LogWarning("External login info is not available");
return RedirectToPage("./Login");
}
var result = await SignInManager.ExternalLoginSignInAsync(
loginInfo.LoginProvider,
loginInfo.ProviderKey,
isPersistent: false,
bypassTwoFactor: true
);
if (!result.Succeeded)
{
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{
Identity = IdentitySecurityLogIdentityConsts.IdentityExternal,
Action = "Login" + result
});
}
if (result.IsLockedOut)
{
Logger.LogWarning($"External login callback error: user is locked out!");
throw new UserFriendlyException("Cannot proceed because user is locked out!");
}
if (result.IsNotAllowed)
{
Logger.LogWarning($"External login callback error: user is not allowed!");
throw new UserFriendlyException("Cannot proceed because user is not allowed!");
}
IdentityUser user;
if (result.Succeeded)
{
user = await UserManager.FindByLoginAsync(loginInfo.LoginProvider, loginInfo.ProviderKey);
if (user != null)
{
// Clear the dynamic claims cache.
await IdentityDynamicClaimsPrincipalContributorCache.ClearAsync(user.Id, user.TenantId);
}
return await RedirectSafelyAsync(returnUrl, returnUrlHash);
}
//TODO: Handle other cases for result!
var email = loginInfo.Principal.FindFirstValue(AbpClaimTypes.Email) ?? loginInfo.Principal.FindFirstValue(ClaimTypes.Email);
if (email.IsNullOrWhiteSpace())
{
return RedirectToPage("./Register", new
{
IsExternalLogin = true,
ExternalLoginAuthSchema = loginInfo.LoginProvider,
ReturnUrl = returnUrl
});
}
user = await UserManager.FindByEmailAsync(email);
if (user == null)
{
return RedirectToPage("./Register", new
{
IsExternalLogin = true,
ExternalLoginAuthSchema = loginInfo.LoginProvider,
ReturnUrl = returnUrl
});
}
if (await UserManager.FindByLoginAsync(loginInfo.LoginProvider, loginInfo.ProviderKey) == null)
{
CheckIdentityErrors(await UserManager.AddLoginAsync(user, loginInfo));
}
await SignInManager.SignInAsync(user, false);
await IdentitySecurityLogManager.SaveAsync(new IdentitySecurityLogContext()
{
Identity = IdentitySecurityLogIdentityConsts.IdentityExternal,
Action = result.ToIdentitySecurityLogAction(),
UserName = user.Name
});
// Clear the dynamic claims cache.
await IdentityDynamicClaimsPrincipalContributorCache.ClearAsync(user.Id, user.TenantId);
return await RedirectSafelyAsync(returnUrl, returnUrlHash);
}
protected virtual Task<IActionResult> TwoFactorLoginResultAsync()
{
// ÖØ¶¨ÏòË«ÒòËØÈÏÖ¤Ò³Ãæ
return Task.FromResult<IActionResult>(RedirectToPage("SendCode", new
@ -128,39 +271,117 @@ public class LoginModel : Volo.Abp.Account.Web.Pages.Account.LoginModel
}));
}
protected virtual async Task<IdentityUser> GetIdentityUserAsync(string userNameOrEmailAddress)
{
return await UserManager.FindByNameAsync(LoginInput.UserNameOrEmailAddress) ??
await UserManager.FindByEmailAsync(LoginInput.UserNameOrEmailAddress);
}
protected async override Task<List<ExternalProviderModel>> GetExternalProviders()
protected async virtual Task<List<ExternalLoginProviderModel>> GetExternalProviders()
{
var schemes = await SchemeProvider.GetAllSchemesAsync();
var externalProviders = await ExternalProviderService.GetAllAsync();
var providers = schemes
.Where(x => x.DisplayName != null || x.Name.Equals(AccountOptions.WindowsAuthenticationSchemeName, StringComparison.OrdinalIgnoreCase))
.Select(x => new ExternalProviderModel
{
DisplayName = x.DisplayName,
AuthenticationScheme = x.Name
})
.ToList();
foreach (var provider in providers)
var externalProviderModels = new List<ExternalLoginProviderModel>();
foreach (var scheme in schemes)
{
var localizedDisplayName = L[provider.DisplayName];
if (localizedDisplayName.ResourceNotFound)
if (TryGetExternalLoginProvider(scheme, externalProviders, out var externalLoginProvider) ||
scheme.Name.Equals(AccountOptions.WindowsAuthenticationSchemeName, StringComparison.OrdinalIgnoreCase))
{
localizedDisplayName = L["AuthenticationScheme:" + provider.DisplayName];
externalProviderModels.Add(new ExternalLoginProviderModel
{
Name = externalLoginProvider.Name,
AuthenticationScheme = scheme.Name,
DisplayName = externalLoginProvider.DisplayName,
ComponentType = externalLoginProvider.ComponentType,
});
}
}
if (!localizedDisplayName.ResourceNotFound)
return externalProviderModels;
}
protected virtual bool TryGetExternalLoginProvider(AuthenticationScheme scheme, List<ExternalLoginProviderModel> externalProviders, out ExternalLoginProviderModel externalLoginProvider)
{
if (ReflectionHelper.IsAssignableToGenericType(scheme.HandlerType, typeof(RemoteAuthenticationHandler<>)))
{
externalLoginProvider = externalProviders.FirstOrDefault(x => x.Name == scheme.Name);
return externalLoginProvider != null;
}
externalLoginProvider = null;
return false;
}
protected virtual async Task ReplaceEmailToUsernameOfInputIfNeeds()
{
if (!ValidationHelper.IsValidEmailAddress(LoginInput.UserNameOrEmailAddress))
{
return;
}
var userByUsername = await UserManager.FindByNameAsync(LoginInput.UserNameOrEmailAddress);
if (userByUsername != null)
{
return;
}
var userByEmail = await UserManager.FindByEmailAsync(LoginInput.UserNameOrEmailAddress);
if (userByEmail == null)
{
return;
}
LoginInput.UserNameOrEmailAddress = userByEmail.UserName;
}
protected virtual async Task CheckLocalLoginAsync()
{
if (!await SettingProvider.IsTrueAsync(AccountSettingNames.EnableLocalLogin))
{
throw new UserFriendlyException(L["LocalLoginDisabledMessage"]);
}
}
protected virtual Task<IActionResult> HandleUserLockedOut()
{
Alerts.Warning(L["UserLockedOutMessage"]);
return Task.FromResult<IActionResult>(Page());
}
protected async virtual Task<IActionResult> HandleUserNotAllowed()
{
var notAllowedUser = await GetIdentityUserAsync(LoginInput.UserNameOrEmailAddress);
if (await UserManager.CheckPasswordAsync(notAllowedUser, LoginInput.Password))
{
// Óû§±ØÐëÐÞ¸ÄÃÜÂë
if (notAllowedUser.ShouldChangePasswordOnNextLogin || await UserManager.ShouldPeriodicallyChangePasswordAsync(notAllowedUser))
{
provider.DisplayName = localizedDisplayName.Value;
var changePwdIdentity = new ClaimsIdentity(AbpAccountAuthenticationTypes.ShouldChangePassword);
changePwdIdentity.AddClaim(new Claim(AbpClaimTypes.UserId, notAllowedUser.Id.ToString()));
if (notAllowedUser.TenantId.HasValue)
{
changePwdIdentity.AddClaim(new Claim(AbpClaimTypes.TenantId, notAllowedUser.TenantId.ToString()));
}
await HttpContext.SignInAsync(AbpAccountAuthenticationTypes.ShouldChangePassword, new ClaimsPrincipal(changePwdIdentity));
return RedirectToPage("ChangePassword", new
{
returnUrl = ReturnUrl,
returnUrlHash = ReturnUrlHash,
rememberMe = LoginInput.RememberMe
});
}
}
Alerts.Warning(L["LoginIsNotAllowed"]);
return Page();
}
return providers;
protected virtual Task<IActionResult> HandleUserNameOrPasswordInvalid()
{
Alerts.Danger(L["InvalidUserNameOrPassword"]);
return Task.FromResult<IActionResult>(Page());
}
}

23
aspnet-core/modules/openIddict/LINGYUN.Abp.OpenIddict.WeChat/LINGYUN/Abp/OpenIddict/WeChat/WeChatOffcialTokenExtensionGrant.cs

@ -1,12 +1,7 @@
using LINGYUN.Abp.WeChat.Official;
using LINGYUN.Abp.WeChat.Official.Features;
using LINGYUN.Abp.WeChat.OpenId;
using Microsoft.Extensions.Localization;
using System.Threading.Tasks;
using Volo.Abp;
using Volo.Abp.Features;
using Volo.Abp.OpenIddict.ExtensionGrantTypes;
using Volo.Abp.OpenIddict.Localization;
namespace LINGYUN.Abp.OpenIddict.WeChat;
public class WeChatOffcialTokenExtensionGrant : WeChatTokenExtensionGrant
@ -17,17 +12,17 @@ public class WeChatOffcialTokenExtensionGrant : WeChatTokenExtensionGrant
public override string AuthenticationMethod => AbpWeChatOfficialConsts.AuthenticationMethod;
protected async override Task CheckFeatureAsync(ExtensionGrantContext context)
{
var featureChecker = GetRequiredService<IFeatureChecker>(context);
//protected async override Task CheckFeatureAsync(ExtensionGrantContext context)
//{
// var featureChecker = GetRequiredService<IFeatureChecker>(context);
if (!await featureChecker.IsEnabledAsync(WeChatOfficialFeatures.EnableAuthorization))
{
var localizer = GetRequiredService<IStringLocalizer<AbpOpenIddictResource>>(context);
// if (!await featureChecker.IsEnabledAsync(WeChatOfficialFeatures.EnableAuthorization))
// {
// var localizer = GetRequiredService<IStringLocalizer<AbpOpenIddictResource>>(context);
throw new AbpException(localizer["OfficialAuthorizationDisabledMessage"]);
}
}
// throw new AbpException(localizer["OfficialAuthorizationDisabledMessage"]);
// }
//}
protected async override Task<WeChatOpenId> FindOpenIdAsync(ExtensionGrantContext context, string code)
{

1
aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN.Abp.SettingManagement.Application.csproj

@ -28,6 +28,7 @@
<ItemGroup>
<ProjectReference Include="..\..\account\LINGYUN.Abp.Account.Application.Contracts\LINGYUN.Abp.Account.Application.Contracts.csproj" />
<ProjectReference Include="..\..\account\LINGYUN.Abp.Account.OAuth\LINGYUN.Abp.Account.OAuth.csproj" />
<ProjectReference Include="..\..\identity\LINGYUN.Abp.Identity.Domain.Shared\LINGYUN.Abp.Identity.Domain.Shared.csproj" />
<ProjectReference Include="..\..\..\framework\settings\LINGYUN.Abp.SettingManagement.Application.Contracts\LINGYUN.Abp.SettingManagement.Application.Contracts.csproj" />
</ItemGroup>

10
aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN/Abp/SettingManagement/AbpSettingManagementApplicationModule.cs

@ -1,4 +1,7 @@
using Microsoft.Extensions.DependencyInjection;
using LINGYUN.Abp.Account;
using LINGYUN.Abp.Account.OAuth;
using LINGYUN.Abp.Account.OAuth.Localization;
using Microsoft.Extensions.DependencyInjection;
using Volo.Abp.Application;
using Volo.Abp.Localization;
using Volo.Abp.Modularity;
@ -13,6 +16,8 @@ namespace LINGYUN.Abp.SettingManagement;
typeof(AbpSettingManagementDomainModule),
typeof(AbpSettingManagementApplicationContractsModule),
typeof(VoloAbpSettingManagementApplicationContractsModule),
typeof(AbpAccountApplicationContractsModule),
typeof(AbpAccountOAuthModule),
typeof(AbpDddApplicationModule)
)]
public class AbpSettingManagementApplicationModule : AbpModule
@ -29,7 +34,8 @@ public class AbpSettingManagementApplicationModule : AbpModule
Configure<AbpLocalizationOptions>(options =>
{
options.Resources.Get<AbpSettingManagementResource>()
.AddVirtualJson("/LINGYUN/Abp/SettingManagement/Localization/Resources");
.AddVirtualJson("/LINGYUN/Abp/SettingManagement/Localization/Resources")
.AddBaseTypes(typeof(AccountOAuthResource));
});
}
}

46
aspnet-core/modules/settings/LINGYUN.Abp.SettingManagement.Application/LINGYUN/Abp/SettingManagement/SettingAppService.cs

@ -1,4 +1,6 @@
using LINGYUN.Abp.Identity;
using LINGYUN.Abp.Account.OAuth.Features;
using LINGYUN.Abp.Account.OAuth.Settings;
using LINGYUN.Abp.Identity;
using Microsoft.AspNetCore.Authorization;
using Microsoft.Extensions.Options;
using System.Linq;
@ -489,6 +491,48 @@ public class SettingAppService : ApplicationService, ISettingAppService, ISettin
#endregion
#region 外部登录
var oauthSettingDto = new SettingGroupDto(L["Settings:ExternalOAuthLogin"], L["Settings:ExternalOAuthLogin"]);
if (await FeatureChecker.IsEnabledAsync(true, AccountOAuthFeatureNames.GitHub.Enable))
{
var githubOAuthSetting = oauthSettingDto.AddSetting(L["Settings:GitHubAuth"], L["Settings:GitHubAuth"]);
githubOAuthSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AccountOAuthSettingNames.GitHub.ClientId),
StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AccountOAuthSettingNames.GitHub.ClientId, providerName, providerKey),
ValueType.String,
providerName);
githubOAuthSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AccountOAuthSettingNames.GitHub.ClientSecret),
StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AccountOAuthSettingNames.GitHub.ClientSecret, providerName, providerKey),
ValueType.String,
providerName);
}
if (await FeatureChecker.IsEnabledAsync(true, AccountOAuthFeatureNames.Bilibili.Enable))
{
var bilibiliOAuthSetting = oauthSettingDto.AddSetting(L["Settings:BilibiliAuth"], L["Settings:BilibiliAuth"]);
bilibiliOAuthSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AccountOAuthSettingNames.Bilibili.ClientId),
StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AccountOAuthSettingNames.Bilibili.ClientId, providerName, providerKey),
ValueType.String,
providerName);
bilibiliOAuthSetting.AddDetail(
await SettingDefinitionManager.GetAsync(AccountOAuthSettingNames.Bilibili.ClientSecret),
StringLocalizerFactory,
await SettingManager.GetOrNullAsync(AccountOAuthSettingNames.Bilibili.ClientSecret, providerName, providerKey),
ValueType.String,
providerName);
}
settingGroups.AddGroup(oauthSettingDto);
#endregion
return settingGroups;
}

Loading…
Cancel
Save