Token Based Authentication using ASP.NET Web API 2, Owin, and Identity

Last week I was looking at the top viewed posts on my blog and I noticed that visitors are interested in the authentication part of ASP.NET Web API, CORS Support, and how to authenticate users in single page applications built with AngularJS using token based approach.

So I decided to compile mini tutorial of three five posts which covers and connects those topics. In this tutorial we’ll build SPA using AngularJS for the front-end, and ASP.NET Web API 2, Owin middleware, and ASP.NET Identity for the back-end.


The demo application can be accessed on (http://ngAuthenticationWeb.azurewebsites.net). The back-end API can be accessed on (http://ngAuthenticationAPI.azurewebsites.net/) and both are hosted on Microsoft Azure, for learning purposes feel free to integrate and play with the back-end API with your front-end application. The API supports CORS and accepts HTTP calls from any origin. You can check the source code for this tutorial on Github.

AngularJS Authentication

 

Token Based Authentication

As I stated before we’ll use token based approach to implement authentication between the front-end application and the back-end API, as we all know the common and old way to implement authentication is the cookie-based approach were the cookie is sent with each request from the client to the server, and on the server it is used to identify the authenticated user.

With the evolution of front-end frameworks and the huge change on how we build web applications nowadays the preferred approach to authenticate users is to use signed token as this token sent to the server with each request, some of the benefits for using this approach are:

  • Scalability of Servers: The token sent to the server is self contained which holds all the user information needed for authentication, so adding more servers to your web farm is an easy task, there is no dependent on shared session stores.
  • Loosely Coupling: Your front-end application is not coupled with specific authentication mechanism, the token is generated from the server and your API is built in a way to understand this token and do the authentication.
  • Mobile Friendly: Cookies and browsers like each other, but storing cookies on native platforms (Android, iOS, Windows Phone) is not a trivial task, having standard way to authenticate users will simplify our life if we decided to consume the back-end API from native applications.

What we’ll build in this tutorial?

The front-end SPA will be built using HTML5, AngularJS, and Twitter Bootstrap. The back-end server will be built using ASP.NET Web API 2 on top of Owin middleware not directly on top of ASP.NET; the reason for doing so that we’ll configure the server to issue OAuth bearer token authentication using Owin middleware too, so setting up everything on the same pipeline is better approach. In addition to this we’ll use ASP.NET Identity system which is built on top of Owin middleware and we’ll use it to register new users and validate their credentials before generating the tokens.

As I mentioned before our back-end API should accept request coming from any origin, not only our front-end, so we’ll be enabling CORS (Cross Origin Resource Sharing) in Web API as well for the OAuth bearer token provider.

Use cases which will be covered in this application:

  • Allow users to signup (register) by providing username and password then store credentials in secure medium.
  • Prevent anonymous users from viewing secured data or secured pages (views).
  • Once the user is logged in successfully, the system should not ask for credentials or re-authentication for the next 24 hours 30 minutes because we are using refresh tokens.

So in this post we’ll cover step by step how to build the back-end API, and on the next post we’ll cover how we’ll build and integrate the SPA with the API.

Enough theories let’s get our hands dirty and start implementing the API!

Building the Back-End API

Step 1: Creating the Web API Project

In this tutorial I’m using Visual Studio 2013 and .Net framework 4.5, you can follow along using Visual Studio 2012 but you need to install Web Tools 2013.1 for VS 2012 by visiting this link.

Now create an empty solution and name it “AngularJSAuthentication” then add new ASP.NET Web application named “AngularJSAuthentication.API”, the selected template for project will be as the image below. Notice that the authentication is set to “No Authentication” taking into consideration that we’ll add this manually.

Web API Project Template

Step 2: Installing the needed NuGet Packages:

Now we need to install the NuGet packages which are needed to setup our Owin server and configure ASP.NET Web API to be hosted within an Owin server, so open NuGet Package Manger Console and type the below:

The  package “Microsoft.Owin.Host.SystemWeb” is used to enable our Owin server to run our API on IIS using ASP.NET request pipeline as eventually we’ll host this API on Microsoft Azure Websites which uses IIS.

Step 3: Add Owin “Startup” Class

Right click on your project then add new class named “Startup”. We’ll visit this class many times and modify it, for now it will contain the code below:

What we’ve implemented above is simple, this class will be fired once our server starts, notice the “assembly” attribute which states which class to fire on start-up. The “Configuration” method accepts parameter of type “IAppBuilder” this parameter will be supplied by the host at run-time. This “app” parameter is an interface which will be used to compose the application for our Owin server.

The “HttpConfiguration” object is used to configure API routes, so we’ll pass this object to method “Register” in “WebApiConfig” class.

Lastly, we’ll pass the “config” object to the extension method “UseWebApi” which will be responsible to wire up ASP.NET Web API to our Owin server pipeline.

Usually the class “WebApiConfig” exists with the templates we’ve selected, if it doesn’t exist then add it under the folder “App_Start”. Below is the code inside it:

Step 4: Delete Global.asax Class

No need to use this class and fire up the Application_Start event after we’ve configured our “Startup” class so feel free to delete it.

Step 5: Add the ASP.NET Identity System

After we’ve configured the Web API, it is time to add the needed NuGet packages to add support for registering and validating user credentials, so open package manager console and add the below NuGet packages:

The first package will add support for ASP.NET Identity Owin, and the second package will add support for using ASP.NET Identity with Entity Framework so we can save users to SQL Server database.

Now we need to add Database context class which will be responsible to communicate with our database, so add new class and name it “AuthContext” then paste the code snippet below:

As you can see this class inherits from “IdentityDbContext” class, you can think about this class as special version of the traditional “DbContext” Class, it will provide all of the Entity Framework code-first mapping and DbSet properties needed to manage the identity tables in SQL Server. You can read more about this class on Scott Allen Blog.

Now we want to add “UserModel” which contains the properties needed to be sent once we register a user, this model is POCO class with some data annotations attributes used for the sake of validating the registration payload request. So under “Models” folder add new class named “UserModel” and paste the code below:

Now we need to add new connection string named “AuthContext” in our Web.Config class, so open you web.config and add the below section:

Step 6: Add Repository class to support ASP.NET Identity System

Now we want to implement two methods needed in our application which they are: “RegisterUser” and “FindUser”, so add new class named “AuthRepository” and paste the code snippet below:

What we’ve implemented above is the following: we are depending on the “UserManager” that provides the domain logic for working with user information. The “UserManager” knows when to hash a password, how and when to validate a user, and how to manage claims. You can read more about ASP.NET Identity System.

Step 7: Add our “Account” Controller

Now it is the time to add our first Web API controller which will be used to register new users, so under file “Controllers” add Empty Web API 2 Controller named “AccountController” and paste the code below:

By looking at the “Register” method you will notice that we’ve configured the endpoint for this method to be “/api/account/register” so any user wants to register into our system must issue HTTP POST request to this URI and the pay load for this request will contain the JSON object as below:

Now you can run your application and issue HTTP POST request to your local URI: “http://localhost:port/api/account/register” or you can try the published API using this end point: http://ngauthenticationapi.azurewebsites.net/api/account/register if all went fine you will receive HTTP status code 200 and the database specified in connection string will be created automatically and the user will be inserted into table “dbo.AspNetUsers”.

Note: It is very important to send this POST request over HTTPS so the sensitive information get encrypted between the client and the server.

The “GetErrorResult” method is just a helper method which is used to validate the “UserModel” and return the correct HTTP status code if the input data is invalid.

Step 8: Add Secured Orders Controller

Now we want to add another controller to serve our Orders, we’ll assume that this controller will return orders only for Authenticated users, to keep things simple we’ll return static data. So add new controller named “OrdersController” under “Controllers” folder and paste the code below:

Notice how we added the “Authorize” attribute on the method “Get” so if you tried to issue HTTP GET request to the end point “http://localhost:port/api/orders” you will receive HTTP status code 401 unauthorized because the request you send till this moment doesn’t contain valid authorization header. You can check this using this end point: http://ngauthenticationapi.azurewebsites.net/api/orders

Step 9: Add support for OAuth Bearer Tokens Generation

Till this moment we didn’t configure our API to use OAuth authentication workflow, to do so open package manager console and install the following NuGet package:

After you install this package open file “Startup” again and call the new method named “ConfigureOAuth” as the first line inside the method “Configuration”, the implemntation for this method as below:

Here we’ve created new instance from class “OAuthAuthorizationServerOptions” and set its option as the below:

  • The path for generating tokens will be as :”http://localhost:port/token”. We’ll see how we will issue HTTP POST request to generate token in the next steps.
  • We’ve specified the expiry for token to be 24 hours, so if the user tried to use the same token for authentication after 24 hours from the issue time, his request will be rejected and HTTP status code 401 is returned.
  • We’ve specified the implementation on how to validate the credentials for users asking for tokens in custom class named “SimpleAuthorizationServerProvider”.

Now we passed this options to the extension method “UseOAuthAuthorizationServer” so we’ll add the authentication middleware to the pipeline.

Step 10: Implement the “SimpleAuthorizationServerProvider” class

Add new folder named “Providers” then add new class named “SimpleAuthorizationServerProvider”, paste the code snippet below:

As you notice this class inherits from class “OAuthAuthorizationServerProvider”, we’ve overridden two methods “ValidateClientAuthentication” and “GrantResourceOwnerCredentials”. The first method is responsible for validating the “Client”, in our case we have only one client so we’ll always return that its validated successfully.

The second method “GrantResourceOwnerCredentials” is responsible to validate the username and password sent to the authorization server’s token endpoint, so we’ll use the “AuthRepository” class we created earlier and call the method “FindUser” to check if the username and password are valid.

If the credentials are valid we’ll create “ClaimsIdentity” class and pass the authentication type to it, in our case “bearer token”, then we’ll add two claims (“sub”,”role”) and those will be included in the signed token. You can add different claims here but the token size will increase for sure.

Now generating the token happens behind the scenes when we call “context.Validated(identity)”.

To allow CORS on the token middleware provider we need to add the header “Access-Control-Allow-Origin” to Owin context, if you forget this, generating the token will fail when you try to call it from your browser. Not that this allows CORS for token middleware provider not for ASP.NET Web API which we’ll add on the next step.

Step 11: Allow CORS for ASP.NET Web API

First of all we need to install the following NuGet package manger, so open package manager console and type:

Now open class “Startup” again and add the highlighted line of code (line 8) to the method “Configuration” as the below:

Step 12: Testing the Back-end API

Assuming that you registered the username “Taiseer” with password “SuperPass” in the step below, we’ll use the same username to generate token, so to test this out open your favorite REST client application in order to issue HTTP requests to generate token for user “Taiseer”. For me I’ll be using PostMan.

Now we’ll issue a POST request to the endpoint http://ngauthenticationapi.azurewebsites.net/token the request will be as the image below:

OAuth Token Request

Notice that the content-type and payload type is “x-www-form-urlencoded” so the payload body will be on form (grant_type=password&username=”Taiseer”&password=”SuperPass”). If all is correct you’ll notice that we’ve received signed token on the response.

As well the “grant_type” Indicates the type of grant being presented in exchange for an access token, in our case it is password.

Now we want to use this token to request the secure data using the end point http://ngauthenticationapi.azurewebsites.net/api/orders so we’ll issue GET request to the end point and will pass the bearer token in the Authorization header, so for any secure end point we’ve to pass this bearer token along with each request to authenticate the user.

Note: that we are not transferring the username/password as the case of Basic authentication.

The GET request will be as the image below:

Token Get Secure Resource

If all is correct we’ll receive HTTP status 200 along with the secured data in the response body, if you try to change any character with signed token you directly receive HTTP status code 401 unauthorized.

Now our back-end API is ready to be consumed from any front end application or native mobile app.

Update (2014-08-11) Thanks for Attila Hajdrik for forking my repo and updating it to use MongoDb instead of Entity Framework, you can check it here.

You can check the demo application, play with the back-end API for learning purposes (http://ngauthenticationapi.azurewebsites.net), and check the source code on Github.

Follow me on Twitter @tjoudeh

References

Comments

  1. says

    no ‘access-control-allow-origin’ header is present on the requested resource.

    I tried this in IE as well and I still get this error. Please help!! I am running the site under iis express

  2. says

    This is a great article… good job!.. I’m not an expert in web security right now I’m looking for a sample about secure web api but try to access the services from an MVC app I don’t know how to store the token at the MVC app when the user gets Login success. Will you mind to give me some example about it? I’ll appreciate any help about…

    Best regards.
    Angel

  3. Rami Yam says

    Thank you. This is a very helpful tutorial. I have one question and will really appreciate if you can answer: After the log-in process, when user got the token and now calling the get-orders service. What is the right way to implement “profile”, I mean to return orders that related to the user that calls the service.? I have to recognize somehow, who is the user and not just to know that he is authorized to call the service.
    Thanks again.
    Rami

      • Rami Yam says

        Thanks, it was helpful and worked simply with adding claims. Is the added data to the claim encrypted into the token and then decrypted on the server when the server checks the token? and also is the added claim signed?
        If you know good source to read more about that, I will be happy to read. Thanks again!

        • says

          Hi Rami,
          Yes if you are using the default token protection implementation then it is signed and encrypted.
          Could you please drop me an email showing how did you implement claims authentication?
          Did you use your own Authorization Filter? I’m researching this area and there is different ways to do it, so I would like to see your implementation if you can share it.

          • Rami Yam says

            Thank you Taiseer fro replay.
            Currently I am learning the subject and your solution in this article and in the one with Facebook authentication are a very good start for me. So now I have no my own implementation yet. I think I will be ready to start in two weeks as I still need to cover material to have the full picture (and I’m doing it on my free time which is usually weekends). I will share later, when I have prototype that I will use.

          • Lance Comtreras says

            Hi,

            I have tried a way to authenticate based on claims. I’m not sure if it should really be this way, but it works for me. I extended the AuthorizeAttribute and Created ClaimsAuthorize(I copied the name from a thinktecture).

            public class ClaimsAuthorizeAttribute : AuthorizeAttribute
            {
            string value;
            string type;
            public ClaimsAuthorizeAttribute(string type, string value)
            {
            this.type = type;
            this.value = value;
            }
            protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext)
            {
            var ci = actionContext.RequestContext.Principal.Identity as ClaimsIdentity;
            var x = (from i in ci.Claims
            where i.Type == type && i.Value == value
            select i).Count();

            return x > 0;
            //return base.IsAuthorized(actionContext);
            }
            }

            Then in my controller, you can add as much claimsauthorize attribute as you want.

            [Authorize]
            [ClaimsAuthorize(“role”, “user”)]
            public IEnumerable Get()
            {
            var claim = HttpContext.Current.User.Identity;
            return new string[] { “value1″, “value2″ };
            }

            Now if you removed the claim “role: user” from the GrantResourceOwnerCredentials method. It will not be authorized.

          • says

            Thanks Lance for sharing this, I’m working on something similar now and its almost like your case, I’ll share it soon in the coming blog posts, claims authentication is little bit tricky.

  4. Sam says

    Hi Taiseer,

    Fisrtly, I would like to thank you very much for this post, it is great. Saved me a lot of time building that from scratch by myself.

    Just wanted to correct you on one thing. In the SimpleAuthorizationServerProvider, I believe that the first method is where the _repo.FindUser() should be placed and you should take the user name and password from the context.Parameters[“username”] and context.Parameters[“password”]. The if the user is not found, you set the context error and call context.Rejected(), and in case of a valid user, you call context.validated().

    Then the second method SimpleAuthorizationServerProvider gets invoked and you know it this point you have already been validate and just create the Identity and its claim and generate the oAuth token.

    All in all, I am learning a lot from your posts, keep up the good work mate :).

    Cheers,
    Sam

    • says

      Hi Sam,
      The first method “ValidateClientAuthentication” should only validate the client_id and client_secret, you should not validate the resource owner credentials here (User credentials). You should do this validation in the second method.
      So each method exists for a reason here. Hope this makes sense.

  5. Rick Butler says

    Great article Taiseer!

    The only issue I had was with the NuGet packages. Some of them have become a bit out dated it seems. I basically upgraded to the latest versions of the packages and worked through the dependency issues to get my solution working. Aside from that it worked well.

    –Rick

    • says

      Thanks Rick for your post, but I’m sitting the version for each NuGet package installed so if you used the same version in the post for all packages then it should work fine, anyhow upgrading to latest version of each package is preferred, thanks again.

  6. says

    Was implementing this into my existing application and getting 401 for all calls even though I was getting the token and sending it in header. Turns out you MUST put the lines in Startup.cs in correct order.

    app.UseOAuthAuthorizationServer(OAuthServerOptions);
    app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

    MUST go above

    WebApiConfig.Register(config);
    app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
    app.UseWebApi(config);

    Hopefully this will save someone else a few hours of stress ;) Thanks for the great tutorial.

  7. Jerry T says

    Please add a new section on Ninject with OWIN. I spent a lot of my Saturday trying to get DI working with this code and then I found out that OWIN has a completely different way of working with Ninject and there is very little info on the web about it. Some So posts and some minor blog posts, but no walk-throughs and it’s very challenging so far. It would make a fantastic addition to this series (and save others from wasting their Saturdays on it.) :-)

  8. says

    Hi Taiseer,
    Thanks a lot for wonderful posts explaining the complexity of web api security in so simple language.
    Learnt a lot from your posts.
    I am wondering where and how does the validation of token happens? i am preparing a sequence diagram of the authentication process which i have built by understanding your posts. So you answer will greatly help me.

    Thank you in advance.

    Regards, Naveen.

    • says

      Hi Naveen,
      The validation for the access token happens inside the implementation of the [Authorize] attribute, because you have configured your API at the “Starup” calls to be protected using OAuth tokens as this line: ” app.UseOAuthBearerAuthentication(OAuthBearerOptions);”. I recommend you to check this post where I cover more details on how the validation for the access token happens.
      Hope this help.

  9. nemos says

    I’ve tried to implement blog version of your code, and when I run it and use debugger on Startup class methods in API part, they never get invoked even thou there is a OwinStartup setup there. For that reason when I try to generate token using localhost: port/token I get 404 not found. Does anyone have an idea what can be possible wrong and is there any other settings beside the ones shown in tutorial to do?

    • says

      Hmm make sure you have installed the package “Microsoft.Owin.Host.SystemWeb” and you attributed the “Startup” class by “[assembly: OwinStartup(typeof(AngularJSAuthentication.API.Startup))]”, that is only the thing passes my mind right now.

  10. Samoji says

    Thank you Taiseer Joudah for this article, it’s awesome!
    I have a question: is it possible to modify the token endpoint response body? I know that you can add additional parameters but I really need to remove some “default” informations.

  11. Elie says

    Started looking into AngularJS and in particular authentication and securing user data. This is a great writeup in all its parts and very helpful.

    Wanted to ask regarding securing user data (login information, and even user profile data) what is the best approach to send/receive data from the AngularJS application and the back-end

  12. Lance Comtreras says

    Hi, How did you manage to deploy this in Azure. I am always getting an error when running the deployed app. I think there’s an issue with deploying self hosted aplication to azure or there’s a right way of doing that.

  13. Luke says

    Hi Taiseer,

    Thanks for your posts on these topics, they have been a big help to me :D

    I was wondering if you would take a look at a question I have raised on stack overflow.. I built my app largely following the approach in your posts and I am having a problem with claims that I cant work out..

    http://stackoverflow.com/questions/28734523/asp-identity-2-web-api-token-auth-persistent-claims-not-loading

    any help you could give would be much appreciated..

    Thanks

    _L

    • jirikavi says

      Hi Luke and Taiseer,

      I am also having a problem with getting persistent claims but only when a user is authenticated via external provider.
      During a registration of user I stored additional data (filled by user on association page) as claims to AspNetUserClaims.
      Then I tried to set up a new cookie with stored claims (after registration or when user logs in via an external provider again)
      because I found a comment on SO (http://stackoverflow.com/a/25311865/4613695):

      “No, you can’t change the claims in the cookie without sign-in/sign-out. But you can add claims to user record and these will be available in the cookie on the next sign-in.”

      but again the claims was not listed among claims when I tried to get them (only Name and Role claims exists) in Orders controller:

      var claims = ((ClaimsIdentity)User.Identity).Claims.ToList()

      I can only get these claims from DB by calling DB query:
      var _repo = new AuthRepository();
      var user = await _repo.FindByNameAsync(User.Identity.Name);
      var claims = user.Claims.ToList();

      Can anybody help? Why also custom (persistent) claims are not listed there?
      Thanks in advance.
      Jiri.

  14. Bas says

    Hey Taiseer,

    I made a quick console application to communicate with your server to register a user, retrieve an access token and use that token to retrieve the order list. However, I can’t seem to authenticate the token. Would you mind looking at this question on Stack Overflow?

    http://stackoverflow.com/questions/28855535/this-identity-bearer-token-is-not-being-recognized

    And thanks for maintaining this blog! It’s really useful, and maybe I’ll be MS MVP in the year 2020. :)

  15. Saurabh says

    Thank you Taiseer. Its great help to me in building Authentication for the web APIs. One quick question, can we implement similar to the page level, as with the current implementation, new page is getting displayed for 1-2 seconds, then it is redirecting to login page?

  16. says

    this is really a great article, im new in learning the web api, and i was crazy for this authentication process,
    i did almost everything the same as u mentioned in ur tutorial, im trying this on localhost, may b thats the problem im getting this error on requesting api/Orders
    {
    “message”: “Authorization has been denied for this request.”
    }

    token is being retrieved and rest everything is fine,
    i dont know the reason except one and that is im testing it on localhost, with visual studio 2013 and iis built in with vs2013
    thanx,

    • says

      Hi Rehan, make sure you are setting the Authorization header correctly using the “Bearer” scheme, are you using Web API template or following the steps in the post exactly?

  17. says

    Great article! It really helped me get unstuck, and I have something to add that may help others. In my situation, I’m authenticating against a single-sign-on (SSO) cookie, transforming the external identity into a local identity and subsequently a bearer token. The authentication happens in a data service, and typically on an AJAX call, so I had to add ‘withCredentials: true’ to the AJAX call so that the SSO cookie would transmit to the server. Setting the “Access-Control-Allow-Origin” header was the critical missing piece for me, but because the call is “with credentials”, I had to also set “Access-Control-Allow-Credentials” header to “true”. And because this header is set to true, “Access-Control-Allow-Origin” cannot be set to “*” (a runtime exception told me this), so I’m setting it to the value of the “Origin” request header. So, my code to set these headers looks like this:

    var origin = context.Request.Headers.Get(CorsConstants.Origin);
    context.OwinContext.Response.Headers.Add(CorsConstants.AccessControlAllowOrigin, new[] { origin });
    context.OwinContext.Response.Headers.Add(CorsConstants.AccessControlAllowCredentials, new[] { “true” });

    And one last thing for those that may need to authenticate from an external provider. Because I’m using an external provider, the call to /Token endpoint posts with a custom “grant_type” value specific to the provider (i.e. grant_type=NetCrowd), and is processed in an override of OAuthAuthorizationServerProvider.GrantCustomExtension rather than GrantResourceOwnerCredentials in the example. Descriptions of the “Grant…” methods in the documentation were very helpful in figuring this out.

    https://msdn.microsoft.com/en-us/library/microsoft.owin.security.oauth.oauthauthorizationserverprovider(v=vs.113).aspx

    Many thanks, to Taiseer and others who have helped me to solve these problems. Namaste!

    • says

      Update: Apparently some browsers do not send an “Origin” header, so adjust accordingly.

      // Set CORS headers
      if (context.Request.Headers.ContainsKey(CorsConstants.Origin))
      {
      // Some browsers (e.g. IE11) don’t send ‘Origin’ header
      var origin = context.Request.Headers.Get(CorsConstants.Origin);
      context.OwinContext.Response.Headers.Add(CorsConstants.AccessControlAllowOrigin, new[] { origin });
      }
      context.OwinContext.Response.Headers.Add(CorsConstants.AccessControlAllowCredentials, new[] { “true” });

  18. Mantua says

    First I got error The requested resource does not support http method ‘GET’. on http://localhost:26264/api/Account/Register,
    Then I added [AcceptVerbs(“GET”, “POST”)].I am getting error The request contains an entity body but no Content-Type header. The inferred media type ‘application/octet-stream’ is not supported for this resource.
    Please help as I am new to webapi,owin

  19. Shrikant says

    I am integrating it on my project but not going to intagrate, there is rooting problem and js files are not going to work any more.

  20. says

    Fantastic article, this is an amazing help to my company and myself (now just to figure out the Android native side of this xD). I just want to ask, how secure is sending usernames and passwords in plain text even over HTTPS?

    • says

      Hi Michael,
      When you use HTTPS you are not sending username/password in plain text, they will be encrypted over the wire, so seeing them on the client doesn’t mean they are going to be sent in plain text if you are using HTTPS, it is the same case for every login page you type username and password in.

  21. Jeroen Vannevel says

    Hey Taiseer

    For some reason I’m receiving an “invalid_grant” error when trying to retrieve the access token, even though the username and password are the same and the user is inserted for sure. When I put a breakpoint at if(user == null) I can see that the object has the correct values and the if-block is skipped. However as soon as it reaches the end of the GrantResourceOwnerCredentials() method, the request is done and I receive beforementioned HTTP 400 response.

    Do you have any idea of what might cause this?

    • says

      Hi Jeroen,
      Did you download/forked the GitHub sample project or you started this from scratch? I recommend to download the repo and test it out, if all is good you start moving small pieces of the code to your repo.
      As well make sure you are using the same NuGet packages version I’m using, I’m not sure if this will be an issue as I have used version 3.0.0 in another projects with no issues but I’m trying to minimize the differences between the code in the sample and your code.
      Check this comment which might be useful to your case.

  22. says

    Hi again, thanks for your response to my first question, I’m now having trouble hosting this on IIS 7.5 on windows server 2008. Keep getting a “HTTP Error 403.14 – Forbidden” error with the “DirectoryListingModule”. I have checked that the correct version of asp.net is registered with IIS and it is certainly running in integrated pipeline mode. I have deployed MVC5 apps to this server but for some reason this OWIN middleware app is giving me trouble. Is there anything else I need to add to web.config to get this thing to run?

  23. says

    I was able to get my API to work locally without CORS using Google REST Console. I originally tried using Postman but it didn’t allow me to provide a username and password but with Google REST console I was given a popup to enter my username and password.

  24. Paolo says

    In the Register() method of the AccountController, when everything passes through, shouldn’t it return Created() instead of Ok() since you’re essentially adding a new record?

    Was there a reason for just returning Ok(), or was it just for convenience?

      • Paolo says

        Thanks for the clarification, Taiseer. Yes I will study the code in your other repo. It’s a great help!

        One other question: How did you ensure that Register() only accepted POST and not GET or any other HTTP verb? Is there some convention that that automatically assumes that any method in a controller named Register() is assumed to be a POST?

        • says

          Hi Paolo,
          Well there is convention in Web API, it understands it is POST method because I’m sending a CLR object (UserModel) as a parameter of the method. You can attribute it with [HttpPost] attribute too.

  25. says

    Hi,
    Thanks for the great post.
    If Imay,I have a question about using the ASP.NET Identity.
    Can I use something else instead of the ASP.NET Identity?

  26. Camilla Kaasi says

    Hi and thank you for this great tutorial!

    I am building a web application with this tutorial and I have been trying to implement functionality for changing a users password. As I am struggling a bit I was wondering if you had any tips for how to do this?

    Any help would be much appreciated!

  27. says

    Man I have just followed your steps for authentication of facebook and google and it helped me a lot. But I am trying to Use twitter authentication but its a bit difficult for me. have you tried it, If soc then can you help me for twitter base authentication.
    Thanks

  28. Devon says

    To be clear the Post works OK and a token is returned. It’s when sending the get request with the bearer token returned from the POST request that the error occurs:

    GET /token?Accept=application/json&Content-Type=application/x-www-form-urlencoded&Authorization=Bearer mc0UaZiHM97ueb8xiEQqeZ5oCwMnF6ZoKgEHp0cd8ftSQ5MCAHkwo6HAcOPFQil3k7hjD-dB-tX5OHTzlmbP8ncHUU6ZMt8a1OYVGhv59AzN1f7YiaNydHPnIrjbI-U74aEtAyFrmghtK0_JjIvBBGM3kxYW1hVFP_BDhljFA33LVhEfzqQFxGJIobIv0C6gHfoqeXjW9g857BUSA1xjk24PmaQK9KFORugmK6Jx68s HTTP/1.1
    Host: localhost:35075
    Content-Type: application/json
    Cache-Control: no-cache
    Content-Type: application/x-www-form-urlencoded

  29. says

    Hi Devon, you do not need to send Get request to /token endpoint again, you need to send it to the secured endpoint which is “/orders” and set the token. As well the content type should be application/json when sending this request. Hope this answers your question.

  30. Devon says

    Finally noticed I forgot to change my url on the get. Silly mistake. Also had accidentally left the URL params tab click in postman rather than Headers. Trying to work too quickly as the end of the day neared.

  31. Hemant says

    You Saved My Life man…….Worked Like Charm………On My Production ……….Building something for NGO will surely put link to your blog …..

    Thanks Taiseer…..Really Nice Blog

  32. Tom says

    Hi Taiseer,
    I’m getting “unsupported_grant_type”, but what do you mean with “Build the request like this https://www.getpostman.com/collections/1ff438e088efac658be8

    I have this request:

    POST http://localhost:53701/token HTTP/1.1
    User-Agent: Fiddler
    Host: localhost:53701
    Content-Length: 248
    Accept: application/json
    Content-Type: application/x-www-form-urlencoded

    [
    {
    “key”: “username”,
    “value”: “Test”,
    “type”: “text”
    },
    {
    “key”: “password”,
    “value”: “MyPass”,
    “type”: “text”
    },
    {
    “key”: “grant_type”,
    “value”: “password”,
    “type”: “text”
    }
    ]

  33. Jiten says

    Hey Taiseer ! Need your help.

    I need to invoke /Token endpoint from OAuth service itself and generate access token and refresh token explicit once your change his password and pass tokens to client. I don’t want user to login again.

    Thanks,
    Jiten

  34. Aibol says

    Dear Taiseer,

    I faced the following problem:

    XMLHttpRequest cannot load http://localhost:57606/token. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://localhost:32153′ is therefore not allowed access.

    The problem occurs in Chrome browser. In IE it’s ok. Don’t you know what the problem could be?

  35. says

    Hi Aibol,
    I believe you need to set the client allowed origin column to match your host i.e. “http://localhost:57606″, CORS is not configured correctly in your case. Check this post on how to do it.
    IE doesn’t consider the port in URI as different URI that’s why it is working correctly because it only checks the host-name “localhost”, Chrome, Firefox take care of the port as well.

  36. says

    Hi Jiten,
    With the current implementation you can’t do this, what you can do is to use refresh tokens and once the user change his password you delete his refresh token. So when the client application wants to use this refresh token to obtain new access token it will receive 401 and you need to re-authenticate him by providing username and his new password.

  37. Aibol says

    Thank you Taiseer. Yes, you’re correct! The problem was in not configured CORS, e.g. there weren’t any rows in Client table.

    Unfortunately, I faced another problem when FindClient method is invoked:

    An exception of type ‘System.Data.Entity.Core.ProviderIncompatibleException’ occurred in EntityFramework.dll but was not handled in user code

    Additional information: An error occurred accessing the database. This usually means that the connection to the database failed. Check that the connection string is correct and that the appropriate DbContext constructor is being used to specify it or find it in the application’s config file. See http://go.microsoft.com/fwlink/?LinkId=386386 for information on DbContext and connections. See the inner exception for details of the failure.

    Could you also to clarify what is the difference between the RefreshTokenLifeTime which is saved in Client table and AccessTokenExpireTimeSpan = TimeSpan.FromMinutes(30) in Startup.cs?

  38. says

    Hi Aibol, I’ve covered the difference in the post, but the AccessTokenExpireTimeSpan is used to determine the life time for the local access token, the RefreshTokenLifeTime is used to determine the validity for refresh toke, usually this value is big (1 month, 2 weeks). Once this value expires user needs to re-authenticate again be providing credentials.

  39. Jerry T says

    I ran into this problem as well and used PostMan (a Chrome app) to send the JSON string to the url as a Post request and now it works. Caused me a bit of frustration till I realized this. Maybe you can add it to the blog post where you tell people to test the url so it’s right next to the proper step? :-)

    And thanks for all the work done with these blog posts. I really need this info and it looks like this will be perfect for a new project I have to start.

  40. says

    That is strange, it should be working correctly.
    This is how my request look like:

    POST /token HTTP/1.1
    Host: ngauthenticationapi.azurewebsites.net
    Accept: application/json
    Content-Type: application/x-www-form-urlencoded
    Cache-Control: no-cache
    Postman-Token: 3fc06f29-8f4f-54ed-10c2-3f3045dc8dfa

    username=Taiseer&password=SuperPass&grant_type=password

  41. Tom says

    Hi all,
    I have solved my problem whit “unsupported_grant_type” using this request:

    POST http://localhost:53701/token HTTP/1.1
    User-Agent: Fiddler
    Accept: application/json
    Content-Type: application/x-www-form-urlencoded
    Host: localhost:53701
    Content-Length: 51

    grant_type=password&username=myuser&password=mypsw

Trackbacks

Leave a Reply