This blog will help to understand how we are going to integrate and use existing LinkedIn profile to perform basic authentication. Here we will also discuss how we can extract useful information from api provided by LinkedIn.

Before starting you can review my previous blog about building Basic Asp.net core Application.

Overview

Any Website designing require some sort of authentication and authorization mechanism in order to serve user specific Web Content. In classic we application, we use to write our own mechanism using form authentication. This involves lots of backend work as well as have lots of security concerns.

In order to avoid complexity we use external logins provided by many vendors like Google, Facebook, Microsoft, LinkedIn etc. In previous version of Asp.net we were able to authenticate using these providers but with limited capability and have to write lots of code in order to enable such feature.

Better Approach

Open source project like OAuth2 have tried to solve this problem and have come up with better implementation approach to provide simple authentication.

Asp.net core has also included OAuth2 provider which is being used to perform authentication by writing minimum code. To learn more about OAuth, please visit its official site https://auth0.com

Following steps are involved in setting up Authentication using LinkedIn.

LinkedIn Developer Network

1> Register your application at https://www.linkedin.com/developer

Once you have successfully registered your application you will be provide with “Clientid” and  “ClientSecret” which is used to get access token on successful authentication. This access token is used to keep identify user and keep active session by saving into Cookies or LocalStorage.

Next step is to set CallbackUrl which will be used to redirect once user is successfully authenticated.

Now we need to configure Asp.net core Application to enable authentication using OAuth2.

Add following LinkedIn specific config entries in appsettings.json file.

"LinkedIn": {
    "Clientid": "your clientid",
    "ClientSecret": "your client secret",
    "CallbackUrl": "your callback url",
    "AuthorizationEndpoint": "https://www.linkedin.com/oauth/v2/authorization",
    "TokenEndpoint": "https://www.linkedin.com/oauth/v2/accessToken",
    "UserInformationEndpoint": "https://api.linkedin.com/v1/people/~:(id,formatted-name,email-address,picture-url)",
    "Scope": [
      "r_basicprofile",
      "r_emailaddress"
    ]
}

Now add dependencies in project.json file which are required to enable OAuth authentication in Asp.net core.

"Microsoft.AspNetCore.Authentication": "1.0.0",
"Microsoft.AspNetCore.Authentication.Cookies": "1.0.0",
"Microsoft.AspNetCore.Authentication.OAuth": "1.0.0",

As authentication with OAuth2 depend on cookies so we need to register cookies with application middleware.

Once we are done with all the configuration as mentioned above we need to update our middleware code to support Linkedin Authentication.

Add following Code to add Cookies support in middleware in Startup.cs

app.UseIdentity();

app.UseCookieAuthentication(new CookieAuthenticationOptions
{
                AuthenticationScheme = "Cookies",
                LoginPath = new PathString("/login"),
                AccessDeniedPath = new PathString("/logout"),
                CookieName = "auth-token",
                AutomaticAuthenticate = true,
                AutomaticChallenge = true,
                Events = new CookieAuthenticationEvents
                {
                }
 });

Create a helper file ConfigureOAuth.cs which will contain code to add LinkedIn Authentication scheme.

public class ConfigureOAuth
    {        

        public void Register(IApplicationBuilder app, IHostingEnvironment env, IOptions<LinkedInSettings> linkedInSettings)
        {
            // Add the OAuth2 middleware
            app.UseOAuthAuthentication(new OAuthOptions
            {
                // We need to specify an Authentication Scheme
                AuthenticationScheme = "LinkedIn",

                ClaimsIssuer = "OAuth2-LinkedIn",

                // Configure the LinkedIn Client ID and Client Secret
                ClientId = linkedInSettings.Value.ClientId,
                ClientSecret = linkedInSettings.Value.ClientSecret,

                // Set the callback path, so LinkedIn will call back to http://APP_URL/signin-linkedin
                // Also ensure that you have added the URL as an Authorized Redirect URL in your LinkedIn application
                CallbackPath = new PathString(linkedInSettings.Value.CallbackUrl),

                // Configure the LinkedIn endpoints                
                AuthorizationEndpoint = linkedInSettings.Value.AuthorizationEndpoint,
                TokenEndpoint = linkedInSettings.Value.TokenEndpoint,
                UserInformationEndpoint = linkedInSettings.Value.UserInformationEndpoint,

                Scope = { "r_basicprofile", "r_emailaddress" },

                Events = new OAuthEvents
                {
                    // The OnCreatingTicket event is called after the user has been authenticated and the OAuth middleware has
                    // created an auth ticket. We need to manually call the UserInformationEndpoint to retrieve the user's information,
                    // parse the resulting JSON to extract the relevant information, and add the correct claims.
                    OnCreatingTicket = async context =>
                    {

                        var request = new HttpRequestMessage(HttpMethod.Get, context.Options.UserInformationEndpoint);
                        request.Headers.Authorization = new AuthenticationHeaderValue("Bearer", context.AccessToken);
                        request.Headers.Add("x-li-format", "json"); // Tell LinkedIn we want the result in JSON, otherwise it will return XML

                        var response = await context.Backchannel.SendAsync(request, context.HttpContext.RequestAborted);
                        response.EnsureSuccessStatusCode(); 
                            
                        // user this response to set cookies or claims Authentication.

                        
                    }
                }
            });
        }
    }

Call above method in Startup.cs which will add LinkedIn authentication scheme in OAuth middleware.

public void Configure(IApplicationBuilder app, IHostingEnvironment env, IOptions<LinkedInSettings> linkedInSettings)

 // Used to register OAuth for linkedIn.
  new ConfigureOAuth().Register(app, env, linkedInSettings);
}

Now we need to tell Asp.net core on accessing which url OAuth authentication needs to be triggered. This is achieved by registering app routes in startup.cs

 // Listen for requests on the /login path, and issue a challenge to log in with the LinkedIn middleware
            app.Map("/external-login", builder =>
            {                
                builder.Run(async context =>
                {                   

                    // Return a challenge to invoke the LinkedIn authentication scheme
                    await context.Authentication.ChallengeAsync("LinkedIn", properties: new AuthenticationProperties() { RedirectUri = "/profile/manage" });
                });
            });

            // Listen for requests on the /logout path, and sign the user out
            app.Map("/logout", builder =>
            {
                builder.Run(async context =>
                {
                    // Sign the user out of the authentication middleware (i.e. it will clear the Auth cookie)
                    await context.Authentication.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);

                    // Redirect the user to the home page after signing out
                    context.Response.Redirect("/");
                });
            });

We are almost done with all the relevant changes in Middleware.

Next step is to add Asp.net views which will be used to test login/logout feature.

In case, if you are build SPA using framework like Angularjs or Angular2, then you need to add views and controllers which will display user information once successfully authenticated.

Build project and run application server.

On Home page, click on login button, you will be redirected to Linkedin for authentication. On successful authentication you will be redirected to application specific page.

Conclusion

Using OAuth and Asp.net core, we can build web application which can be easily integrated with external authentication providers. We need to follow almost similar steps when trying to authenticate using other providers like Google, Microsoft or Facebook.