Closed sivagithub-pk closed 3 years ago
Could you step into this and see if you can debug this call. I don't use linked in, but form what you posted it sounds like the json response is different than what we are expecting.
Hi @niemyjski ,
I have fixed this issue. the reason why it's throwing the exception is,
I have fixed this issue by customizing the LinkedInclient File that will point to the API version V2. Existing LinkedIn client file. that points to API version V1
using System; using System.Threading; using System.Threading.Tasks; using OAuth2.Configuration; using OAuth2.Infrastructure; using OAuth2.Models; using RestSharp; using System.Xml.Linq; using System.Xml.XPath;
namespace OAuth2.Client.Impl
{
///
/// <summary>
/// Defines URI of service which issues access code.
/// </summary>
protected override Endpoint AccessCodeServiceEndpoint
{
get
{
return new Endpoint
{
BaseUri = "https://www.linkedin.com",
Resource = "/uas/oauth2/authorization"
};
}
}
/// <summary>
/// Defines URI of service which issues access token.
/// </summary>
protected override Endpoint AccessTokenServiceEndpoint
{
get
{
return new Endpoint
{
BaseUri = "https://www.linkedin.com",
Resource = "/uas/oauth2/accessToken"
};
}
}
/// <summary>
/// Defines URI of service which allows to obtain information about user which is currently logged in.
/// </summary>
protected override Endpoint UserInfoServiceEndpoint
{
get
{
return new Endpoint
{
BaseUri = "https://api.linkedin.com",
Resource = "/v1/people/~:(id,email-address,first-name,last-name,picture-url)"
};
}
}
public override Task<string> GetLoginLinkUriAsync(string state = null, CancellationToken cancellationToken = default)
{
return base.GetLoginLinkUriAsync(state ?? Guid.NewGuid().ToString("N"), cancellationToken);
}
protected override void BeforeGetUserInfo(BeforeAfterRequestArgs args)
{
args.Client.Authenticator = null;
args.Request.Parameters.Add(new Parameter("oauth2_access_token", AccessToken, ParameterType.GetOrPost));
}
/// <summary>
/// Should return parsed <see cref="UserInfo"/> from content received from third-party service.
/// </summary>
/// <param name="content">The content which is received from third-party service.</param>
protected override UserInfo ParseUserInfo(string content)
{
var document = XDocument.Parse(content);
var avatarUri = SafeGet(document, "/person/picture-url");
var avatarSizeTemplate = "{0}_{0}";
if (string.IsNullOrEmpty(avatarUri))
{
avatarUri = "https://www.linkedin.com/scds/common/u/images/themes/katy/ghosts/person/ghost_person_80x80_v1.png";
avatarSizeTemplate = "{0}x{0}";
}
var avatarDefaultSize = string.Format(avatarSizeTemplate, 80);
return new UserInfo
{
Id = document.XPathSelectElement("/person/id").Value,
Email = SafeGet(document, "/person/email-address"),
FirstName = document.XPathSelectElement("/person/first-name").Value,
LastName = document.XPathSelectElement("/person/last-name").Value,
AvatarUri =
{
Small = avatarUri.Replace(avatarDefaultSize, string.Format(avatarSizeTemplate, AvatarInfo.SmallSize)),
Normal = avatarUri,
Large = avatarUri.Replace(avatarDefaultSize, string.Format(avatarSizeTemplate, AvatarInfo.LargeSize))
}
};
}
private string SafeGet(XDocument document, string path)
{
var element = document.XPathSelectElement(path);
if (element == null)
return null;
return element.Value;
}
/// <summary>
/// Friendly name of provider (OAuth service).
/// </summary>
public override string Name
{
get { return "LinkedIn"; }
}
}
}
My customized LinkedClient file that points to API Version V2
using System; using System.Threading; using System.Threading.Tasks; using Newtonsoft.Json.Linq; using OAuth2.Client; using OAuth2.Configuration; using OAuth2.Infrastructure; using OAuth2.Models; using RestSharp;
namespace Apex.Web.Authentication
{
///
/// <summary>
/// Gets friendly name of provider (OAuth service).
/// </summary>
public override string Name => "LinkedIn";
/// <summary>
/// Gets defines URI of service which issues access code.
/// </summary>
protected override Endpoint AccessCodeServiceEndpoint
{
get
{
return new Endpoint
{
BaseUri = "https://www.linkedin.com",
Resource = "/uas/oauth2/authorization"
};
}
}
/// <summary>
/// Gets defines URI of service which issues access token.
/// </summary>
protected override Endpoint AccessTokenServiceEndpoint
{
get
{
return new Endpoint
{
BaseUri = "https://www.linkedin.com",
Resource = "/uas/oauth2/accessToken"
};
}
}
/// <summary>
/// Gets defines URI of service which allows to obtain information about user which is currently logged in.
/// </summary>
protected override Endpoint UserInfoServiceEndpoint
{
get
{
return new Endpoint
{
BaseUri = "https://api.linkedin.com",
Resource = "/v2/clientAwareMemberHandles?q=members&projection=(elements*(primary,type,handle~))
};
}
}
public override Task<string> GetLoginLinkUriAsync(string state = null, CancellationToken cancellationToken = default)
{
return base.GetLoginLinkUriAsync(state ?? Guid.NewGuid().ToString("N"), cancellationToken);
}
protected override void BeforeGetUserInfo(BeforeAfterRequestArgs args)
{
args.Client.Authenticator = null;
args.Request.Parameters.Add(new Parameter("oauth2_access_token", AccessToken, ParameterType.GetOrPost));
}
/// <summary>
/// Should return parsed <see cref="UserInfo"/> from content received from third-party service.
/// </summary>
/// <param name="content">The content which is received from third-party service.</param>
/// <returns>UserInfo.</returns>
protected override UserInfo ParseUserInfo(string content)
{
var jsonContent = JObject.Parse(content);
return new UserInfo
{
Email = jsonContent["elements"][0]["handle~"]["emailAddress"].ToString()
};
}
}
}
Now I am able to query and read the user email details successfully.
Hi, I am using OAuth2 to implement the SSO for Google, Facebook, and LinkedIn. Google and Facebook I am able to log in and read the user profile info but for LinkedIn, I am able to get the authorization code but when I call method to get the User info I am getting the exception as Exception of type 'OAuth2.Client.UnexpectedResponseException' was thrown. below is my code snippet ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls12; var userInfo = await oauth.GetUserInfoAsync(new NameValueCollection { { "code", code } });
Here is the exception of staktrace. at OAuth2.Infrastructure.RestClientExtensions.VerifyResponse(IRestResponse response) at OAuth2.Infrastructure.RestClientExtensions.d1.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitable`1.ConfiguredTaskAwaiter.GetResult()
at OAuth2.Client.OAuth2Client.d 52.MoveNext()
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)
at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)
at System.Runtime.CompilerServices.ConfiguredTaskAwaitabled__6.MoveNext() in C:\Users\ksivasankar\Source\Repos\Apex\Source\Backend\Shared\Web\Authentication\SingleSignOnService.cs:line 75
Can any one please suggest where I am doing wrong.
1.ConfiguredTaskAwaiter.GetResult() at OAuth2.Client.OAuth2Client.<GetUserInfoAsync>d__53.MoveNext() at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw() at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task) at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task) at System.Runtime.CompilerServices.TaskAwaiter
1.GetResult() at Apex.Web.Authentication.SingleSignOnService.