如何在ASP.NET Core 2中对Facebook Web API进行身份验证

我目前正在Xamarin.Forms中构建我的第一个移动应用程序。该应用程序具有Facebook登录名,并且在用户登录后,我存储了Facebook令牌,因为我想将其用作承载令牌,以验证针对API的任何其他请求。

该API是一个.NET Core 2.0项目,我正在努力使身份验证正常工作。

在我的Xamarin.Forms应用程序中,使用以下代码将facebook令牌设置为不记名令牌;

_httpClient.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", UserToken);

据我所知,这可以在请求的标头中正确设置承载令牌。我已经和我的一位同事讨论过这个问题,他告诉我看一下应该支持这一点的Identityserver4。但是现在,我决定不执行此操作,因为对于我来说,现在,实施此操作开销很大。因此,我决定保留使用Facebook令牌作为不记名令牌的想法,并对此进行验证。

因此,对我来说,下一步就是找到一种方法,用Facebook验证传入的承载令牌,以检查它是否仍然有效。因此,我为API项目配置了启动方式,如下所示;

public class Startup
{
    public Startup(IConfiguration configuration)
    {
        Configuration = configuration;
    }

    public IConfiguration Configuration { get; }

    // This method gets called by the runtime. Use this method to add services to the container.
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddAuthentication(o =>
        {
            o.DefaultAuthenticateScheme = JwtBearerDefaults.AuthenticationScheme;
            o.DefaultChallengeScheme = JwtBearerDefaults.AuthenticationScheme;
        }).AddFacebook(o =>
        {
            o.AppId = "MyAppId";
            o.AppSecret = "MyAppSecret";
        });

        services.AddMvc();
    }

    // This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        if (env.IsDevelopment())
        {
            app.UseDeveloperExceptionPage();
        }

        //Enable authentication
        app.UseAuthentication();

        //Enable support for default files (eg. default.htm, default.html, index.htm, index.html)
        app.UseDefaultFiles();

        //Configure support for static files
        app.UseStaticFiles();

        app.UseMvc();
    }
}

但是,当我使用邮递员发出请求并测试是否一切正常时,我收到以下错误;

InvalidOperationException: No authenticationScheme was specified, and there was no DefaultChallengeScheme found.

我在这里做错了什么?

编辑:在此同时,如果正忙于尝试为此找到解决方案。在Google上阅读了很多书之后,目前看来,添加AuthorizationHandler是可行的。从那里,我可以向Facebook发出请求,以检查令牌是否有效。我已经将以下代码添加到我的ConfigureServices方法中;

public void ConfigureServices(IServiceCollection services)
    {
        //Other code

        services.AddAuthorization(options =>
        {
            options.AddPolicy("FacebookAuthentication", policy => policy.Requirements.Add(new FacebookRequirement()));
        });

        services.AddMvc();
    }

而且我创建了一个FacebookRequirement,它将帮助我处理该政策;

public class FacebookRequirement : AuthorizationHandler<FacebookRequirement>, IAuthorizationRequirement
    {
        private readonly IHttpContextAccessor contextAccessor;
        public FacebookRequirement(IHttpContextAccessor contextAccessor)
        {
            this.contextAccessor = contextAccessor;
        }

        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FacebookRequirement requirement)
        {
            //var socialConfig = new SocialConfig{Facebook = new SocialApp{AppId = "MyAppId", AppSecret = "MyAppSecret" } };
            //var socialservice = new SocialAuthService(socialConfig);

            //var result = await socialservice.VerifyFacebookTokenAsync()
            var httpContext = contextAccessor.HttpContext;

            if (httpContext != null && httpContext.Request.Headers.ContainsKey("Authorization"))
            {
                var token = httpContext.Request.Headers.Where(x => x.Key == "Authorization").ToList();
            }

            context.Succeed(requirement);

            return Task.FromResult(0);
        }
    }

我现在遇到的问题是我不知道从哪里获取IHttpContextAccessor。这是以某种方式注入的吗?我什至在解决这个问题的正确道路上吗?

我最终创建了自己的AuthorizationHandler,以使用承载令牌验证针对Facebook的传入请求。将来,我可能会开始使用Identityserver处理多种登录类型。但就目前而言,facebook已经足够。

以下是将来参考的解决方案。

首先创建一个FacebookRequirement继承自AuthorizationHandler

public class FacebookRequirement : AuthorizationHandler<FacebookRequirement>, IAuthorizationRequirement
    {
        protected override Task HandleRequirementAsync(AuthorizationHandlerContext context, FacebookRequirement requirement)
        {
            var socialConfig = new SocialConfig { Facebook = new SocialApp { AppId = "<FacebookAppId>", AppSecret = "<FacebookAppSecret>" } };
            var socialservice = new SocialAuthService(socialConfig);

            var authorizationFilterContext = context.Resource as AuthorizationFilterContext;
            if (authorizationFilterContext == null)
            {
                context.Fail();
                return Task.FromResult(0);
            }

            var httpContext = authorizationFilterContext.HttpContext;
            if (httpContext != null && httpContext.Request.Headers.ContainsKey("Authorization"))
            {
                var authorizationHeaders = httpContext.Request.Headers.Where(x => x.Key == "Authorization").ToList();
                var token = authorizationHeaders.FirstOrDefault(header => header.Key == "Authorization").Value.ToString().Split(' ')[1];

                var user = socialservice.VerifyTokenAsync(new ExternalToken { Provider = "Facebook", Token = token }).Result;
                if (!user.IsVerified)
                {
                    context.Fail();
                    return Task.FromResult(0);
                }

                context.Succeed(requirement);
                return Task.FromResult(0);
            }

            context.Fail();
            return Task.FromResult(0);
        }
    }

添加以下类,其中将包含代表用户的配置;

public class SocialConfig
    {
        public SocialApp Facebook { get; set; }
    }

    public class SocialApp
    {
        public string AppId { get; set; }
        public string AppSecret { get; set; }
    }

    public class User
    {
        public Guid Id { get; set; }
        public string SocialUserId { get; set; }
        public string Email { get; set; }
        public bool IsVerified { get; set; }
        public string Name { get; set; }

        public User()
        {
            IsVerified = false;
        }
    }

    public class ExternalToken
    {
        public string Provider { get; set; }
        public string Token { get; set; }
    }

最后但并非最不重要的一点是SocialAuthService,将通过facebook处理请求类;

public class SocialAuthService
    {
        private SocialConfig SocialConfig { get; set; }

        public SocialAuthService(SocialConfig socialConfig)
        {
            SocialConfig = socialConfig;
        }

        public async Task<User> VerifyTokenAsync(ExternalToken exteralToken)
        {
            switch (exteralToken.Provider)
            {
                case "Facebook":
                    return await VerifyFacebookTokenAsync(exteralToken.Token);
                default:
                    return null;
            }
        }

        private async Task<User> VerifyFacebookTokenAsync(string token)
        {
            var user = new User();
            var client = new HttpClient();

            var verifyTokenEndPoint = string.Format("https://graph.facebook.com/me?access_token={0}&fields=email,name", token);
            var verifyAppEndpoint = string.Format("https://graph.facebook.com/app?access_token={0}", token);

            var uri = new Uri(verifyTokenEndPoint);
            var response = await client.GetAsync(uri);

            if (response.IsSuccessStatusCode)
            {
                var content = await response.Content.ReadAsStringAsync();
                dynamic userObj = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(content);

                uri = new Uri(verifyAppEndpoint);
                response = await client.GetAsync(uri);
                content = await response.Content.ReadAsStringAsync();
                dynamic appObj = (Newtonsoft.Json.Linq.JObject)Newtonsoft.Json.JsonConvert.DeserializeObject(content);

                if (appObj["id"] == SocialConfig.Facebook.AppId)
                {
                    //token is from our App
                    user.SocialUserId = userObj["id"];
                    user.Email = userObj["email"];
                    user.Name = userObj["name"];
                    user.IsVerified = true;
                }

                return user;
            }
            return user;
        }
    }

这将验证来自请求的Facebook令牌是否为承载令牌,并由Facebook检查其是否仍然有效。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

ASP.NET Core Web API Facebook JWT身份验证

使用 ASP.NET Core Web API 的 Facebook JWT 身份验证

ASP.NET Core Web API身份验证

Google身份验证ASP.NET Core Web Api

ASP.NET Core Web API + Angular 2授权和身份验证

当使用ASP.NET Core Web API中没有身份的cookie身份验证时,如何在登录时刷新CSRF令牌

使用ASP.NET Web API 2进行身份验证

使用 ASP.NET Web API 2 进行外部身份验证 - Microsoft 现在不工作

考虑到以下所述的错误,人们如何在Ubuntu / Docker上的ASP.NET Core Web API中进行身份验证?

如何使用ASP.NET身份在Web API 2中实现两因素身份验证?

如何在ASP.NET Core Web API中的每种方法中进行模型验证?

ASP.NET Web API中的用户身份验证

ASP.NET 5中的Web API身份验证

如何使用Postman使用Cookie身份验证测试ASP.NET Core Web API?

在测试过程中跳过JWT身份验证ASP.Net Core 3.1 Web Api

ASP.NET Web API 2-如何在默认VS 2013模板中启用基本身份验证?

如何在Web API Core 2中支持多种身份验证方案?

如何在ASP.NET Core 2中添加身份验证Cookie超时

使用 ASP.Net Core 2 中的 cookie(无 DB)进行 Google 身份验证

在.NET Core Web API中使用自定义属性进行JWT身份验证

使用.NET Core Web API和React进行Active Directory身份验证

.NET Core Web Api Azure AD和Swagger不进行身份验证

自定义身份验证ASP.NET Core Web API

Asp Net Core (2.1) WebApp - API 和 Web 界面的身份验证

Web 应用程序和 API AzureAD 身份验证流程 ASP.NET Core

响应 JWT 错误的身份验证 Asp.Net Core Web Api

Asp.net Core Web API-当前用户和Windows身份验证

静态文件 - asp.net web api core 2.1 身份验证方案承载

我们如何在ASP.NET Web API中记录身份验证令牌请求