Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

LinkedIn full profile details using DotNetOpenAuth in MVC4

My MVC4 application allows login using LinkedIn account. I want to pull all details that are avaible from linkedIn of the logged in User. Currently i have done the following.

In My AuthConfig.cs,

  Dictionary<string, object> linkedInExtraData = new Dictionary<string, object>();           
        linkedInExtraData.Add("Icon", "../Images/linkedIn.png");          
        OAuthWebSecurity.RegisterClient(
          client: new App_Start.LinkedInCustomClient("xxxxxxxxxxxx", "yyyyyyyyyyyyyyy"),
          displayName: "LinkedIn",
          extraData: linkedInExtraData);

In linkedInCustomClient.cs , from LinkedIn Developer Kit

public class LinkedInCustomClient : OAuthClient
{
    private static XDocument LoadXDocumentFromStream(Stream stream)
    {
        var settings = new XmlReaderSettings
        {
            MaxCharactersInDocument = 65536L
        };
        return XDocument.Load(XmlReader.Create(stream, settings));
    }


    /// Describes the OAuth service provider endpoints for LinkedIn.
    private static readonly ServiceProviderDescription LinkedInServiceDescription =
            new ServiceProviderDescription
            {
                AccessTokenEndpoint =
                        new MessageReceivingEndpoint("https://api.linkedin.com/uas/oauth/accessToken",
                        HttpDeliveryMethods.PostRequest),
                RequestTokenEndpoint =
                        new MessageReceivingEndpoint("https://api.linkedin.com/uas/oauth/requestToken?scope=r_fullprofile",
                        HttpDeliveryMethods.PostRequest),
                UserAuthorizationEndpoint =
                        new MessageReceivingEndpoint("https://www.linkedin.com/uas/oauth/authorize",
                        HttpDeliveryMethods.PostRequest),
                TamperProtectionElements =
                        new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() },
                ProtocolVersion = ProtocolVersion.V10a
            };

    public LinkedInCustomClient(string consumerKey, string consumerSecret) :
        base("linkedIn", LinkedInServiceDescription, consumerKey, consumerSecret) { }

    /// Check if authentication succeeded after user is redirected back from the service provider.
    /// The response token returned from service provider authentication result. 
    [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,interests,headline,industry,summary,email-address,location:(name),picture-url,positions,associations,languages,honors,educations,date-of-birth,primary-twitter-account,three-current-positions,three-past-positions,group-memberships,specialties,skills)";


        string accessToken = response.AccessToken;
        string tokenSecret = (response as ITokenSecretContainingMessage).TokenSecret;
        string Verifier = response.ExtraData.Values.First();


        var profileEndpoint =
            new MessageReceivingEndpoint(profileRequestUrl, HttpDeliveryMethods.GetRequest);
        HttpWebRequest request =
            WebWorker.PrepareAuthorizedRequest(profileEndpoint, accessToken);

        try
        { 
            using (WebResponse profileResponse = request.GetResponse())
            {
                using (Stream responseStream = profileResponse.GetResponseStream())
                {
                    XDocument document = LoadXDocumentFromStream(responseStream); 

                    return new AuthenticationResult(
                        isSuccessful: true,
                        provider: ProviderName,
                        providerUserId: userId,
                        userName: userName,
                        extraData: extraData);
                }
            }
        }
        catch (Exception exception)
        {
            return new AuthenticationResult(exception);
        }
    }

}

In my controller,

AuthenticationResult result = OAuthWebSecurity.VerifyAuthentication(Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
        if (!result.IsSuccessful)
        {
            return RedirectToAction("ExternalLoginFailure");
        }

I need to get the following details in my controller as authentication result.

(id,first-name,last-name,interests,headline,industry,summary,email-address,location:(name),picture-url,positions,associations,languages,honors,educations,date-of-birth,primary-twitter-account,three-current-positions,three-past-positions,group-memberships,specialties,skills)
like image 913
sudil ravindran pk Avatar asked Mar 25 '13 07:03

sudil ravindran pk


1 Answers

The response of your request from LinkedIn will be a xml file. The format and fields are mentioned in LinkedIn Profile Fields

For getting email field, you need to modify your request token url as

RequestTokenEndpoint = new MessageReceivingEndpoint("https://api.linkedin.com/uas/oauth/requestToken?scope=r_fullprofile+r_emailaddress", HttpDeliveryMethods.PostRequest),

You can get the fields as required in the following code

 XDocument document = LoadXDocumentFromStream(responseStream); 

Eg : For getting the first name field from the xml file,

var firstName = document.Root.Element("first-name").Value;

Fields like languages, positions, skills etc will be returned as structured objects as part of the profile.

Eg : Language field.

    var Lang = document.Root.Element("languages");                        
    var languages = new List<string>();
    if (Lang != null)
    {
     foreach (var l in Lang.Elements())
        {
          if (l.Element("language") != null && l.Element("language").Element("name") != null)
          {
            languages.Add(l.Element("language").Element("name").Value);
           }
         }
      }

Then you can add fields to "extraData" which can be accessed in the controller.

 extraData.Add("firstName", firstName);
 extraData.Add("languages", lang);
like image 166
Rifaj Avatar answered Oct 03 '22 19:10

Rifaj