首页 > 解决方案 > 基于 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();
}

标签: c#facebookowin

解决方案


推荐阅读