//----------------------------------------------------------------------- // // Copyright (c) Microsoft. All rights reserved. // //----------------------------------------------------------------------- namespace DotNetOpenAuth.AspNet.Clients { using System; using System.Collections.Generic; using System.Diagnostics.CodeAnalysis; using System.IO; using System.Net; using System.Xml.Linq; using DotNetOpenAuth.Messaging; using DotNetOpenAuth.OAuth; using DotNetOpenAuth.OAuth.ChannelElements; using DotNetOpenAuth.OAuth.Messages; /// /// Represents LinkedIn authentication client. /// public sealed class LinkedInClient : OAuthClient { #region Constants and Fields /// /// Describes the OAuth service provider endpoints for LinkedIn. /// public static readonly ServiceProviderDescription LinkedInServiceDescription = new ServiceProviderDescription { RequestTokenEndpoint = new MessageReceivingEndpoint( "https://api.linkedin.com/uas/oauth/requestToken", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest), UserAuthorizationEndpoint = new MessageReceivingEndpoint( "https://www.linkedin.com/uas/oauth/authenticate", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest), AccessTokenEndpoint = new MessageReceivingEndpoint( "https://api.linkedin.com/uas/oauth/accessToken", HttpDeliveryMethods.GetRequest | HttpDeliveryMethods.AuthorizationHeaderRequest), TamperProtectionElements = new ITamperProtectionChannelBindingElement[] { new HmacSha1SigningBindingElement() }, }; #endregion #region Constructors and Destructors /// /// Initializes a new instance of the class. /// /// /// The LinkedIn app's consumer key. /// /// /// The LinkedIn app's consumer secret. /// [SuppressMessage("Microsoft.Reliability", "CA2000:Dispose objects before losing scope", Justification = "We can't dispose the object because we still need it through the app lifetime.")] public LinkedInClient(string consumerKey, string consumerSecret) : base("linkedIn", LinkedInServiceDescription, consumerKey, consumerSecret) { } /// /// Initializes a new instance of the class. /// /// The consumer key. /// The consumer secret. /// The token manager. public LinkedInClient(string consumerKey, string consumerSecret, IOAuthTokenManager tokenManager) : base("linkedIn", LinkedInServiceDescription, new SimpleConsumerTokenManager(consumerKey, consumerSecret, tokenManager)) { } #endregion #region Methods /// /// 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 = "http://api.linkedin.com/v1/people/~:(id,first-name,last-name,headline,industry,summary)"; 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 = XDocument.Load(responseStream); string userId = document.Root.Element("id").Value; string firstName = document.Root.Element("first-name").Value; string lastName = document.Root.Element("last-name").Value; string userName = firstName + " " + lastName; var extraData = new Dictionary(); extraData.Add("accesstoken", accessToken); extraData.Add("name", userName); 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); } } #endregion } }