【问题标题】:Force re-authentication using OAuthWebSecurity with Facebook使用 OAuthWebSecurity 和 Facebook 强制重新认证
【发布时间】:2013-10-04 12:04:59
【问题描述】:

我的网站使用 facebook 作为它的 oauth 提供商。用户将能够通过我的网站购买东西,所以我想强制他们进行身份验证,即使他们已经与 facebook 进行了活动会话。

我发现这个link in facebook's api documentation 讨论了重新身份验证,但我无法让它与我的 mvc 应用程序一起使用。有人知道这是否可能吗?

var extra = new Dictionary<string, object>();
extra.Add("auth_type", "reauthenticate");

OAuthWebSecurity.RegisterFacebookClient(
            appId: "**********",
            appSecret: "**********************",
            displayName: "",
            extraData: extra);  

【问题讨论】:

    标签: c# asp.net-mvc facebook oauth


    【解决方案1】:

    找到了解决办法。我必须创建自己的客户端,而不是使用OAuthWebSecurity.RegisterFacebookClient 提供的默认客户端

    using System;
    using System.Collections.Generic;
    using System.Collections.Specialized;
    using System.Linq;
    using System.Net;
    using System.Web;
    using System.Web.Helpers;
    
    namespace Namespace.Helpers
    {
        public class MyFacebookClient : DotNetOpenAuth.AspNet.Clients.OAuth2Client
        {
            private const string AuthorizationEP = "https://www.facebook.com/dialog/oauth";
            private const string TokenEP = "https://graph.facebook.com/oauth/access_token";
            private readonly string _appId;
            private readonly string _appSecret;
    
            public MyFacebookClient(string appId, string appSecret)
                : base("facebook")
            {
                this._appId = appId;
                this._appSecret = appSecret;
            }
    
    
            protected override Uri GetServiceLoginUrl(Uri returnUrl)
            {
                return new Uri(
                            AuthorizationEP
                            + "?client_id=" + this._appId
                            + "&redirect_uri=" + HttpUtility.UrlEncode(returnUrl.ToString())
                            + "&scope=email,user_about_me"
                            + "&display=page"
                            + "&auth_type=reauthenticate"
                        );
            }
    
            protected override IDictionary<string, string> GetUserData(string accessToken)
            {
                WebClient client = new WebClient();
                string content = client.DownloadString(
                    "https://graph.facebook.com/me?access_token=" + accessToken
                );
                dynamic data = Json.Decode(content);
                return new Dictionary<string, string> {
                    {
                        "id",
                        data.id
                    },
                    {
                        "name",
                        data.name
                    },
                    {
                        "photo",
                        "https://graph.facebook.com/" + data.id + "/picture"
                    },
                    {
                        "email",
                        data.email
                    }
                };
            }
    
            protected override string QueryAccessToken(Uri returnUrl, string authorizationCode)
            {
                WebClient client = new WebClient();
                string content = client.DownloadString(
                    TokenEP
                    + "?client_id=" + this._appId
                    + "&client_secret=" + this._appSecret
                    + "&redirect_uri=" + HttpUtility.UrlEncode(returnUrl.ToString())
                    + "&code=" + authorizationCode
                );
    
                NameValueCollection nameValueCollection = HttpUtility.ParseQueryString(content);
                if (nameValueCollection != null)
                {
                    string result = nameValueCollection["access_token"];
                    return result;
                }
                return null;
            }
        }
    }
    

    然后在 AuthConfig.cs...

     OAuthWebSecurity.RegisterClient(
                    new MyFacebookClient(
                        appId: "xxxxxxxxxx", 
                        appSecret: "xxxxxxxxxxxxxxxx"),
                    "facebook", null
                );
    

    【讨论】:

    • 如果此答案对您不起作用,请查看我的回复,因为它在撰写本文时是正确的,但需要更新。
    【解决方案2】:

    请注意,如果您的 Facebook 身份验证在 v2.3 成为您可以访问的最低版本时停止工作(非版本化调用获得应用程序可以访问的最低版本),则会发生这种情况。 API 现在返回 JSON 而不是名称值对,因此您必须更新上面@Ben Tidman 显示的 QueryAccessToken 方法

    下面是更新的方法

    protected override string QueryAccessToken(Uri returnUrl, string authorizationCode)
            {
                WebClient client = new WebClient();
                string content = client.DownloadString(
                    TokenEP
                    + "?client_id=" + this._appId
                    + "&client_secret=" + this._appSecret
                    + "&redirect_uri=" + HttpUtility.UrlEncode(returnUrl.ToString())
                    + "&code=" + authorizationCode
                );
    
                dynamic json = System.Web.Helpers.Json.Decode(content);
                if (json != null)
                {
                    string result = json.access_token;
                    return result;
                }
                return null;
            }
    

    【讨论】:

      【解决方案3】:

      使用 MyFacebookClient 实现存在一个问题。 可能有人试图实现它遇到了错误:

      给定的键不在字典中

      正在尝试调用 ActionController 中的 ExternalLoginCallback 方法。

      该方法时引发的错误

      OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
      

      被调用。

      为了让它工作,必须重写方法 VerifyAuthentication。 特别是

      public virtual AuthenticationResult VerifyAuthentication(HttpContextBase context, Uri returnPageUrl);
      

      抽象类 OAuth2Client 的重载。

      如果您使用以下内容:

       public override AuthenticationResult VerifyAuthentication(HttpContextBase context, Uri returnPageUrl)
          {
              string code = context.Request.QueryString["code"];
      
              string rawUrl = context.Request.Url.OriginalString;
              //From this we need to remove code portion
              rawUrl = Regex.Replace(rawUrl, "&code=[^&]*", "");
      
              IDictionary<string, string> userData =    GetUserData(QueryAccessToken(returnPageUrl, code));
      
              if (userData == null)
                  return new AuthenticationResult(false, ProviderName, null, null, null);
      
      
              AuthenticationResult result = new AuthenticationResult(true, ProviderName, userData["id"], userData["name"], userData);
              userData.Remove("id");
              userData.Remove("name");
              return result;
          }
      }
      

      最后你得到了以正确方式调用的方法,并且没有抛出异常。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2013-07-26
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2014-09-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多