自去年年底以来,LinkedIn 终于允许我们检索当前登录用户的电子邮件地址,但我一直未能这样做。我已经阅读了我可以在 SO 和其他地方找到的所有帖子,并且据我所知,我的代码应该可以工作。它在所有其他字段中都返回得很好,
但是,电子邮件地址字段始终为空。
这是我的 LinkedInClient 类;
public class LinkedInClient2 : OAuthClient
{
public static readonly ServiceProviderDescription LinkedInServiceDescription = new ServiceProviderDescription
{
AccessTokenEndpoint =
new MessageReceivingEndpoint(
"https://api.linkedin.com/uas/oauth/accessToken",
HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
RequestTokenEndpoint =
new MessageReceivingEndpoint(
"https://api.linkedin.com/uas/oauth/requestToken?scope=r_basicprofile+r_emailaddress",
HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
UserAuthorizationEndpoint =
new MessageReceivingEndpoint(
"https://www.linkedin.com/uas/oauth/authenticate",
HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest),
TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() },
ProtocolVersion = ProtocolVersion.V10a
};
public LinkedInClient2(string consumerKey, string consumerSecret, IConsumerTokenManager tokenManager)
: base("linkedIn", LinkedInServiceDescription, tokenManager)
{
}
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes", Justification = "We don't care if the request fails.")]
protected override AuthenticationResult VerifyAuthenticationCore(AuthorizedTokenResponse response)
{
// See here for Field Selectors API http://developer.linkedin.com/docs/DOC-1014
const string ProfileRequestUrl = "https://api.linkedin.com/v1/people/~:(id,first-name,last-name,email-address,headline,industry,summary,picture-url)";
string accessToken = response.AccessToken;
var profileEndpoint = new MessageReceivingEndpoint(ProfileRequestUrl, HttpDeliveryMethods.GetRequest);
HttpWebRequest request = this.WebWorker.PrepareAuthorizedRequest(profileEndpoint, accessToken);
try
{
using (WebResponse profileResponse = request.GetResponse())
{
using (Stream responseStream = profileResponse.GetResponseStream())
{
XDocument document = LoadXDocumentFromStream(responseStream);
string userId = document.Root.Element("id").Value;
// User Profile Fields - https://developer.linkedin.com/documents/profile-fields
string firstName = document.Root.Element("first-name").Value;
string lastName = document.Root.Element("last-name").Value;
string userName = document.Root.Element("email-address").Value; // <<<<<< ERROR - always empty
var extraData = new Dictionary<string, string>();
extraData.Add("accesstoken", accessToken);
extraData.Add("name", userName);
extraData.AddDataIfNotEmpty(document, "picture-url");
extraData.AddDataIfNotEmpty(document, "location");
extraData.AddDataIfNotEmpty(document, "headline");
extraData.AddDataIfNotEmpty(document, "summary");
extraData.AddDataIfNotEmpty(document, "industry");
return new AuthenticationResult(
isSuccessful: true, provider: this.ProviderName, providerUserId: userId, userName: userName, extraData: extraData);
}
}
}
catch (Exception exception)
{
return new AuthenticationResult(exception);
}
}
internal static XDocument LoadXDocumentFromStream(Stream stream)
{
const int MaxChars = 0x10000; // 64k
XmlReaderSettings settings = new XmlReaderSettings()
{
MaxCharactersInDocument = MaxChars
};
return XDocument.Load(XmlReader.Create(stream, settings));
}
}
}
我意识到我应该将它添加scope=r_emailaddress
到RequestTokenEndpoint
(我拥有的),但是从提琴手的痕迹中我什至看不到那个端点被提取。基本上,它只有每个都使用AccessTokenEndpoint
可能与我的问题有关的东西。
这大概是我的 ASP.Net MVC4.5 控制器的外观;
[AllowAnonymous]
public virtual ActionResult LinkedIn(string returnUrl)
{
var tokenMgr = new RepoOAuthTokenManager(_iOtk, LinkedInAppKey, LinkedInAppSecret);
var iacp = new LinkedInClient2(LinkedInAppKey, LinkedInAppSecret, tokenMgr); // if none specified, LinkedInClient uses the AuthenticationOnlyCookieOAuthTokenManager which doesn't work for APIs
var ioadp = new MyOauthDataProvider();
var oasm = new OpenAuthSecurityManager(this.HttpContext, iacp, ioadp);
var redirectUri = Url.ActionFullyQualified(this.nameof(c => c.LinkedIn(null)), null, new RouteValueDictionary(new { returnUrl = returnUrl }));
AuthenticationResult ar = oasm.VerifyAuthentication(redirectUri);
if (ar.Error == null)
{
if (ar.IsSuccessful)
DoSomethingResultingInRedirect(redirectUri); // OK
else
oasm.RequestAuthentication(redirectUri);
}
else
ModelState.AddModelError("", ar.Error.Message);
return View(this.nameof(c=>c.Login(null)));
}//LinkedIn
我不能说我完全理解 DotNetOpenAuth 中的可扩展性机制,我可能会误解一些东西,所以我很感激一些指示。
我在某处错过了一步吗?