My previous article Integrate Google (Gmail) Authentication in Asp.Net MVC 5.0 - OAuth 2.0 discussed about integrating Gmail id for authenticating users in Asp.Net MVC application using OAuth 2.0. In this article, let’s see how we can integrate LinkedIn authentication in Asp.Net MVC site. We will use same DotNetOpenAuth components in this article too to develop this feature.
The LinkedIn authentication flow is also similar to integrating Google. To recap,
-
Users will be redirected to LinkedIn Login page from Asp.Net MVC application.
-
User Enters Username and Password. User allows the third party (our MVC application) application access to read the LinkedIn profile details. As I said in my previous article, this is a onetime process.
-
LinkedIn redirects the user to a pre-configured landing on the application by passing access token and user’s basic details for local user registration.
-
Application gets the details form LinkedIn in landing page and create the user in local database and issue a forms authentication ticket.
DotNetOpenAuth Component
The DotNetOpenAuth package that we add using Nuget does not have OAuth 2.0 implementation for LinkedIn. For LinkedIn OAuth 2.0 support, we have the LinkedInOAuth2 client implementation in below GitHub repository which we need to include.
https://github.com/sanction10/DotNetOpenAuth.LinkedInOAuth2
So, to integrate LinkedIn we need to add the DotNetOpenAuth packages and additionally use the OAuth 2.0 client implementation from the above GitHub repository.
The pre-requisite of integrating any OAuth providers into our website require us to create OAuth applications on the provider (LinkedIn in this case) that gives a Client Id and Secret for our app to use. It is in this place we provide information to OAuth providers about our application and the redirect url(landing url) once the provider authenticate the users.
Creating OAuth LinkedIn application
-
Go to https://developer.linkedin.com. Sign-in with your LinkedIn id.
-
Click “My Apps” tab in the top nav bar. Click Create Application button to create new OAuth 2.0 application.
-
Fill in all the mandatory details. Enter your website root url, phone, email and a logo. Click Submit to create the OAuth application.
-
This will create the application and display the Client ID and Secret. Copy this to configure in our application.
-
Select r_emailaddress if not selected already and add Authorized Redirect URLs. Click Update.
You can also view the created application on “My Apps” tab in developer console after creation
The implementation is very similar to integrating Google except we need to add LinkedIn OAuth 2 client from GitHub reposiory.
Creating New Project
-
Open Visual Studio (2012/2015) and create a new Asp.Net MVC project. Select Empty project template to add the required Nuget package ourselves. I have used “Asp.Net MVC 5 Empty Project”
-
Add the below Nuget packages into your solution.
-
DotNetOpenAuth.AspNet
-
Microsoft.AspNet.Membership.OpenAuth
-
Microsoft.AspNet.Providers.LocalDB
-
Note – For simplicity, I will use Microsoft.AspNet.Providers.LocalDB Asp.Net Universal Provider to create and persist user in localDb under App_data. You can call your User data access code to create user once the provider calls the landing page with user details.
-
Get the LinkedIn OAuth2 client from the repository here. You can download the source as zip file from repository page by clicking “Clone or download”.
Unzip the project and you can either include the whole project into your solution or just include LinkedInOAuth2Client.cs class into your project. I have just added the LinkedInOAuth2Client.cs class into a folder LinkedInOAuth2Client. Refer below,
-
Add a new class file AuthConfig.cs under App_Start Folder. Let’s configure and add the LinkedIn OAuth 2 client into the OpenAuth AuthenticationClients collection. This is where we will put the client Id and client secret to connect LinkedIn OAuth 2.0 API.
public static class AuthConfig
{
public static void RegisterOpenAuth()
{
if (OpenAuth.AuthenticationClients.GetByProviderName("linkedin") == null)
{
var client = new LinkedInOAuth2Client("[ClientId]", "[ClientSecret]");
OpenAuth.AuthenticationClients.Add("linkedin", () => client);
}
}
}
Include DotNetOpenAuth.LinkedInOAuth2 and Microsoft.AspNet.Membership.OpenAuth namespace in using section for the above code to work.
Note – You can add multiple OAuth provider clients like Google, FaceBook, Twitter here. You can get the registered OAuth clients by access OpenAuth.AuthenticationClients collection property across application. The default project template’s AccountController code uses this collection when you select “Individual User Accounts” or “Internet Applications” as template when creating new projects.
-
Call this method from Global.asax Application_Start event to register the LinkedIn OAuth client during app startup.
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
RouteConfig.RegisterRoutes(RouteTable.Routes);
AuthConfig.RegisterAuth();
}
-
Let’s add AccountController into Controller folder and add Login methods. For easy understanding, let’s not add local registration and FormsAuthentication local login process here. We will just add a “Login Using LinkedIn” button in the login page similar to below.
-
Add an action method to redirect user to LinkedIn on click of the above “Login Using LinkedIn” link.
public ActionResult RedirectToLinkedIn()
{
string provider = "linkedin";
string returnUrl = "";
return new ExternalLoginResult(provider, Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl }));
}
internal class ExternalLoginResult : ActionResult
{
public ExternalLoginResult(string provider, string returnUrl)
{
Provider = provider;
ReturnUrl = returnUrl;
}
public string Provider { get; private set; }
public string ReturnUrl { get; private set; }
public override void ExecuteResult(ControllerContext context)
{
OpenAuth.RequestAuthentication(Provider, ReturnUrl);
}
}
When user clicks the link, he or she will be redirected to LinkedIn login page by specifying “/Account/ExternalLoginCallback” as the redirect url. This url should match the url we saved when creating OAuth application on LinkedIn developer console page.
-
Next, let’s add the landing page or redirect url action method to get back access token and user details LinkedIn is forwarding.
[AllowAnonymous]
public ActionResult ExternalLoginCallback(string returnUrl)
{
string ProviderName = OpenAuth.GetProviderNameFromCurrentRequest();
if (ProviderName == null || ProviderName == "")
{
NameValueCollection nvs = Request.QueryString;
if (nvs.Count > 0)
{
if (nvs["state"] != null)
{
NameValueCollection provideritem = HttpUtility.ParseQueryString(nvs["state"]);
if (provideritem["__provider__"] != null)
{
ProviderName = provideritem["__provider__"];
}
}
}
}
LinkedInOAuth2Client.RewriteRequest();
var redirectUrl = Url.Action("ExternalLoginCallback", new { ReturnUrl = returnUrl });
var retUrl = returnUrl;
var authResult = OpenAuth.VerifyAuthentication(redirectUrl);
string ProviderDisplayName = OpenAuth.GetProviderDisplayName(ProviderName);
if (!authResult.IsSuccessful)
{
return Redirect(Url.Action("Login", "Account"));
}
// User has logged in with provider successfully
// Check if user is already registered locally
if (OpenAuth.Login(authResult.Provider, authResult.ProviderUserId, createPersistentCookie: false))
{
return Redirect(Url.Action("Index","Home"));
}
//Get provider user details
string ProviderUserId = authResult.ProviderUserId;
string ProviderUserName = authResult.UserName;
string FirstName = null;
string LastName = null;
string Email = null;
if (Email == null && authResult.ExtraData.ContainsKey("email-address"))
{
Email = authResult.ExtraData["email-address"];
}
if (FirstName == null && authResult.ExtraData.ContainsKey("first-name"))
{
FirstName = authResult.ExtraData["first-name"];
}
if (LastName == null && authResult.ExtraData.ContainsKey("last-name"))
{
LastName = authResult.ExtraData["last-name"];
}
if (User.Identity.IsAuthenticated)
{
// User is already authenticated, add the external login and redirect to return url
OpenAuth.AddAccountToExistingUser(ProviderName, ProviderUserId, ProviderUserName, User.Identity.Name);
return Redirect(Url.Action("Index", "Home"));
}
else
{
// User is new, save email as username
string membershipUserName = Email ?? ProviderUserId;
var createResult = OpenAuth.CreateUser(ProviderName, ProviderUserId, ProviderUserName, membershipUserName);
if (!createResult.IsSuccessful)
{
ViewBag.Message = "User cannot be created";
return View();
}
else
{
// User created
if (OpenAuth.Login(ProviderName, ProviderUserId, createPersistentCookie: false))
{
return Redirect(Url.Action("Index", "Home"));
}
}
}
return View();
}
The above code will create user and login locally. On successful login, the user will be created by the provider in localDb under App_Data and redirected to Home page. You can view the user details in localDb using Visual Studio Server Explorer.
Note - The First Name, Last Name and Email of user from LinkedIn can be got from the ExtraData dictionary. You can use this information to save it to user table.
-
Finally, we will add LogOff action to logoff user.
public ActionResult LogOff()
{
FormsAuthentication.SignOut();
return Redirect(Url.Action("Index","Home"));
}
-
That’s it. Press F5.
Click Login Using LinkedIn Link. This will redirect to LinkedIn Login page. Enter LinkedIn credentials and click “Allow access” button to allow LinkedIn to pass user profile info to the application redirect url. Refer below,
Download the source and see it in action. I have also included WebForms version of the project for reference. The WebForms version will use the default project “Individual User Accounts” template code for LinkedIn integration. Before execting, please make sure you create Linked OAuth Application in LinkedIn Developer site and confire the ClientId and Secret in AuthConfig.cs file.