Support us .Net Basics C# SQL ASP.NET Aarvi MVC Slides C# Programs Subscribe Download

ASP.NET Web API google authentication

Suggested Videos
Part 25 - Web api bearer token example
Part 26 - ASP.NET Web API logout
Part 27 - How to get authenticated user identity name in asp.net web api

In this video we will discuss
1. Benefits of social logins
2. Using Google authentication with ASP.NET Web API



Benefits of social logins : Registration is simple and easy. All they have to provide is their social login username and password and the user is registered with our application. This also means one less password to remember. When users don’t have to remember mulitple usernames and passwords to login to multiple web sites, there will be less failed logins. As you know remembering multiple usernames and passwords is definitely as hassle.

From development point of view, we do not have to write code to manage usernames and passwords. All this is done by the external authentication providers like Google, Facebook, Twitter, Microsoft etc.



Using Google authentication with ASP.NET Web API : When the user clicks "Login with Google" button, he will be redirected to Google login page. The user will then provide his Google credentials. Once the login is successful, the user will be redirected to our application with an access token, which is a proof that the user is successfully authenticated and our web application grants access to the protected resources.

asp net web api external authentication

To use Google account for authentication, we will have to first register our application with Google. Here are the steps to register your application with Google. Once we successfully register our application with Google, we will be given a Client ID and Client Secret. We need both of these for using Google authentication with our Web API service.

Step 1 : To register your application go to 
https://console.developers.google.com

Step 2 : Login with your GMAIL account. Click on Credentials link on the left, and then create a new project, by clicking on "Create Project" button.

register application with google

Step 3 : Name your project "Test Project" and click "CREATE" button.

google developer console create project

Step 4 : The new project will be created. Click on "OAuth consent screen". In the "Product name shown to users" textbox type "Test Project" and click "Save" button

google oauth create application

Step 5 : The changes will be saved and you will be redirected to "Credentials" tab. If you are not redirected automatically, click on the "Credentials" tab and you will see "Create Credentials" dropdown button. Click on the button, and select "OAuth client ID" option

google developer console oauth

Step 6 : On the next screen, 
  • Select "Web application" radio button. 
  • Type "Web client 1" in the "Name" textbox.
  • In the "Authorized JavaScript origins" textbox type in the URI of your application. I have my web api application running at http://localhost:61358
  • In the "Authorized redirect URIs" textbox type in the redirect URI i.e the path in our application that users are redirected to after they have authenticated with Google. I have set it to http://localhost:61358/signin-google
  • Click the "Create" button
google developer console register app

You will see a popup with OAuth client ID and client secret. Make a note of both of them. We will need both of these later.

how to get google oauth client id

Step 7 : Enable Google+ API service. To do this click on "Library" link on the left hand pane.Under "Social APIs" click on "Google+ API" link and click "Enable" button.

Enable Google OAuth authentication in ASP.NET Web API service

Step 1 : In Startup.Auth.cs file in App_Start folder un-comment the following code block, and include ClientId and ClientSecret that we got after registering our application with Google.

app.UseGoogleAuthentication(new GoogleOAuth2AuthenticationOptions()
{
    ClientId = "Your Google Client Id",
    ClientSecret = "Your Google Client Secret"
});

Step 2 : In Login.html page include the following HTML table, just below "Existing User Login" table

<table class="table table-bordered">
    <thead>
        <tr class="success">
            <th>
                Social Logins
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <input type="button" id="btnGoogleLogin"
                        value="Login with Google" class="btn btn-success" />
            </td>
        </tr>
    </tbody>
</table>

Step 3 : In the script section, in "Login.html" page, wire up the click event handler for "Login with Google" button. 

$('#btnGoogleLogin').click(function () {
    window.location.href = "/api/Account/ExternalLogin?provider=Google&response_type=token&client_id=self&redirect_uri=http%3a%2f%2flocalhost%3a61358%2fLogin.html&state=GerGr5JlYx4t_KpsK57GFSxVueteyBunu02xJTak5m01";
});

Notice when we click the button we are redirecting the user to /api/Account/ExternalLogin

The obvious question that we get at this point is from where do we get this URL. To get this URL, issue a GET request to api/Account/ExternalLogins?returnUrl=%2F&generateState=true. Since in my case the application is running at http://localhost:61358, the complete URL is http://localhost:61358/api/Account/ExternalLogins?returnUrl=%2F&generateState=true. The following is the response I got

<ArrayOfExternalLoginViewModel xmlns:i="http://www.w3.org/2001/XMLSchema-instance" xmlns="http://schemas.datacontract.org/2004/07/EmployeeService.Models">
<ExternalLoginViewModel>
<Name>Google</Name>
<State>6Phc_u0Xkj3opJ9TymPhw9olZV_zB6Pjv_OcIfNAprk1</State>
<Url>
/api/Account/ExternalLogin?provider=Google&response_type=token&client_id=self&redirect_uri=http%3A%2F%2Flocalhost%3A61358%2F&state=6Phc_u0Xkj3opJ9TymPhw9olZV_zB6Pjv_OcIfNAprk1
</Url>
</ExternalLoginViewModel>
</ArrayOfExternalLoginViewModel>

Notice the Url, it is encoded. Now go to http://www.url-encode-decode.com/. Paste the URL in "Enter the text that you wish to encode or decode" textbox and click on "Decode Url" button. Notice the redirect_uri query string parameter. It is set to http://localhost:61358/ This parameter specifies the URI to redirect the user after they have been authenticated by Google. In our case we want the user to be redirected to the Login.html page. So URL encode the following URL
http://localhost:61358/Login.html

After you URL encode the above URL, it looks as shown below. Set it as the value for redirect_uri query string parameter
http%3A%2F%2Flocalhost%3A61358%2FLogin.html%2F

Step 4 : Open "ApplicationOAuthProvider.cs" file from "Providers" folder, and modify ValidateClientRedirectUri() method as shown below. The change is to set the Redirect URI to Login.html

public override Task ValidateClientRedirectUri
    (OAuthValidateClientRedirectUriContext context)
{
    if (context.ClientId == _publicClientId)
    {
        Uri expectedRootUri = new Uri(context.Request.Uri, "/Login.html");

        if (expectedRootUri.AbsoluteUri == context.RedirectUri)
        {
            context.Validated();
        }
    }

    return Task.FromResult<object>(null);
}

Step 5 : At this point build the solution and navigate to Login.html. Click on "Login with Google" button. Notice we are redirected to "Google" login page. Once we provide our Google credentials and successfully login, we are redirected to our application Login.html page with access token appended to the URL.

http://localhost:61358/Login.html#access_token=Pwf1kU_LkrdueJbnaDtZohLsUHMDBvrYrdMxL59c4pilUC0&token_type=bearer&expires_in=1209600&state=GerGr5JlYx4t_KpsK57GFSxVueteyBunu02xJTak5m01

Step 6 : Next we need to retrieve the access token from the URL. The following JavaScript function does this. Add a new JavaScript file to the Scripts folder. Name it GoogleAuthentication.js. Reference jQuery. You can find minified jQuery file in the scripts folder. Copy and and paste the following function in it. Notice we named the function getAccessToken()

function getAccessToken() {
    if (location.hash) {
        if (location.hash.split('access_token=')) {
            var accessToken = location.hash.split('access_token=')[1].split('&')[0];
            if (accessToken) {
                isUserRegistered(accessToken);
            }
        }
    }
}

Step 7 : Notice the above function calls isUserRegistered() JavaScript function which checks if the user is already registered with our application. isUserRegistered() function is shown below. To check if the user is registered we issue a GET request to /api/Account/UserInfo passing it the access token using Authorization header. If the user is already registered with our application, we store the access token in local storage and redirect the user to our protected page which is Data.html. If the user is not registered, we call a different JavaScript function - signupExternalUser(). We will discuss what signupExternalUser() function does in just a bit. Now copy and paste the following function also in GoogleAuthentication.js file.

function isUserRegistered(accessToken) {
    $.ajax({
        url: '/api/Account/UserInfo',
        method: 'GET',
        headers: {
            'content-type': 'application/JSON',
            'Authorization' : 'Bearer ' + accessToken
        },
        success: function (response) {
            if (response.HasRegistered) {
                localStorage.setItem('accessToken', accessToken);
                localStorage.setItem('userName', response.Email);
                window.location.href = "Data.html";
            }
            else {
                signupExternalUser(accessToken);
            }
        }
    });
}

Step 8 : If the Google authenticated user is not already registered with our application, we need to register him. This is done by signupExternalUser() function show below. To register the user with our application we issue a POST request to /api/Account/RegisterExternal, passing it the access token. Once the user is successfully registered, we redirect him again to the same URL, to which the user is redirected when we clicked the "Login with Google" button. Since the user is already authenticated by Google, the access token will be appended to the URL, which will be parsed by getAccessToken() JavaScript function. getAccessToken() function will again call isUserRegistered() function. Since the user is already registered with our application, we redirect him to the Data.html page and he will be able to see the employees data. Copy and paste the following function also in GoogleAuthentication.js file.

function signupExternalUser(accessToken) {
    $.ajax({
        url: '/api/Account/RegisterExternal',
        method: 'POST',
        headers: {
            'content-type': 'application/json',
            'Authorization': 'Bearer ' + accessToken
        },
        success: function () {
            window.location.href = "/api/Account/ExternalLogin?provider=Google&response_type=token&client_id=self&redirect_uri=http%3a%2f%2flocalhost%3a61358%2fLogin.html&state=GerGr5JlYx4t_KpsK57GFSxVueteyBunu02xJTak5m01";
        }
    });

}

Step 9 : In AccountController.cs, modify RegisterExternal() method as shown below. Notice we removed "RegisterExternalBindingModel" parameter and if (!ModelState.IsValid) code block.

// POST api/Account/RegisterExternal
[OverrideAuthentication]
[HostAuthentication(DefaultAuthenticationTypes.ExternalBearer)]
[Route("RegisterExternal")]
public async Task<IHttpActionResult> RegisterExternal()
{
    var info = await Authentication.GetExternalLoginInfoAsync();
    if (info == null)
    {
        return InternalServerError();
    }

    var user = new ApplicationUser() { UserName = info.Email, Email = info.Email };

    IdentityResult result = await UserManager.CreateAsync(user);
    if (!result.Succeeded)
    {
        return GetErrorResult(result);
    }

    result = await UserManager.AddLoginAsync(user.Id, info.Login);
    if (!result.Succeeded)
    {
        return GetErrorResult(result);
    }
    return Ok();
}

Step 10 : Finally, on Login.html page reference GoogleAuthentication.js file and call get getAccessToken() function

Build the solution and navigate to Login.html page and click on "Login with Google" button. Notice we are redirected to Google Login page. Once we provide our Google credentials and Login, we are redirected to Data.html page. When we click "Load Employees" button we see employees data.

At this point if you query AspNetUsers and AspNetUserLogins tables you will see an entry for your login is made into these 2 tables
  • Select * from AspNetUsers
  • Select * from AspNetUserLogins
ASP.NET Web API tutorial for beginners

54 comments:

  1. for understanding this tutorial which tutorials we need to watch?

    ReplyDelete
    Replies
    1. hahaha..same here..
      Took me straight 3 hours to build this from the scratch.

      At least now I know the flow how this works and other apis will follow same I guess.

      Delete
  2. Replies
    1. What's the issue? Can you elaborate a bit more?

      Delete
  3. ApplicationUser how to create sir

    ReplyDelete
  4. after this series please sir start series on design pattern...
    thank you .......

    ReplyDelete
  5. Would you please discuss external authentication providers like Twitter, Microsoft?

    Thanks

    ReplyDelete
  6. I have two questions.
    1. How to implement google auth in asp.net mvc web app? If so how do i get the redirect url for google login- externallogin or externallogincallback?
    2.As far as i know ,web api are meant only for services. Why do we use it like an web app?

    ReplyDelete
  7. Hello Venkat,
    I am getting this error while login with google account.
    I am able to get token but after this getting
    HTTP/1.1 401 Unauthorized
    Cache-Control: no-cache
    Pragma: no-cache
    Content-Type: application/json; charset=utf-8
    Expires: -1
    Server: Microsoft-IIS/10.0
    X-AspNet-Version: 4.0.30319
    WWW-Authenticate: Bearer
    WWW-Authenticate: Bearer
    X-Powered-By: ASP.NET
    Date: Wed, 03 May 2017 06:35:39 GMT
    Content-Length: 61

    {"Message":"Authorization has been denied for this request."}

    ReplyDelete
  8. Hi

    On step five I got error:invalid_request. I run vs2015
    I fixed it by removing / from the URI

    i.e
    http%3A%2F%2Flocalhost%3A61358%2FLogin.html

    and not

    http%3A%2F%2Flocalhost%3A61358%2FLogin.html%2F

    ReplyDelete
  9. I am getting error when trying to find api/Account/ExternalLogin

    ReplyDelete
  10. how to get the url which we fix in .
    aspx page

    ReplyDelete
  11. Hi. I follow all of your tutorials and have learnt so much. Thank you for such great tutorials here and on youtube. I wanted to know if you are interested in creating .net core version of this tutorial. I am struggling in the case of web api created on .net core because it doesnot scaffolds the code required for external authentication like accountcontroller and other files. It would be helpful if you could point me in right direction. Thankyou so much.

    ReplyDelete
  12. I need to apply Google Auth to an existing project. What NuGet package do i install?...there are many Google Oauth?? Please specify...thanks

    ReplyDelete
    Replies
    1. Microsoft.Owin.Security.Google sir

      Delete
  13. Hi Venkat Sir,

    My application is only allowing me to sign-in into Google+ once and not even asking permissions from me when I sign-in using my existing Google account.

    It also provides a new token in the browser's URL everytime I click on Login with Google button but doesn't redirects me to Sign-in with Google page.

    I am really frustrated now because my Application's irrespective behavior as well as to add on I have built it from the scratch thrice now by completely wacthing your videos from Part-18.

    Please help me with this issue.

    ReplyDelete
    Replies
    1. Open Gmail.com or any google page and logout from there before trying to login on localhost. Then you will get the login page. Logout in localhost wouldn't log you out of the google account.

      Delete
  14. Hi Venkat Sir,

    My application is only allowing me to sign-in into Google+ once and not even asking permissions from me when I sign-in using my existing Google account.

    It also provides a new token in the browser's URL everytime I click on Login with Google button but doesn't redirects me to Sign-in with Google page.

    I am really frustrated now because my Application's irrespective behavior as well as to add on I have built it from the scratch thrice now by completely wacthing your videos from Part-18.

    Please help me with this issue.

    ReplyDelete
  15. Can we execute the Google API like YouTube Data API v3 using these tokens?

    ReplyDelete
  16. Thanks for the videos..i am trying to implement this google authentication..but i m getting access_denied,error=access_denied
    in
    public async Task GetExternalLogin(string provider, string error = null)
    {}
    pls help me in that

    ReplyDelete
    Replies
    1. Add to your project Google+ API in Google API Console

      Delete
  17. My page is not redirecting to Data.html page,After successfull login it's again n again showing the login page with new access token.

    ReplyDelete
  18. My page is not redirecting to Data.html page,After successfull login it's again n again showing the login page with new access token.

    ReplyDelete
    Replies
    1. if your query is solved then tell me how you did it.

      Delete
    2. change the redirect url inside isUserRegistered() function. Add dot dot slash then Data.html, since GoogleAuthentication.js is inside the Scripts folder. window.location.href = "../Data.html"

      Delete
  19. Very good article. Is is possible to have source code. Thanks.

    ReplyDelete
  20. Hi, I am getting error when i tried to login using my google account:

    Request URL: http://localhost:56244/api/Account/RegisterExternal
    Request method: POST
    Status code: 401 Unauthorized

    all steps have been followed and successful, however only to this external register i have some issue.

    ReplyDelete
  21. Dear Sir,

    I have a web project of college.

    In that project admission page have control for webcam capture, but I can't understand that how to do it ?
    its https based project.
    Please Help me ...............

    Thanks in advance.................

    ReplyDelete
  22. Why you have not connected to database using Web API methods like GET POST PUT DELETE ?

    ReplyDelete
  23. Sir i got it but little confuse about database what the column required

    ReplyDelete
  24. after successfully login with google it redirects to againhttp://localhost:31281/api/Account/ExternalLogin?provider=Google&response_type=token&client_id=self&redirect_uri=http%3A%2F%2Flocalhost%3A57939%2FIndex&state=mQW70cU53GokGJSolk6BqmXK6_vYYDdidLUW-3X1VCs1#

    ReplyDelete
  25. I did't understand database section.Where is the database is creating or storing.

    ReplyDelete
    Replies
    1. Database is in application itself. Once you will execute the application and try to login then you can see the values in db.
      Please find the db directory below:
      appDirectory>>App_data>>yourDB

      Delete
  26. If i deploy it online, it will create .mdf like file separatelly on app data folder??

    ReplyDelete
  27. Hi @kudvenkat
    Your videos are really good to learn things from scratch.
    I am facing a problem. After successful login with google account, I am not able to Load Employees on clicking the button in Data.html. After login with google, I got the details in both Users and UserLogin tables. On clicking Load Employees button, the error I am receiving is "GET http://localhost:9301/api/employee 401 (Unauthorized)". I checked this with simple login and it was working perfect. Can you please tell me what I am doing wrong?

    ReplyDelete
    Replies
    1. Hi kudvenkat,
      iam unabale redirect data.html after successfully login in login.html page , its generated to next token in same login.html page .How to slove this isssues, total application run successfully but when iam entiren in google authntication not redirect to data.html page

      Delete
  28. Hello,
    i have encountered a strange error im not quite sure how to solve. I get redirected to Facebook for the authentication but, as soon as i confirm it, i get a strange error at the uri part:'#error=access_denied'. I don't know if i have to update the split function for the token or is it a database problem? Please help, im very confused how to procced.

    ReplyDelete
  29. If any one is fetching issues for running this topic, you need to follow previous some videos.
    ----------------------------------------------------
    This tutorial of google authentication is working well in 'visual studio express 2015 for web'. Thanks Kudvenkat sir.
    Now, design of https://console.developers.google.com website has changed. But by using little guess & Kudvenkat sir's video on this topic, you will get understand that how to perform task on this website to register our application.

    ReplyDelete
  30. Hello,
    I have encountered a problem when I try to access the URL
    api/Account/ExternalLogins?returnUrl=%2F&generateState=true.
    it says something like
    "the resource you are looking for is either removed or doesn't exist"
    please help to resolve this issue. I can't seem to understand what is wrong...

    ReplyDelete
  31. Hello already enable Google+ API but still i get access_denied error

    ReplyDelete
  32. Hello Venkat & Team,

    After redirecting to Google and providing correct email/password, i am getting below error

    http://localhost:54321/#error=access_denied


    ..I verified Google+API is enabled , with that, i have also enabled Google Drive API and Gmail API ..but still no luck.

    ReplyDelete
  33. After successful login using google account it is redirected to UI end of the url #error=access_denied. Please let us know why is it happening like this

    ReplyDelete
  34. The solution for #error=access_denied is:
    1- Open (Tools) Tab
    2- Choose (NuGet Package Manager)
    3- Choose (Package Manager Console)
    4- Execute this command in Package Manager Console (Install-Package Microsoft.Owin.Security.Google -Version 2.1.0)

    Note:- The Solution taken from youtube comment by "Khaled Said "

    ReplyDelete
  35. I am getting "error=access_denied" in the browser url, while returning back from google sign-in process.

    I have Package Microsoft.Owin.Security.Google already installed in my machine

    ReplyDelete
  36. sir from where i can get the startup,auth,cs file..bcz without that file i canot greate googlr button

    ReplyDelete
  37. do i need to create account controller and externallogins OR just replace port number from url i get this that xml page please help ,me ???????

    ReplyDelete
  38. What should be there in ExternalLogin?

    ReplyDelete
  39. There is neither External Login Method nor Account Controller can you please share the AccountControllerFile.cs ?

    ReplyDelete
  40. I need seperate Front End MVC Solution that has google Login, and seperate multiple webapi project which need to be using same bearer token to authenticate. can i have any sample example working solution?. the front end can be extended to mobile apps also in future.

    ReplyDelete
  41. but how you configure sql server , how tables created. so many confusions.

    ReplyDelete
  42. I am getting "#error=access_denied" in the URL. I have got the Package Microsoft.Owin.Security.Google already installed but updated with the latest release. Still having the issue. Please help.

    ReplyDelete
  43. when I Fire this request "api/Account/ExternalLogins?returnUrl=%2F&generateState=true"
    its say "No HTTP resource was found that matches the request URI 'http://localhost:9050/api/Account/ExternalLogins?returnUrl=%2F&generateState=true'."

    Please suggest as so many comments having same issue.

    ReplyDelete

It would be great if you can help share these free resources