加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > asp.Net > 正文

WebApi ASP.NET身份Facebook登录

发布时间:2020-12-15 19:28:12 所属栏目:asp.Net 来源:网络整理
导读:在用于asp.net身份的facebook身份验证流程中,facebook oath对话框将一个代码而不是访问令牌附加到redirect_url,以便服务器可以通过http:// localhost:49164 / signin-facebook交换此代码作为访问令牌。 code = … state = …. 我的问题是,我的客户是一
在用于asp.net身份的facebook身份验证流程中,facebook oath对话框将一个代码而不是访问令牌附加到redirect_url,以便服务器可以通过http:// localhost:49164 / signin-facebook交换此代码作为访问令牌。 code = …& state = ….

我的问题是,我的客户是一个移动应用程序使用的facebook sdk,直接给我一个访问令牌。 Facebook说使用sdk总是给你一个访问令牌,所以我可以直接给web API访问令牌。我明白这不是很安全,但它是可能的?

解决方法

我不知道你是否终于找到了解决方案,但我想做一些很相似的事情,我仍然把拼图的部分放在一起。
我试图张贴这作为一个评论,而不是一个答案,因为我不提供一个真正的解决方案,但它太长。

显然,所有WebAPI Owin OAuth选项都是基于浏览器的,也就是说他们需要大量的浏览器重定向请求,不适合本地移动应用程序(我的情况)。
我仍然在调查和实验,但正如Hongye Sun在他的博客文章http://blogs.msdn.com/b/webdev/archive/2013/09/20/understanding-security-features-in-spa-template.aspx?PageIndex=2#comments的一个评论中所简要描述的,使用Facebook登录访问令牌可以直接通过API进行验证,通过图形调用/ me端点。

通过使用图形调用返回的信息,您可以检查用户是否已经注册。
最后,我们需要登录用户,也许使用Authentication.SignIn Owin方法,返回一个将用于所有后续API调用的承载令牌。

编辑:
实际上我错了,承载令牌是发出呼叫“/ Token”端点,其上输入接受类似grant_type =密码&用户名=爱丽丝&密码=密码123
这里的问题是我们没有密码(这是OAuth机制的整个要点),那么我们还能如何调用“/ Token”端点呢?

更新:
我终于找到一个工作的解决方案,以下是我不得不添加到现有的类,使其工作:
Startup.Auth.cs

public partial class Startup
{
    /// <summary>
    /// This part has been added to have an API endpoint to authenticate users that accept a Facebook access token
    /// </summary>
    static Startup()
    {
        PublicClientId = "self";

        //UserManagerFactory = () => new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
        UserManagerFactory = () => 
        {
            var userManager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext()));
            userManager.UserValidator = new UserValidator<ApplicationUser>(userManager) { AllowOnlyAlphanumericUserNames = false };
            return userManager;
        };

        OAuthOptions = new OAuthAuthorizationServerOptions
        {
            TokenEndpointPath = new PathString("/Token"),Provider = new ApplicationOAuthProvider(PublicClientId,UserManagerFactory),AuthorizeEndpointPath = new PathString("/api/Account/ExternalLogin"),AccessTokenExpireTimeSpan = TimeSpan.FromDays(14),AllowInsecureHttp = true
        };

        OAuthBearerOptions = new OAuthBearerAuthenticationOptions();
        OAuthBearerOptions.AccessTokenFormat = OAuthOptions.AccessTokenFormat;
        OAuthBearerOptions.AccessTokenProvider = OAuthOptions.AccessTokenProvider;
        OAuthBearerOptions.AuthenticationMode = OAuthOptions.AuthenticationMode;
        OAuthBearerOptions.AuthenticationType = OAuthOptions.AuthenticationType;
        OAuthBearerOptions.Description = OAuthOptions.Description;
        OAuthBearerOptions.Provider = new CustomBearerAuthenticationProvider();            
        OAuthBearerOptions.SystemClock = OAuthOptions.SystemClock;
    }

    public static OAuthBearerAuthenticationOptions OAuthBearerOptions { get; private set; }

    public static OAuthAuthorizationServerOptions OAuthOptions { get; private set; }

    public static Func<UserManager<ApplicationUser>> UserManagerFactory { get; set; }

    public static string PublicClientId { get; private set; }

    // For more information on configuring authentication,please visit http://go.microsoft.com/fwlink/?LinkId=301864
    public void ConfigureAuth(IAppBuilder app)
    {
        [Initial boilerplate code]

        OAuthBearerAuthenticationExtensions.USEOAuthBearerAuthentication(app,OAuthBearerOptions);

        [More boilerplate code]
    }
}

public class CustomBearerAuthenticationProvider : OAuthBearerAuthenticationProvider
{
    public override Task ValidateIdentity(OAuthValidateIdentityContext context)
    {
        var claims = context.Ticket.Identity.Claims;
        if (claims.Count() == 0 || claims.Any(claim => claim.Issuer != "Facebook" && claim.Issuer != "LOCAL_AUTHORITY" ))
            context.Rejected();
        return Task.FromResult<object>(null);
    }
}

进入AccountController,我添加了以下操作

[HttpPost]
        [AllowAnonymous]
        [Route("FacebookLogin")]
        public async Task<IHttpActionResult> FacebookLogin(string token)
        {
            [Code to validate input...]
            var tokenExpirationTimeSpan = TimeSpan.FromDays(14);            
            ApplicationUser user = null;    
            // Get the fb access token and make a graph call to the /me endpoint    
            // Check if the user is already registered
            // If yes retrieve the user 
            // If not,register it  
            // Finally sign-in the user: this is the key part of the code that creates the bearer token and authenticate the user
            var identity = new ClaimsIdentity(Startup.OAuthBearerOptions.AuthenticationType);
            identity.AddClaim(new Claim(ClaimTypes.Name,user.Id,null,"Facebook"));
                // This claim is used to correctly populate user id
                identity.AddClaim(new Claim(ClaimTypes.NameIdentifier,"LOCAL_AUTHORITY"));
            AuthenticationTicket ticket = new AuthenticationTicket(identity,new AuthenticationProperties());            
            var currentUtc = new Microsoft.Owin.Infrastructure.SystemClock().UtcNow;
            ticket.Properties.IssuedUtc = currentUtc;
            ticket.Properties.ExpiresUtc = currentUtc.Add(tokenExpirationTimeSpan);            
            var accesstoken = Startup.OAuthBearerOptions.AccessTokenFormat.Protect(ticket); 
            Authentication.SignIn(identity);

            // Create the response
            JObject blob = new JObject(
                new JProperty("userName",user.UserName),new JProperty("access_token",accesstoken),new JProperty("token_type","bearer"),new JProperty("expires_in",tokenExpirationTimeSpan.TotalSeconds.ToString()),new JProperty(".issued",ticket.Properties.IssuedUtc.ToString()),new JProperty(".expires",ticket.Properties.ExpiresUtc.ToString())
            );
            var json = Newtonsoft.Json.JsonConvert.SerializeObject(blob);
            // Return OK
            return Ok(blob);
        }

而已。我发现与经典/令牌端点响应的唯一的区别是承载令牌稍短,过期和发布日期在UTC,而不是在GMT(至少在我的机器上)。

我希望这有帮助!

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读