简体   繁体   English

如何在asp.net core 2中验证facebook web api

[英]How to authenticate facebook web api in asp.net core 2

I'm currently building my very first mobile app in Xamarin.Forms.我目前正在 Xamarin.Forms 中构建我的第一个移动应用程序。 The app has a facebook login and after the user has been logged in I'm storing the facebook token because I want to use it as a bearer-token to authenticate any further requests against an API.该应用程序具有 facebook 登录名,在用户登录后,我将存储 facebook 令牌,因为我想将其用作不记名令牌来验证针对 API 的任何进一步请求。

The API is a .NET core 2.0 project and I am struggling to get the authentication working. API 是一个 .NET 核心 2.0 项目,我正在努力使身份验证正常工作。

In my Xamarin.Forms app the facebook token is set as bearer-token with the following code;在我的 Xamarin.Forms 应用程序中,使用以下代码将 facebook 令牌设置为不记名令牌;

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

As far as I know, this properly sets the bearer token in the headers of the request.据我所知,这在请求的标头中正确设置了不记名令牌。 I've talked to a colleague of mine about this and he told me to take a look at Identityserver4 which should support this.我已经和我的一位同事谈过这件事,他告诉我看看应该支持这一点的 Identityserver4。 But for now, I've decided not to do that since for me, at this moment, it is overhead to implement this.但就目前而言,我决定不这样做,因为对我而言,此时此刻,实现这一点是开销。 So I've decided to stay with the idea to use the facebook token as bearer token and validate this.所以我决定保留使用 facebook 令牌作为不记名令牌并验证这一点的想法。

So the next step for me is to find a way to authenticate the incoming bearer token with Facebook to check if it is (still) valid.所以我的下一步是找到一种方法来验证传入的不记名令牌与 Facebook 以检查它是否(仍然)有效。 So I've configured the startup for my API projects as following;所以我为我的 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();
    }
}

But when I'm using postman to do a request and test if everything is working I'm receiving the following error;但是当我使用邮递员进行请求并测试一切是否正常时,我收到以下错误;

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

What am I doing wrong here?我在这里做错了什么?

EDIT: In the mean time if been busy trying to find a solution for this.编辑:同时,如果忙于为此寻找解决方案。 After reading a lot on Google it seems thatadding an AuthorizationHandler is the way to go at the moment.在谷歌上阅读了很多之后,似乎添加 AuthorizationHandler 是目前的方法。 From there on I can make request to facebook to check if the token is valid.从那时起,我可以向 Facebook 发出请求以检查令牌是否有效。 I've added the following code to my ConfigureServices method;我已将以下代码添加到我的 ConfigureServices 方法中;

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

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

        services.AddMvc();
    }

And I've created a FacebookRequirement which will help me handling the policy;我创建了一个 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);
        }
    }

The problem I'm running into now is that I don't know where to get the IHttpContextAccessor.我现在遇到的问题是我不知道从哪里获得 IHttpContextAccessor。 Is this being injected somehow?这是以某种方式注入的吗? Am I even on the right path to solve this issue?我是否走在解决这个问题的正确道路上?

I ended up creating my own AuthorizationHandler to validate incoming requests against facebook using bearer tokens.我最终创建了自己的 AuthorizationHandler 以使用不记名令牌验证针对 Facebook 的传入请求。 In the future I'll probably start using Identityserver to handle multiple login types.将来我可能会开始使用 Identityserver 来处理多种登录类型。 But for now facebook is sufficient.但是现在facebook就足够了。

Below is the solution for future references.以下是供将来参考的解决方案。

First create an FacebookRequirement class inheriting from AuthorizationHandler ;首先创建一个继承自AuthorizationHandlerFacebookRequirement类;

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);
        }
    }

Add the following classes which will contain the configuration an represent the user;添加以下类,这些类将包含代表用户的配置;

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; }
    }

And last but not least, the SocialAuthService class which will handle the requests with facebook;最后但并非最不重要的是, 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;
        }
    }

This will validate the Facebook token coming from the request as bearer token, with Facebook to check if it's still valid.这将验证来自请求的 Facebook 令牌作为不记名令牌,由 Facebook 来检查它是否仍然有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 使用ASP.NET Core Web API进行Facebook JWT身份验证 - Facebook JWT authentication using ASP.NET Core Web API asp.net Web API-如何验证用户 - asp.net web api - How to authenticate user 如何在.Net Core API中验证Facebook JWT - How to authenticate Facebook JWT in .Net Core API 使用Azure Active Directory验证ASP.NET Core 2.1 Web API和使用Entity Framework验证Azure SQL - Authenticate ASP.NET Core 2.1 Web API with Azure Active Directory and Azure SQL with Entity Framework ASP.NET Core Web API - 无法验证 - 获取 401 - - ASP.NET Core Web API - can't authenticate - Getting 401 - 从 React Native 访问 ASP.NET Core 2.1 Web API 时“无法对 HTTPS 连接进行身份验证” - 'Failed to authenticate HTTPS connection' while accessing ASP.NET Core 2.1 Web API from React Native 如何从 ASP.NET 核心 mvc 向 ASP.NET 核心中的 Web API 发出 PUT 请求? - How to make a PUT request from ASP.NET core mvc to Web API in asp.net core? Facebook取消授权ASP.NET Web API - Facebook Deauthorization ASP.NET Web API ASP.NET 核心 API 使用 JWT 不记名令牌进行身份验证 - ASP.NET Core API authenticate using JWT bearer tokens 如何在ASP.NET Core动态Web API中使用HttpGet? - How to use HttpGet in ASP.NET Core dynamic web api?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM