我正在尝试通过Google对用户进行身份验证。 我正在使用带有Vue的ASP.NET Core的ABP启动模板。
这是我到目前为止所做的:
我在Web.Core中创建了一个GoogleAuthProviderApi
:
using System;
using System.Net.Http;
using System.Net.Http.Headers;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authentication.Google;
using Newtonsoft.Json.Linq;
namespace Mindbus.MindbooksSEO.Authentication.External.Google
{
public class GoogleAuthProviderApi : ExternalAuthProviderApiBase
{
public const string Name = "Google";
public override async Task<ExternalAuthUserInfo> GetUserInfo(string accessCode)
{
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.UserAgent.ParseAdd("Microsoft ASP.NET Core OAuth middleware");
client.DefaultRequestHeaders.Accept.ParseAdd("application/json");
client.Timeout = TimeSpan.FromSeconds(30);
client.MaxResponseContentBufferSize = 1024 * 1024 * 10; // 10 MB
var request = new HttpRequestMessage(HttpMethod.Get, GoogleDefaults.UserInformationEndpoint);
request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", accessCode);
var response = await client.SendAsync(request);
response.EnsureSuccessStatusCode();
var payload = JObject.Parse(await response.Content.ReadAsStringAsync());
return new ExternalAuthUserInfo
{
//Name = GoogleHelper.GetName(payload),
EmailAddress = GoogleHelper.GetEmail(payload),
//Surname = GoogleHelper.GetFamilyName(payload),
//ProviderKey = GoogleHelper.GetId(payload),
Provider = Name
};
}
}
}
}
我在Web.Host中的 AuthConfigurer.cs 中注册了Google外部身份验证:
if (bool.Parse(configuration["Authentication:Google:IsEnabled"]))
{
services.AddAuthentication().AddGoogle(googleOptions =>
{
googleOptions.ClientId = configuration["Authentication:Google:ClientId"];
googleOptions.ClientSecret = configuration["Authentication:Google:ClientSecret"];
});
}
我已将设置添加到Web.Host中的 appsettings.json ,并创建了相应的机密( ClientId 和 ClientSecret )秘密管理器工具。
我已使用RequireHttpsAttribute
强制API进行SSL。
我在 [ProjectName] WebCoreModule.cs 中注册了GoogleAuthProviderApi
:
public override void PreInitialize()
{
Configuration.DefaultNameOrConnectionString = _appConfiguration.GetConnectionString(
MindbooksSEOConsts.ConnectionStringName
);
// Use database for language management
Configuration.Modules.Zero().LanguageManagement.EnableDbLocalization();
Configuration.Modules.AbpAspNetCore()
.CreateControllersForAppServices(
typeof(MindbooksSEOApplicationModule).GetAssembly()
);
ConfigureTokenAuth();
Configuration.Modules.Zero().UserManagement.ExternalAuthenticationSources.Add<GoogleAuthProviderApi>();
}
我不知道我在这里缺少什么,也不知道到底会发生什么。
我原本以为调用 api / TokenAuth / GetExternalAuthenticationProviders 端点至少会给我一个包含Google的列表,但是这个请求在结果中返回一个空数组。 / p>
此外,对于我来说,这种外部身份验证的范围有点不明确,例如Google和Facebook等OAuth提供商。在我看来,您要么使用OAuth进行服务器端使用,在这种情况下,我不明白为什么要通过API公开部分内容。或者您拥有适用于JavaScript网络应用程序的OAuth,在这种情况下,您不需要在自己的服务器上使用API端点,只需通过Web应用程序处理整个客户端。
那么,External Authenticate API端点的确切目的是什么?是否您自己的服务器充当身份验证的代理?这样您可以同时使用外部(Google)API的客户端和服务器端使用吗?
评论要求我补充一些说明。
#1 :如果我在Postman中添加Abp.TenantId
标题,则回复保持不变:
GET /api/TokenAuth/GetExternalAuthenticationProviders HTTP/1.1
Host: localhost:44300
Accept: application/json
Abp.TenantId: 2
Cache-Control: no-cache
Postman-Token: 0cb72e57-4b9a-474d-b60d-492fa727a7a2
#2 :Swagger中的控制台“欺骗”会导致错误:
abp.swagger.login()
undefined
VM40:49 POST https://localhost:44300/api/TokenAuth/Authenticate 500 ()
abp.swagger.login @ VM40:49
(anonymous) @ VM84:1
abp.swagger.addAuthToken()
false
我认为GoogleAuthProviderApi
有问题。在我对所有CLR异常进行调试器中断后,我发现了以下错误:
'Mindbus.MindbooksSEO.Authentication.External.Google.GoogleAuthProviderApi' to type
'Abp.Authorization.Users.IExternalAuthenticationSource`2
[Mindbus.MindbooksSEO.MultiTenancy.Tenant,
Mindbus.MindbooksSEO.Authorization.Users.User]'.'
答案 0 :(得分:4)
请注意,Social Login 提供商(例如Google)的配置与External Authentication 来源(例如LDAP)完全不同。所以,删除这一行:
Configuration.Modules.Zero().UserManagement.ExternalAuthenticationSources.Add<GoogleAuthProviderApi>();
观察GetExternalAuthenticationProviders
查看IExternalAuthConfiguration
因此,在IExternalAuthConfiguration
的{{1}}方法中配置PostInitialize
:
*WebHostModule
虽然上述处理社交登录提供程序的方式可能有效,但它是no longer recommended。
内置if (bool.Parse(configuration["Authentication:Google:IsEnabled"]))
{
var externalAuthConfiguration = IocManager.Resolve<IExternalAuthConfiguration>();
externalAuthConfiguration.Providers.Add(
new ExternalLoginProviderInfo(
GoogleAuthProviderApi.Name,
configuration["Authentication:Google:ClientId"],
configuration["Authentication:Google:ClientSecret"],
typeof(GoogleAuthProviderApi)
)
);
}
方式:
.AddGoogle
...意在与:
一起使用if (bool.Parse(configuration["Authentication:Google:IsEnabled"]))
{
services.AddAuthentication().AddGoogle(googleOptions =>
{
googleOptions.ClientId = configuration["Authentication:Google:ClientId"];
googleOptions.ClientSecret = configuration["Authentication:Google:ClientSecret"];
});
}
获得外部身份验证计划的方法是:
var result = await _signInManager.ExternalLoginSignInAsync(
info.LoginProvider,
info.ProviderKey,
isPersistent: false,
bypassTwoFactor : true
);
您可以修改var schemes = (await _signInManager.GetExternalAuthenticationSchemesAsync()).ToList();
以返回此数据。
答案 1 :(得分:0)
对于那些访问此主题却找不到答案的人(如我)。
aspnetcore 2.2和abp 4.5.0 Facebook工作示例
* WebHostModule.cs
public override void PostInitialize()
{
var externalAuthConfiguration = IocManager.Resolve<IExternalAuthConfiguration>();
externalAuthConfiguration.Providers.Add(
new ExternalLoginProviderInfo(
FacebookAuthProvider.Name,
configuration["Authentication:Facebook:ClientId"],
configuration["Authentication:Facebook:Secret"],
typeof(FacebookAuthProvider)
)
);
}
* FacebookAuthProvider.cs
public class FacebookAuthProvider: ExternalAuthProviderApiBase
{
private static readonly HttpClient Client = new HttpClient();
public const string Name = "Facebook";
public override async Task<ExternalAuthUserInfo> GetUserInfo(string accessCode)
{
//gen app access token
var appAccessTokenResponse = await Client.GetStringAsync("https://graph.facebook.com/oauth/access_token" +
"?client_id=" + ProviderInfo.ClientId +
"&client_secret=" + ProviderInfo.ClientSecret +
"&grant_type=client_credentials");
var appAccessToken = JsonConvert.DeserializeObject<FacebookAppAccessToken>(appAccessTokenResponse);
//validate user access token
var userAccessTokenValidationResponse = await Client.GetStringAsync("https://graph.facebook.com/v3.2/debug_token" +
"?input_token="+ accessCode +
"&access_token="+ appAccessToken.AccessToken);
var userAccessTokenValidation = JsonConvert.DeserializeObject<FacebookUserAccessTokenValidation>(userAccessTokenValidationResponse);
if (!userAccessTokenValidation.Data.IsValid)
{
throw new ArgumentException("login_failure Invalid facebook token.");
}
//get userinfo
var userInfoResponse = await Client.GetStringAsync($"https://graph.facebook.com/v3.2/me?fields=id,email,first_name,last_name&access_token={accessCode}");
var userInfo = JsonConvert.DeserializeObject<FacebookUserData>(userInfoResponse);
return new ExternalAuthUserInfo
{
Name = userInfo.FirstName,
EmailAddress = userInfo.Email,
Surname=userInfo.LastName,
Provider=Name,
ProviderKey=userInfo.Id.ToString()
};
}
}
模型
internal class FacebookUserData
{
public long Id { get; set; }
public string Email { get; set; }
public string Name { get; set; }
[JsonProperty("first_name")]
public string FirstName { get; set; }
[JsonProperty("last_name")]
public string LastName { get; set; }
public string Gender { get; set; }
public string Locale { get; set; }
public FacebookPictureData Picture { get; set; }
}
internal class FacebookPictureData
{
public FacebookPicture Data { get; set; }
}
internal class FacebookPicture
{
public int Height { get; set; }
public int Width { get; set; }
[JsonProperty("is_silhouette")]
public bool IsSilhouette { get; set; }
public string Url { get; set; }
}
internal class FacebookUserAccessTokenData
{
[JsonProperty("app_id")]
public long AppId { get; set; }
public string Type { get; set; }
public string Application { get; set; }
[JsonProperty("expires_at")]
public long ExpiresAt { get; set; }
[JsonProperty("is_valid")]
public bool IsValid { get; set; }
[JsonProperty("user_id")]
public long UserId { get; set; }
}
internal class FacebookUserAccessTokenValidation
{
public FacebookUserAccessTokenData Data { get; set; }
}
internal class FacebookAppAccessToken
{
[JsonProperty("token_type")]
public string TokenType { get; set; }
[JsonProperty("access_token")]
public string AccessToken { get; set; }
}