0

I'm using ASP.NET Core 2.1 and I want to use LinkedIn authentication.

Because there is no extension method .AddLinkedIn by default (developed by Microsoft's dev), so I've tried:

services.AddOAuth("LinkedIn", options =>
{
    options.ClientId = Configuration["Authentication:LinkedIn:ClientId"];
    options.ClientSecret = Configuration["Authentication:LinkedIn:ClientSecret"];
    options.Scope.Add("r_basicprofile");
    options.Scope.Add("r_emailaddress");
    options.CallbackPath = "/signin-linkedin";
    options.AuthorizationEndpoint = "https://www.linkedin.com/oauth/v2/authorization";
    options.TokenEndpoint = "https://www.linkedin.com/oauth/v2/accessToken";
    options.UserInformationEndpoint = "https://api.linkedin.com/v1/people/~:(id,formatted-name,email-address,picture-url)";
    options.Events = new OAuthEvents
    {
        OnCreatingTicket = async context =>
        {
            using (var request = new HttpRequestMessage(HttpMethod.Get, context.Options.UserInformationEndpoint))
            {
                request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken);
                request.Headers.Add("x-li-format", "json");

                var response = await context.Backchannel.SendAsync(request, context.HttpContext.RequestAborted);

                if (response.StatusCode == System.Net.HttpStatusCode.OK)
                {
                    string responseText = await response.Content.ReadAsStringAsync();

                    var user = Newtonsoft.Json.Linq.JObject.Parse(responseText);

                    context.Identity.AddClaim(new Claim(ClaimTypes.NameIdentifier, user.Value<string>("id")));
                    context.Identity.AddClaim(new Claim(ClaimTypes.Name, user.Value<string>("formattedName")));
                    context.Identity.AddClaim(new Claim(ClaimTypes.Email, user.Value<string>("emailAddress")));
                    context.Identity.AddClaim(new Claim("picture", user.Value<string>("pictureUrl")));
                }
            }
        }
    };
});

and in the controller, I've tried to get the info:

var info = await _signInManager.GetExternalLoginInfoAsync();

it returned null.

I'd tried to clear all cookies and signed in again with another services like Facebook, Google or Twitter. All of them worked perfectly (I got the information) except LinkedIn. Why?

Tân
  • 1
  • 15
  • 56
  • 102
  • Possible duplicate of [LinkedIn External Login in ASP.NET Core 2.0](https://stackoverflow.com/questions/46661119/linkedin-external-login-in-asp-net-core-2-0) – Linda Lawton - DaImTo Nov 03 '18 at 14:53

1 Answers1

0

I'd tried to rewrite the code and change the line:

using (var request = new HttpRequestMessage(HttpMethod.Get, context.Options.UserInformationEndpoint))

to

var request = new HttpRequestMessage(HttpMethod.Get, context.Options.UserInformationEndpoint);

Then, it should work! (I don't know why).

It seems like the using block cannot be accepted during this action. After closing the scope, all of the claims will be cleard.

Tân
  • 1
  • 15
  • 56
  • 102
  • So you are saying this is completely unrelated to ASP.NET Core, LinkedIn and OAuth, but just a problem in what gets disposed when the request message gets disposed? – Camilo Terevinto Nov 03 '18 at 14:51
  • @CamiloTerevinto Related, sir! ASP.NET Core doesn't support extension method `AddLinkedIn` by default, so we need to use the 3rd party lib or we implement it ourself. Also, the `using` block *may* work fine in many other cases except using it with `HttpRequestMessage` like that. And the problem is: it made `_signInManager.GetExternalLoginInfoAsync` returned `null`. – Tân Nov 03 '18 at 14:59