LinkedIn Authentication in ASP.Net

For LinkedIn Authentication I have utilized LinkedIn Rest API which use oAuth 1.0 to authorize users and begin making REST API calls using any programming language. Complete understanding tutorials are placed at https://developer.linkedin.com/documents/oauth-overview

Following are the steps to implement LinkedIn Authentication in ASP.Net

Step 1 Installations

  1. Install Hammock Library from CodePlex.com, Hammock is a REST library for .Net that greatly simplifies consuming Restful services.
  2. Configure NuGet (optional to ease referencing code plex libraries directly in Visual Studio project). You can also get the NuGet from http://nuget.codeplex.com/

Step 2 Create LinkedIn Application in LinkedIn developer platform

  1. Go to https://www.linkedin.com/secure/developer
  2. Sign in with your LinkedIn credentials.
  3. Click on Add New Application and fill in the form.
  4. Once your application is created note the API Key and Secret Key that we will use to implement LinkedIn authentication in our application.

Step 3 Create ASP.Net Application

  1. Open Visual Studio and create a new Web Application project.
  2. Add references to Hammock library either by manually referencing from folder or just referencing through NuGet in Visual Studio Directly as shown below.

    Following are the Hammock assemblies we will utilize in the project.

  3. In the Default.aspx page add a button to login with LinkedIn and in that button’s click event call RequestTokenAndAuthorize method which is shown below.
  4. In the Default.aspx page create a new Method named RequestTokenAndAuthorize and place following code.

    public
    void RequestTokenAndAuthorize()

    {


    var credentials = new Hammock.Authentication.OAuth.OAuthCredentials

    {

     CallbackUrl = http://localhost/LinkedInAuthWebSite/Callback.aspx”,

     ConsumerKey = “API Key”,

     ConsumerSecret = “Secret Key”,

    Type = Hammock.Authentication.OAuth.OAuthType.RequestToken

    };


    var client = new Hammock.RestClient

    {

    Authority = https://api.linkedin.com/uas/oauth”, Credentials = credentials };


    var request = new Hammock.RestRequest { Path = “requestToken” };

    Hammock.RestResponse response = client.Request(request);


    String[] strResponseAttributes = response.Content.Split(‘&’);


    string token = strResponseAttributes[0].Substring(strResponseAttributes[0].LastIndexOf(‘=’) + 1);


    string authToken = strResponseAttributes[1].Substring(strResponseAttributes[1].LastIndexOf(‘=’) + 1);

    Session[“Token”] = token;

    Session[“TokenSecret”] = authToken;

    Response.Redirect(https://www.linkedin.com/uas/oauth/authorize?oauth_token=” + token);

}

CallBack URL will be called when the authorization is successfully done by LinkedIn.

  1. Now Create a CallBack page where the callback takes place when the authorization is done after successful login. In my case I have created a Callback.aspx.
  2. In the Callback page place following code in the Page_Load method.

protected
void Page_Load(object sender, EventArgs e)

{


String verifier = Request.QueryString[“oauth_verifier”].ToString();

Session[“Verifier”] = verifier;


var credentials = new Hammock.Authentication.OAuth.OAuthCredentials

{

 ConsumerKey = “API Key”,

 ConsumerSecret = “Secret Key”,

Token = Session[“Token”].ToString(),

 TokenSecret = Session[“TokenSecret”].ToString(),

Verifier = verifier,

Type = Hammock.Authentication.OAuth.OAuthType.AccessToken,

 ParameterHandling = Hammock.Authentication.OAuth.OAuthParameterHandling.HttpAuthorizationHeader,

 SignatureMethod = Hammock.Authentication.OAuth.OAuthSignatureMethod.HmacSha1,

Version = “1.0”

};


var client = new
RestClient { Authority = https://api.linkedin.com/uas/oauth”, Credentials = credentials, Method = WebMethod.Post };


var request = new
RestRequest { Path = “accessToken” };


RestResponse response = client.Request(request);


String[] strResponseAttributes = response.Content.Split(‘&’);


string token = strResponseAttributes[0].Substring(strResponseAttributes[0].LastIndexOf(‘=’) + 1);


string authToken = strResponseAttributes[1].Substring(strResponseAttributes[1].LastIndexOf(‘=’) + 1);

Session[“AccessToken”] = token;

Session[“AccessSecretToken”] = authToken;

 GetUserProfile();

}

  1. GetUserProfile method is used to get the Logged in User First Name and Last name to display on Callback page.

public
void GetUserProfile()

{


var request = new
RestRequest

{

Path = “~”

};


var credentials = new Hammock.Authentication.OAuth.OAuthCredentials

{

Type = Hammock.Authentication.OAuth.OAuthType.AccessToken,

 SignatureMethod = Hammock.Authentication.OAuth.OAuthSignatureMethod.HmacSha1,

 ParameterHandling = Hammock.Authentication.OAuth.OAuthParameterHandling.HttpAuthorizationHeader,

 ConsumerKey = “API Key”,

 ConsumerSecret = “Secret Key”,

Token = Session[“AccessToken”].ToString(),

 TokenSecret = Session[“AccessSecretToken”].ToString(),

Verifier = Session[“Verifier”].ToString()

};


var client = new
RestClient()

{

Authority = http://api.linkedin.com/v1/people”, Credentials = credentials, Method = WebMethod.Get

};


var MyInfo = client.Request(request);


String content = MyInfo.Content.ToString();


var person = from c in
XElement.Parse(content).Elements()


select c;


String fullName=String.Empty;


foreach (var element in person)

{


if((element.Name == “first-name”) || (element.Name==“last-name”))

 fullName += element.Value.ToString();

}

lblName.Text = fullName;

}

Step 4 Run the Application

  1. Run your ASP.Net web application.
  2. Click on the Login via Linked In button to authenticate through linked in. (This button was manually added in the default.aspx page above).

  3. Application requests the RequestToken based on the API key and Secret key and displays the LinkedIn login form as below

  4. Enter your Linked In Credentials and press “Ok, I’ll Allow It”
  5. It will fetch the Access Token and get the User profile and displayed it in the Callback.aspx page.

Configuring Facebook Authentication in SharePoint 2010

I got a task to configure Facebook Authentication couple of days back. I explored couple of blogs like PointBridge and Osnapz , they are good blog posts it give you an idea how to do that but overall i didn’t find anything like a step by step guide for those users who are doing it first time. Also when i started configuring Facebook Authentication i came across several issues which serves a lot of time and eventually my whole day was spent doing that. Therefore, i thought to make a blog entry which provides Step to Step guide for configuring Facebook Authentication in SharePoint 2010.

Following are the steps to configure Facebook Authentication for SharePoint sites.

Step 1: Download and Install Components

  1. Download and Install Windows Identity Framework SDK from http://www.microsoft.com/download/en/details.aspx?utm_source=feedburner&utm_medium=feed&utm_campaign=Feed%3a+MicrosoftDownloadCenter+(Microsoft+Download+Center)&utm_content=Google+Reader&id=4451
  2. Download Json.Net from
    http://json.codeplex.com/

Step 2: Create a new ASP.Net website

  1. Open Visual Studio and click on File> New Website
  2. Specify Website Name and path to the folder where you want to store the website and click on OK
  3. It will create a new Website.
  4. Now associate a certificate with this Website and enable SSL.
  5. Open IIS Manager by typing inetmgr from the run option in windows OS.
  6. Open Server Certificates and click on Create Self-Signed Certificate.
  7.  

     

  8. Specify certificate friendly name, click OK.
  9.  

     

  10. Certificate will be created. Now associate this certificate to your Website
  11. Right click on the Server in IIS and click on Add Website. Specify Site Name and Physical Path, Select Port and click on Ok. Your website will be hosted on IIS.
  12. Select Website and click on Bindings from the left Panel.
  13. Click on Add and select the type ‘Https’ and specify any port by default it uses 443 but you can assign any other port as well. Select certificate you just created and click OK.
  14. Now the server certificate has been associated with your website.
  15. Export this certificate and save it somewhere in your system. We need this when running power shell scripts.
  16. Now Open Visual Studio and change the Sever settings in the Property Pages of the website.
  17. Right click on your website and click on Property Pages
  18. Go to the Startup Options and select Use custom server option and specify the Website URL that is hosted on IIS (Use SSL one).
  19. Now navigate to your website and test it should be in working state and there should not be any issue.
  20.  

 

Step 3: Create an STS Site from ASP.Net website

 

  1. Go to the Visual Studio and right click on the Website project and click on Add STS Reference
  2. It will pop up a Wizard window just click Next.
  3. In the next window select “Create a New STS Project in the current Solution”.
  4. Click on Finish.
  5. You will notice a new Website will be added in the solution.
  6. Now Open the IIS Manager and change the physical path to the newly STS website.
  7. Just click on Website in the IIS Manager
  8. Click on Basic Settings from the Right Panel in IIS Manager
  9. Specify new path and click OK.
  10. Now Test your STS website it should run without any issue.

Step 4: Create Application in Facebook

  1. Navigate to http://facebook.com/developers
  2. Sign in with your account
  3. Create new Application using Create New Application option
  4. Provide name
  5. Click ok It will create a new application
  6. Now Click on Edit Setting and Specify your ASP.Net site URL. We need to specify this so it will redirect it to the default.aspx after successful authentication.
  7. Note Application Id and Secret Key that we will reference in the ASP.Net code.
  8. Now we are ready to move next on Step 5.
  9.  

Step 5: Execute Scripts on Power Shell

Open SharePoint 2010 Management Shell and execute following scripts in order.

  1. $cert = New-Object System.Security.Cryptography.X509Certificates.X509Certificate2(“c:\yourexported_cert.cer”)
  2. $map1 = New-SPClaimTypeMapping “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/authentication” -IncomingClaimTypeDisplayName “FacebookID” –SameAsIncoming
  3. $map2 = New-SPClaimTypeMapping -IncomingClaimType “http://schemas.xmlsoap.org/ws/2005/05/identity/claims/name” -IncomingClaimTypeDisplayName “Display Name” -LocalClaimType http://schemas.xmlsoap.org/ws/2005/05/identity/claims/givenname
  4. $realm = “urn:researchfacebook.com:facebook” (Specify any urn but note it)
  5. $signinurl = https://localhost:4431/Website_STS/ (Your ASP.Net website address)
  6. New-SPTrustedIdentityTokenIssuer -Name “Facebook” -Description “Facebook custom STS” -Realm $realm -ImportTrustCertificate $cert -ClaimsMappings $map1,$map2 -SignInUrl $signinurl -IdentifierClaim $map1.InputClaimType
  7. New-SPTrustedRootAuthority -Name “Facebook custom STS token signing certificate” -Certificate $cert

 

Step 6: Modify Code and Edit Configuration file

1. Create a new oAuthFacebook.cs class and add it in the App_Code folder in the Website project.
Following is a code of oAuthFacebook.cs. Change the Yellow highlighted part according to your application.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Net;
using System.Collections.Specialized;
using System.IO;

///

/// Summary description for oAuthFacebook
///

public class oAuthFacebook
{
public enum Method { GET, POST };
public const string AUTHORIZE = “https://graph.facebook.com/oauth/authorize”;
public const string ACCESS_TOKEN = “https://graph.facebook.com/oauth/access_token”;
public const string CALLBACK_URL = “https://localhost:4431/Login.aspx”;

private string _consumerKey = “”;
private string _consumerSecret = “”;
private string _token = “”;

#region Properties

public string ConsumerKey
{
get
{
if (_consumerKey.Length == 0)
{
//Your application ID
_consumerKey = “000000000000000”;
}
return _consumerKey;
}
set { _consumerKey = value; }
}

public string ConsumerSecret
{
get
{
if (_consumerSecret.Length == 0)
{
//Your application secret key
_consumerSecret = “00000000000000000000000000000000”;
}
return _consumerSecret;
}
set { _consumerSecret = value; }
}

public string Token { get { return _token; } set { _token = value; } }

#endregion

///

/// Get the link to Facebook’s authorization page for this application.
///

/// The url with a valid request token, or a null string.
public string AuthorizationLinkGet()
{
return string.Format(“{0}?client_id={1}&redirect_uri={2}”, AUTHORIZE, this.ConsumerKey, CALLBACK_URL);
}

///

/// Exchange the Facebook “code” for an access token.
///

/// The oauth_token or “code” is supplied by Facebook’s authorization page following the callback.
public void AccessTokenGet(string authToken)
{
this.Token = authToken;
string accessTokenUrl = string.Format(“{0}?client_id={1}&redirect_uri={2}&client_secret={3}&code={4}”,
ACCESS_TOKEN, this.ConsumerKey, CALLBACK_URL, this.ConsumerSecret, authToken);

string response = WebRequest(Method.GET, accessTokenUrl, String.Empty);

if (response.Length > 0)
{
//Store the returned access_token
NameValueCollection qs = HttpUtility.ParseQueryString(response);

if (qs[“access_token”] != null)
{
this.Token = qs[“access_token”];
}
}
}

///

/// Web Request Wrapper
///

/// Http Method
/// Full url to the web resource
/// Data to post in querystring format
/// The web server response.
public string WebRequest(Method method, string url, string postData)
{

HttpWebRequest webRequest = null;
StreamWriter requestWriter = null;
string responseData = “”;

webRequest = System.Net.WebRequest.Create(url) as HttpWebRequest;
webRequest.Method = method.ToString();
webRequest.ServicePoint.Expect100Continue = false;
webRequest.UserAgent = “[You user agent]”;
webRequest.Timeout = 20000;

if (method == Method.POST)
{
webRequest.ContentType = “application/x-www-form-urlencoded”;

//POST the data.
requestWriter = new StreamWriter(webRequest.GetRequestStream());

try
{
requestWriter.Write(postData);
}
catch
{
throw;
}

finally
{
requestWriter.Close();
requestWriter = null;
}
}

responseData = WebResponseGet(webRequest);
webRequest = null;
return responseData;
}

///

/// Process the web response.
///

/// The request object.
/// The response data.
public string WebResponseGet(HttpWebRequest webRequest)
{
StreamReader responseReader = null;
string responseData = “”;

try
{
responseReader = new StreamReader(webRequest.GetResponse().GetResponseStream());
responseData = responseReader.ReadToEnd();
}
catch
{
throw;
}
finally
{
webRequest.GetResponse().GetResponseStream().Close();
responseReader.Close();
responseReader = null;
}

return responseData;
}
}

2. In this step we will replace the existing logic in the Login.aspx for Facebook Authentication
3. Open Login.aspx and replace with following code.

using System;
using System.Web.Security;
using System.Web;
using System.Collections.Generic;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
public partial class Login : System.Web.UI.Page
{
protected void Page_Load( object sender, EventArgs e )
{
string url = string.Empty;
oAuthFacebook fbAuth = new oAuthFacebook();

if (Request[“code”] == null)
{
// Response.Redirect(“http://www.google.com”);
if (Request.QueryString[“ReturnUrl”] != null)
HttpContext.Current.Session.Add(“OriginalQueryString”, Request.QueryString.ToString());

//Redirect the user back to Facebook for authorization.
Response.Redirect(fbAuth.AuthorizationLinkGet());
}
else
{
//Get the access token and secret.

fbAuth.AccessTokenGet(Request[“code”]);

if (fbAuth.Token.Length > 0)
{
url = “https://graph.facebook.com/me?fields=id,name,verified,picture&access_token=” + fbAuth.Token;
string json = fbAuth.WebRequest(oAuthFacebook.Method.GET, url, String.Empty);

Dictionary claims = GetClaims(json);
HttpContext.Current.Session.Add(“AuthClaims”, claims);

FormsAuthentication.SetAuthCookie(“Facebook Test”, false);
Response.Redirect(“default.aspx?” + HttpContext.Current.Session[“OriginalQueryString”]);
}
}
}

private Dictionary GetClaims(string json)
{
Dictionary claims = new Dictionary();
JObject profile = JObject.Parse(json);

string userID = profile[“id”].ToString().Replace(@””””, “”);
string name = profile[“name”].ToString().Replace(@””””, “”);
string verified = profile[“verified”].ToString().Replace(@””””, “”);
string picture = profile[“picture”].ToString().Replace(@””””, “”);

if (!String.IsNullOrEmpty(userID))
claims.Add(System.IdentityModel.Claims.ClaimTypes.Authentication, userID);
if (!String.IsNullOrEmpty(name))
claims.Add(System.IdentityModel.Claims.ClaimTypes.Name, name);
if (!String.IsNullOrEmpty(picture))
claims.Add(System.IdentityModel.Claims.ClaimTypes.Webpage, picture);

return claims;
}

}

4. In the CertificateUtil.cs I have changed the logic from comparing Subject Name with Friendly Name of the certificate. This is done because I have multiple self- signed certificates installed on my server and all having a same subject name i.e. machine name. So the only unique name I found was Friendly Name, that’s why I have changed it to Friendly Name.
public static X509Certificate2 GetCertificate( StoreName name, StoreLocation location, string subjectName )
{
X509Store store = new X509Store( name, location );
X509Certificate2Collection certificates = null;
store.Open( OpenFlags.ReadOnly );

try
{
X509Certificate2 result = null;

//
// Every time we call store.Certificates property, a new collection will be returned.
//
certificates = store.Certificates;

for ( int i = 0; i < certificates.Count; i++ )
{
X509Certificate2 cert = certificates[i];

if ( cert.FriendlyName.ToLower() == subjectName.ToLower() )
{
if ( result != null )
{
throw new ApplicationException( string.Format( "There are multiple certificates for subject Name {0}", subjectName ) );
}

result = new X509Certificate2( cert );
}
}

if ( result == null )
{
throw new ApplicationException( string.Format( "No certificate was found for subject Name {0}", subjectName ) );
}

return result;
}
finally
{
if ( certificates != null )
{
for ( int i = 0; i < certificates.Count; i++ )
{
X509Certificate2 cert = certificates[i];
cert.Reset();
}
}

store.Close();
}
}
}

5. GetScope Method of CustomTokenSecurityService.cs looks like following

protected override Scope GetScope( IClaimsPrincipal principal, RequestSecurityToken request )
{
// ValidateAppliesTo( request.AppliesTo );

//
// Note: The signing certificate used by default has a Distinguished name of "CN=STSTestCert",
// and is located in the Personal certificate store of the Local Computer. Before going into production,
// ensure that you change this certificate to a valid CA-issued certificate as appropriate.
//
Scope scope = new Scope( request.AppliesTo.Uri.OriginalString, SecurityTokenServiceConfiguration.SigningCredentials );
scope.TokenEncryptionRequired = false;
//Specify the Realm name as defined in the script in PowerShell.
if (scope.AppliesToAddress == "urn:fbauth.com:facebook")
{
//Specify the Web Application URL which has claim based authentication as Facebook as a Trusted provider.
scope.ReplyToAddress = "http://win-6rnn5tdp5c6:47213/_trust/&quot;;

}
else
{
scope.ReplyToAddress = scope.AppliesToAddress;
}
return scope;

}

6. In the Web.config file update the SigningCertificateName

 

 

Step 7: Create a New Web Application in SharePoint 2010

  1. Open Central Administration
  2. Click on Manage Web Applications
  3. Select New Web Application option from the Ribbon bar.
  4. In the New Web Application window select Claim Based as Authentication mode.

  5. Select Facebook as Trusted Identity Provider

  6. Click OK
  7. Now Once the Web Application is created we need to create a Site collection.
  8. Click on Create Site Collections under Site Collections
  9. Make sure your newly created Web Application is selected for which you are creating a site collection.
  10. Specify Title and select any template, In the Primary Site Collection Administrator select Browse people/group button.

 

  1. Select People window opens and there you will see Facebook in the left pane

     

     

  2. Now select Facebook and click on the search icon button to search. You will see one Facebook user will populate in the main pane.

     

     

  3. Select and click ok
  4. We are done now we will navigate to our Web Application and login with Facebook account.

[Hint]

 

 

 

Step 8: Navigating to SharePoint 2010 Site

 

  1. Navigate to your SharePoint site. It will show you the option to select Authentication type as Facebook and Windows Authentication.
  2. Just Select Facebook.

  3. As the certificate I have used is self- signed that’s why It will show some warning as below. Just click on Continue to the website and proceed.

  1. It will show the Facebook login page. Enter your user name and password and click on Sign In.

     

  2. It will show the Main SharePoint site Home page.

     

Note: One thing you want to do here is when you will login to your account first time with your Facebook Id you will be prompted Access Denied in SharePoint site and it will give show you the numeric ID of your Facebook Account that this does not have an access to your site. Just copy that ID and place it in any of the SharePoint User Groups of your Site Collection or even specify it as a Primary or Secondary Administrator just to test. Then now when you re login, it will show the main SharePoint site page.