强制使用 OAuthWebSecurity 与 Facebook 重新进行身份验证

本文关键字:Facebook 新进行 身份验证 OAuthWebSecurity | 更新日期: 2023-09-27 18:33:11

我的网站正在使用Facebook作为oauth提供商。 用户将能够通过我的网站购买商品,因此即使他们已经与Facebook进行了活动会话,我也想强制他们进行身份验证。

我在 facebook 的 api 文档中找到了这个链接,该文档讨论了重新身份验证,但我无法让它与我的 mvc 应用程序一起使用。 有人知道这是否可能吗?

var extra = new Dictionary<string, object>();
extra.Add("auth_type", "reauthenticate");
OAuthWebSecurity.RegisterFacebookClient(
            appId: "**********",
            appSecret: "**********************",
            displayName: "",
            extraData: extra);  

强制使用 OAuthWebSecurity 与 Facebook 重新进行身份验证

找到了解决方案。 我必须创建自己的客户端,而不是使用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;
        }
    }
}

然后在身份验证配置.cs...

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

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

以下是更新的方法

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

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

字典中不存在给定的键

尝试在 ActionController 中调用 ExternalLoginCallback 方法。

当方法引发错误时

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

被称为。

为了使它正常工作,必须覆盖验证身份验证方法。特别是

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

最后,你得到以正确的方式调用的方法,并且没有抛出任何表达式。