First of all great thanks to Luke Hoban for his ‘Twitter OAuth in F#‘. His OAuth implementation works fine for LinkedIn as well.
All you need to do is to switch the requestTokenURI/accessTokenURI/authorizeURI addresses from Twitter on LinkedIn.
Additional materials about LinkedIn public API you found at the LinkedIn developers site: https://developer.linkedin.com/
LinkedIn OAuth implementation:
open System open System.IO open System.Net open System.Security.Cryptography open System.Text // LinkedIn OAuth Constants let consumerKey : string = failwith "Must provide the consumerKey for an app registered at https://www.linkedin.com/secure/developer?newapp=" let consumerSecret : string = failwith "Must provide the consumerSecret for an app registered at https://www.linkedin.com/secure/developer?newapp=" let requestTokenURI = "https://api.linkedin.com/uas/oauth/requestToken" let accessTokenURI = "https://api.linkedin.com/uas/oauth/accessToken" let authorizeURI = "https://api.linkedin.com/uas/oauth/authorize" // Utilities let unreservedChars = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-_.~"; let urlEncode str = String.init (String.length str) (fun i -> let symbol = str.[i] if unreservedChars.IndexOf(symbol) = -1 then "%" + String.Format("{0:X2}", int symbol) else string symbol) // Core Algorithms let hmacsha1 signingKey str = let converter = new HMACSHA1(Encoding.ASCII.GetBytes(signingKey : string)) let inBytes = Encoding.ASCII.GetBytes(str : string) let outBytes = converter.ComputeHash(inBytes) Convert.ToBase64String(outBytes) let compositeSigningKey consumerSecret tokenSecret = urlEncode(consumerSecret) + "&" + urlEncode(tokenSecret) let baseString httpMethod baseUri queryParameters = httpMethod + "&" + urlEncode(baseUri) + "&" + (queryParameters |> Seq.sortBy (fun (k,v) -> k) |> Seq.map (fun (k,v) -> urlEncode(k)+"%3D"+urlEncode(v)) |> String.concat "%26") let createAuthorizeHeader queryParameters = let headerValue = "OAuth " + (queryParameters |> Seq.map (fun (k,v) -> urlEncode(k)+"\x3D\""+urlEncode(v)+"\"") |> String.concat ",") headerValue let currentUnixTime() = floor (DateTime.UtcNow - DateTime(1970, 1, 1, 0, 0, 0, 0)).TotalSeconds /// Request a token from LinkedIn and return: /// oauth_token, oauth_token_secret, oauth_callback_confirmed let requestToken() = let signingKey = compositeSigningKey consumerSecret "" let queryParameters = ["oauth_callback", "oob"; "oauth_consumer_key", consumerKey; "oauth_nonce", System.Guid.NewGuid().ToString().Substring(24); "oauth_signature_method", "HMAC-SHA1"; "oauth_timestamp", currentUnixTime().ToString(); "oauth_version", "1.0"] let signingString = baseString "POST" requestTokenURI queryParameters let oauth_signature = hmacsha1 signingKey signingString let realQueryParameters = ("oauth_signature", oauth_signature)::queryParameters let req = WebRequest.Create(requestTokenURI, Method="POST") let headerValue = createAuthorizeHeader realQueryParameters req.Headers.Add(HttpRequestHeader.Authorization, headerValue) let resp = req.GetResponse() let stream = resp.GetResponseStream() let txt = (new StreamReader(stream)).ReadToEnd() let parts = txt.Split('&') (parts.[0].Split('=').[1], parts.[1].Split('=').[1], parts.[2].Split('=').[1] = "true") /// Get an access token from LinkedIn and returns: /// oauth_token, oauth_token_secret let accessToken token tokenSecret verifier = let signingKey = compositeSigningKey consumerSecret tokenSecret let queryParameters = ["oauth_consumer_key", consumerKey; "oauth_nonce", System.Guid.NewGuid().ToString().Substring(24); "oauth_signature_method", "HMAC-SHA1"; "oauth_token", token; "oauth_timestamp", currentUnixTime().ToString(); "oauth_verifier", verifier; "oauth_version", "1.0"] let signingString = baseString "POST" accessTokenURI queryParameters let oauth_signature = hmacsha1 signingKey signingString let realQueryParameters = ("oauth_signature", oauth_signature)::queryParameters let req = WebRequest.Create(accessTokenURI, Method="POST") let headerValue = createAuthorizeHeader realQueryParameters req.Headers.Add(HttpRequestHeader.Authorization, headerValue) let resp = req.GetResponse() let stream = resp.GetResponseStream() let txt = (new StreamReader(stream)).ReadToEnd() let parts = txt.Split('&') (parts.[0].Split('=').[1], parts.[1].Split('=').[1]) /// Compute the 'Authorization' header for the given request data let authHeaderAfterAuthenticated url httpMethod token tokenSecret queryParams = let signingKey = compositeSigningKey consumerSecret tokenSecret let queryParameters = ["oauth_consumer_key", consumerKey; "oauth_nonce", System.Guid.NewGuid().ToString().Substring(24); "oauth_signature_method", "HMAC-SHA1"; "oauth_token", token; "oauth_timestamp", currentUnixTime().ToString(); "oauth_version", "1.0"] let signingQueryParameters = List.append queryParameters queryParams let signingString = baseString httpMethod url signingQueryParameters let oauth_signature = hmacsha1 signingKey signingString let realQueryParameters = ("oauth_signature", oauth_signature)::queryParameters let headerValue = createAuthorizeHeader realQueryParameters headerValue /// Add an Authorization header to an existing WebRequest let addAuthHeaderForUser (webRequest : WebRequest) token tokenSecret queryParams = let url = webRequest.RequestUri.ToString() let httpMethod = webRequest.Method let header = authHeaderAfterAuthenticated url httpMethod token tokenSecret queryParams webRequest.Headers.Add(HttpRequestHeader.Authorization, header) type System.Net.WebRequest with /// Add an Authorization header to the WebRequest for the provided user authorization tokens and query parameters member this.AddOAuthHeader(userToken, userTokenSecret, queryParams) = addAuthHeaderForUser this userToken userTokenSecret queryParams let testing() = // Compute URL to send user to to allow our app to connect with their credentials, // then open the browser to have them accept let oauth_token'', oauth_token_secret'', oauth_callback_confirmed = requestToken() let url = authorizeURI + "?oauth_token=" + oauth_token'' System.Diagnostics.Process.Start("iexplore.exe", url) // *******NOTE********: // Get the 7 digit number from the web page, pass it to the function below to get oauth_token // Sample result if things go okay: // val oauth_token_secret' : string = "9e571e13-d054-44e6-956a-415ab3ee6d23" // val oauth_token' : string = "044da520-0edc-4083-a061-74e115712b61" let oauth_token, oauth_token_secret = accessToken oauth_token'' oauth_token_secret'' ("78846") // Test 1: Get your profile details let streamSampleUrl2 = "http://api.linkedin.com/v1/people/~" let req = WebRequest.Create(streamSampleUrl2) req.AddOAuthHeader(oauth_token, oauth_token_secret, []) let resp = req.GetResponse() let strm = resp.GetResponseStream() let text = (new StreamReader(strm)).ReadToEnd() text // Test 2: Get a connections list let streamSampleUrl3 = "http://api.linkedin.com/v1/people/~/connections" let req = WebRequest.Create(streamSampleUrl3) req.AddOAuthHeader(oauth_token, oauth_token_secret, []) let resp = req.GetResponse() let strm = resp.GetResponseStream() let text = (new StreamReader(strm)).ReadToEnd() text