强制使用 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.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;
}
}
最后,你得到以正确的方式调用的方法,并且没有抛出任何表达式。