我有一个项目(项目 A),它是一个 .NET CORE API 项目,它使用 Openiddict 和 /connect/token 端点来使用 Identity 发布 JWT 令牌来处理安全性等。这个项目按原样工作得很好。
我有另一个项目(项目 B),它只是一个非常简单的项目,其中包含一些 HTML,它向 API 发出请求以获取访问令牌,并从 API 获取数据。这个项目也很好用。
现在我无法绕开我的大脑,我如何在这两个完全独立的项目之间使用 Facebook 登录?如果一切都在一个屋檐下,我知道如何使用它,这真的很容易,但是这种情况让我完全困惑,因为一切都是分开的。那么对于初学者来说,谁处理“ExternalLogin”、“ExternalLoginCallBack”逻辑(来自使用个人帐户的 .NET Web 模板)、API?HTML 项目?与 Facebook 连接时,我应该使用什么重定向 uri(API/HTML 项目)?那么谁应该在他们的“Startup.cs”文件中包含以下代码?
app.UseFacebookAuthentication(new FacebookOptions
{
AppId = "xxxxxxx",
AppSecret = "xxxxxxxxx",
Scope = { "email", "user_friends" },
Fields = { "name", "email" },
SaveTokens = true,
});
最后,如果这有帮助,那么我目前如何设置项目 A:
启动.CS (API)
公共无效配置服务功能:(API)
// add entity framework using the config connection string
services.AddEntityFrameworkSqlServer()
.AddDbContext<ApplicationDbContext>(options =>
options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")));
// add identity
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<ApplicationDbContext>()
.AddDefaultTokenProviders();
// add OpenIddict
services.AddOpenIddict<ApplicationUser, ApplicationRole, ApplicationDbContext>()
.DisableHttpsRequirement()
.EnableTokenEndpoint("/connect/token")
.AllowPasswordFlow()
.AllowRefreshTokenFlow()
.UseJsonWebTokens()
.AddEphemeralSigningKey();
services.AddCors();
公共无效配置功能:(API)
app.UseJwtBearerAuthentication(new JwtBearerOptions
{
AutomaticAuthenticate = true,
AutomaticChallenge = true,
RequireHttpsMetadata = false,
Audience = "http://localhost:54418/",
Authority = "http://localhost:54418/"
});
授权控制器 (API)
public class AuthorizationController : Controller
{
private OpenIddictUserManager<ApplicationUser> _userManager;
public AuthorizationController(OpenIddictUserManager<ApplicationUser> userManager)
{
_userManager = userManager;
}
[HttpPost("~/connect/token")]
[Produces("application/json")]
public async Task<IActionResult> Exchange()
{
var request = HttpContext.GetOpenIdConnectRequest();
if (request.IsPasswordGrantType())
{
var user = await _userManager.FindByNameAsync(request.Username);
if (user == null)
{
return BadRequest(new OpenIdConnectResponse
{
ErrorDescription = "The username or password provided is incorrect"
});
}
var identity = await _userManager.CreateIdentityAsync(user, request.GetScopes());
// Add a custom claim that will be persisted
// in both the access and the identity tokens.
if (user.Avatar != null)
{
identity.AddClaim("user_avatar", user.Avatar,
OpenIdConnectConstants.Destinations.AccessToken,
OpenIdConnectConstants.Destinations.IdentityToken);
}
if (user.InSiteUserName != null)
{
identity.AddClaim("insite_username", user.InSiteUserName,
OpenIdConnectConstants.Destinations.AccessToken,
OpenIdConnectConstants.Destinations.IdentityToken);
}
identity.AddClaim("hasLoggedIn", user.HasLoggedIn.ToString(),
OpenIdConnectConstants.Destinations.AccessToken,
OpenIdConnectConstants.Destinations.IdentityToken);
// Create a new authentication ticket holding the user identity.
var ticket = new AuthenticationTicket(
new ClaimsPrincipal(identity),
new AuthenticationProperties(),
OpenIdConnectServerDefaults.AuthenticationScheme);
ticket.SetResources(request.GetResources());
ticket.SetScopes(request.GetScopes());
return SignIn(ticket.Principal, ticket.Properties, ticket.AuthenticationScheme);
}
return BadRequest(new OpenIdConnectResponse
{
Error = OpenIdConnectConstants.Errors.UnsupportedGrantType,
ErrorDescription = "The specified grant type is not supported."
});
}
}
}
我不知道它是否包含项目 B 中的任何内容,因为它非常基本/裸露,并且一切都依赖于 API。
我知道这是一个复杂而复杂的问题,而且我确信我没有尽可能流畅地提出它,所以我提前为此道歉,就像我之前说的那样,我很困惑。谢谢!