c# - 基于 C# Web Api Facebook 令牌的身份验证
问题描述
我正在尝试将 Facebook 身份验证添加到具有默认 web api 模板的 C# web api 项目中,该模板应该与单独的 Javascript web 界面(使用 React)一起使用。但是,我遇到了无法将授权令牌从后端传递到前端的问题。有什么合适的方法吗?
**
详细描述我到目前为止所取得的成就:
**
前端端口为 3000,后端端口为 44378。
我使用的顺序如下:
1) 首先,获取所有可用的登录提供程序
GET /api/Account/ExternalLogins?returnUrl=%2F&generateState=true
2) 然后,使用与 Facebook 提供商关联的 Url
/api/Account/ExternalLogin?provider=Facebook&response_type=token&redirect_uri=https%3A%2F%2Flocalhost%3A44378%2F&state=KXiWds49DMtXLqwrPFsfvus6VfJRh4Gr5dQFq5Q10nE1
从这里,我们得到几个重定向到 Facebook 并返回到本地后端,如下所示:
在此之后,地址如下所示:
https://localhost:44378/#access_token=[...]&token_type=bearer&expires_in=1209600&state=qrnh0GIG8ZTWTGh4e603gWLaE7E3GBUK-7dLURg6vus1
据我所知,这是一个与 Facebook 没有直接联系的本地访问令牌。
3)这就是我遇到死胡同的地方。重定向 URL 位于后端,因此前端无法访问此令牌。如果我手动将令牌作为Authorization: Bearer复制粘贴到请求标头中,我可以访问 Web Api,但它不会传递回前端组件,所以我被卡在那里。
需要注意的是,在所有重定向之后,后端根据用户是否拥有本地帐户设置 cookie:如果他没有,则为.AspNet.ExternalCookie ,如果他有,则为 .AspNet.Cookies,但我没有无法为它们找到任何用途。
那么问题来了:有没有办法将本地访问令牌传递给前端组件?
为了完整起见,以下是一些相关的代码部分:
启动.Auth.cs
using System;
using Microsoft.AspNet.Identity;
using Microsoft.Owin;
using Microsoft.Owin.Security.Cookies;
using Microsoft.Owin.Security.Facebook;
using Microsoft.Owin.Security.OAuth;
using Owin;
using WebApplication4.Providers;
using WebApplication4.Models;
namespace WebApplication4
{
public partial class Startup
{
public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }
public static string PublicClientId { get; private set; }
public void ConfigureAuth(IAppBuilder app)
{
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create);
app.UseCookieAuthentication(new CookieAuthenticationOptions());
app.UseExternalSignInCookie(DefaultAuthenticationTypes.ExternalCookie);
// Configure the application for OAuth based flow
PublicClientId = "self";
OAuthOptions = new OAuthAuthorizationServerOptions
{
TokenEndpointPath = new PathString("/Token"),
Provider = new ApplicationOAuthProvider(PublicClientId),
AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),
AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),
// In production mode set AllowInsecureHttp = false
AllowInsecureHttp = true
};
var facebookOptions = new FacebookAuthenticationOptions()
{
AppId = "*",
AppSecret = "*", //codes hidden
};
app.UseFacebookAuthentication(facebookOptions);
}
}
}
AccountController.cs - 只是 ExternalLogin 方法
[OverrideAuthentication]
[HostAuthentication(DefaultAuthenticationTypes.ExternalCookie)]
[AllowAnonymous]
[Route("ExternalLogin", Name = "ExternalLogin")]
public async Task<IHttpActionResult> GetExternalLogin(string provider, string error = null)
{
if (error != null)
{
return Redirect(Url.Content("~/") + "#error=" + Uri.EscapeDataString(error));
}
if (!User.Identity.IsAuthenticated)
{
return new ChallengeResult(provider, this);
}
ExternalLoginData externalLogin = ExternalLoginData.FromIdentity(User.Identity as ClaimsIdentity);
if (externalLogin == null)
{
return InternalServerError();
}
if (externalLogin.LoginProvider != provider)
{
Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
return new ChallengeResult(provider, this);
}
ApplicationUser user = await UserManager.FindAsync(new UserLoginInfo(externalLogin.LoginProvider,
externalLogin.ProviderKey));
bool hasRegistered = user != null;
if (hasRegistered)
{
Authentication.SignOut(DefaultAuthenticationTypes.ExternalCookie);
ClaimsIdentity oAuthIdentity = await user.GenerateUserIdentityAsync(UserManager,
OAuthDefaults.AuthenticationType);
ClaimsIdentity cookieIdentity = await user.GenerateUserIdentityAsync(UserManager,
CookieAuthenticationDefaults.AuthenticationType);
AuthenticationProperties properties = ApplicationOAuthProvider.CreateProperties(user.UserName);
Authentication.SignIn(properties, oAuthIdentity, cookieIdentity);
}
else
{
IEnumerable<Claim> claims = externalLogin.GetClaims();
ClaimsIdentity identity = new ClaimsIdentity(claims, OAuthDefaults.AuthenticationType);
Authentication.SignIn(identity);
}
return Ok();
}
解决方案
推荐阅读
- pytorch - 我可以在 Seldon 上部署 PyTorch 训练的模型吗?
- python - 无法在 Pycharm 中和通过苹果 m1 上的 cli 安装包 scikit-learn
- r - 如何将具有多列的数据框从宽转换为长
- local-storage - 关闭浏览器/选项卡时需要清除 localStorage,刷新选项卡时不需要
- python - 如何从列表中删除方括号和撇号
- java - 分离数据之间的分页
- javascript - 即使值为 false 也会执行带有 if 的 JavaScript 布尔变量
- drake - 记录抽象值输出端口
- asp.net - Asp.net core 5:json响应返回网站HTML
- python - aws lambda datadog 集成导入问题