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

    This is the best tutorial/walktrough on Identity and OWIN stuff I’ve seen to date :)
    Thank you very much as this finally got me to really understand it.

    Moving on to part 2 :)

  2. Kenny says

    Very informative post! One of the best post series i’ve read in a while.
    I’m following this approach for my application and have a question.
    Assume the following workflow
    1) User logs in with the correct credentials
    2) A token is issued
    3) User gets redirected to the orders page
    4) User issues a post to the OrdersController

    My question is: is there a way to know who the user is without passing the “user” every time?

    Many thanks!

    • says

      Hi Kenny, happy to hear this :)
      Well I didn’t get your question exactly, but you should not send the UserName with every request, the user can be encoded within the token it self, so in method “GrantResourceOwnerCredentials” you need to add the logged in user as a claim by adding this line code: identity.AddClaim(New Claim(ClaimTypes.Name, context.UserName));
      Then when you issue any HTTP request along with valid token, you can access the UserName in any controller using this line of code: User.Identity.Name
      Hope this answers your question.

      • says

        Taiseer,
        Thanks for this wonderful post.

        Since i needed it to work without the Identity system, I have skipped the AuthRepository + AccountController and for now, in GrantResourceOwnerCredentials method, i harcoded a set of credentials to validate against. Works fine and i can authorize an API endpoint.

        Now, i add a claim by name “role” with value, “admin”.
        Now on the Api front, using User.Identity, i can get ‘Name, isAuthenticated, and AuthenticationTye. How do i read up my role from the token? (Almost everywhere i read, its being again asked from underlying membership system.)

        Thanks,
        Anupam

  3. Mark Vincze says

    Thanks for the great post.

    I would like to ask a question about OAuth tokens. You write:

    “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.”

    How is that implemented? What data does a token contain that can be used to properly authenticate a user? Does it contain the username and the password itself, or only a hash of the password? How is that verified with the password hash stored in the database?

    • says

      You are welcome Mark,
      I recommend you to read the complete series and the comments section as well as I’ve answered this question before, but as a short answer the access token has claims inside it (information about the user) and the password should not be included as a claim. The access token is encrypted and signed using the machineKey node in machine.config file, so only the server issued the access token can decrypt it. The access token can expires and it can’t be revoked and you only generate the access token after you do your Database checks and make sure that username/password combination are valid.
      Hope this answers your question and please look at the comments as there more details about this.

  4. says

    Hello Taiseer,
    Excellent post and great information..
    I have a question

    I am following this to implement OAUTH and API but will be hosting it as separate web application. I am trying to validate the token and get the claim details in API but I cant get to either validate or get the claim data inside controller class . I used User.Identity.Name present in claimPrincipal but no luck.

    1. Does the API and token generation process has to be in single project ?
    2. The claimPrincipal is returning information if the controller is in the same project( where the token generation implementation)

    thanks in advance

    • says

      Hi Aneesh,
      Are you hosting those on different IIS (different servers) or they are on the same server? If they are on the same server then there should be no issue as long as you do not override the “machineKey” in your web.config and your depending on “machineKey” value stored in machine.config file.

  5. says

    You have a good series of this article and this is supposedly solve my problem in deploying my data service through API and the AngularJS front-end.

    I have downloaded the source from git, and tried to open in different instance. I have created a WEB solution to hold the Web project and I have created an API solution to hold the API project. I executed both and works fine.

    However, when I tried to published the API project to IIS on 9090 port, I am getting an error:

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

    I hope you can help me to understand why I am getting this kind of error and to solve then.

    Thank you very much once again for this wonderful article.

    • says

      Hi Korr,glad it was useful.
      Please go on and read part three of this series where I introduce and implement clients concept, you will notice that you need to update the “AllowedOrigin” field in table “Clients” and set its value to ” http://localhost:9090“. The issue is happening on this LOC.
      Hope this answers your question.

      • says

        Hello Taiseer, I have tried every pieces of luck I have to solve the problem but to end up a dizzy Korr. Thank you for your time by the way.

        Well, I hope you can still help me to get through this. And I thank you in advance for this.

        Actually, as I have said, what I did was published the API project to IIS7.5 using the code from the GIT as is, this is using the Publish Web of VS 2013.

        And with the WEB project running at VS2013, below is the serviceBase I’ve used.

        //var serviceBase = ‘http://localhost:26264/’;
        var serviceBase = ‘http://localhost:9090/’;
        //var serviceBase = ‘http://ngauthenticationapi.azurewebsites.net/’;

        I ‘ve updated the said column AllowedOrigin in the table Clients

        But still I ended up getting the same error.

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

        Is this some thing to do with IIS version in any case ? Because, I noticed that when I run the project (which is using IIS8 Express), the API is in good reception. Just my own analysis, I don’t know if this matter.

        Once again, thank you very much for your time Taiseer.

        • Hemant says

          Hi Korr,
          Have you got any solution for this ?

          I’m facing same issue .

          When i ran WebAPI in one project & my App as another in VS it works like Charm…..As soon as i uploaded WebAPI on hosting site ….started giving this error..

          Really need to get it working ……

          • Hemant says

            Resolved My Issue by just Adding headers as below

            $http.
            post(
            serviceBase + ‘token’, data,
            {
            headers: { ‘Accept’: ‘application/json’, ‘Content-Type’: ‘application/json’ }
            }).
            success(function (response) {

            }

  6. Haitahm Shaddad says

    Wonderfull Post, thanks a lot for the great effort.

    i have one question

    you wrote:

    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.

    what do you mean by we have only one client? and why didn’t you validate the username and password in the ValidateClientAuthentication method? what is this method used for anyway?

    i would appreciate if you tell us the difference between the 2 methods

    Thanks again

    • says

      Hello Haitham, always happy to help.
      I recommend you to read part three to have clear understanding for the use of clients in OAuth world, but as short answer the client is not the resource owner (user) who will use the system or own the resource. The client is the piece of software that will interact with the back-end api, so you might build 2-3 clients (iOS app, Android app, Hybrid Mobile app, etc…) to consume this back-end api, and you might have 1000 users, as well the same user might use different clients on the same time. After you read part three you will understand all these concepts.
      Hope this answers your question.

  7. Raghav Kapoor says

    Thanks for the post. This is exactly what I was trying to understand. Just because its extremely clear, it is turning out to be very useful. Moving on to study next parts especially Refresh Tokens implementation.

  8. dluisbr says

    Hi,

    I am following your post and run as described in step 7 using the URI “http: // localhost: port / api / account / register” the bank is not created and the following error occurs:
    “The requested resource does not support http method ‘GET’.”
    could you help me solve this error?

    Tks

      • dluisbr says

        Hi, Taiseer.

        Excuse my ignorance, because I am following step by step the post, and I do not know how to do it, the URI “http //localhost:port/api/account/register” does not send the post? and also this time the tables Idenetity should not have already been created in the DB because they were not?

        Tks

  9. says

    Hi Taiseer

    Thanks for the wonderful post, I have successfully implemented your entire token solution in one of a live application and it is working like a charm. I have got just one query can you explain the right usage of Refresh Token. I mean I do understand the concept of Refresh token but at what point from the application shall I raise the request for request token,

    • says

      Hi,
      I’ve explained this in details in some of comments, so please check them. You need to raise the request for new access token using the refresh token before the expiry of the current access token or when you receive 401.

  10. says

    Hello, thanks for your tutorial.
    Can u give me a simple mvc 5 controller example to consume the API?. I don’t know angularJs, soo, i try to use the backend api with standar mvc5 webapp. Thanks.

  11. Mateusz says

    Hi,
    First of all, this is probably the best article about this issue I’ve read (and I’ve read a lot of them).
    Although implementing token based authentication worked in my case, getting current user in controller’s action is different aspect. If you have time, could you look on my problem, which I describe here (i get null from HttpContext.Current.User.Identity.Name) : http://stackoverflow.com/questions/26046441/current-user-in-owin-authentication

  12. says

    Hi there,

    Excellent tutorial! (Actually, all your tutorials are excellent).

    I have created a working API, and I’m essentially trying to create another MVC web app that will allow the user to login and obtain a token asynchronously via the API call. This would be similar to your AngularJS site in this tutorial, only in C#.

    When building my MVC login web app, I’m wondering how I could take the returned Bearer token (after a successful /token) call, and get the associated C# UserIdentity object with it. I would really like to have the controllers respect any [Authorize] directives to dictate user- or role-specific views. However, I’m lost at how to take the token thats returned from the /token API call and set any session cookies (or whatever needs to be set) to tell the MVC web app that the user has an active token.

    Any pointers?

    Brett

    • says

      Hi Brett,
      Glad you liked all the tutorials :)
      Well if I understand your scenario correctly then this post will help you to implement your solution. You just need to then about the Resource Server (Web API) as your MVC project. You will see how this Resource server understands the access token issue by Auth Server and respect the Authorize attribute, note that I’m only using bearer tokens and no cookies in my case.
      Let me know if you need further help.

  13. says

    Hey, I’m getting an error when trying to implement that into my project. {“error”:”unsupported_grant_type”}
    using Fiddler header:
    User-Agent: Fiddler
    Host: localhost:60906
    Content-Type: application/json; charset=utf-8
    Content-Length: 68
    Body:
    {“Password” : “123″, “email”:”john@doamin.co”, “grant_type”:”password”}

    • says

      Should be like the request below, your content-type is not correct

      POST /token HTTP/1.1
      Host: xxxxx.azurewebsites.net
      Accept: application/json
      Content-Type: application/x-www-form-urlencoded
      Cache-Control: no-cache
      username=xxxx&password=xxxx&grant_type=password

      • says

        Hi Taiseer,
        Thank you for your answer. Now, I have another issue I’m getting an error with key missing from the Dictionary.
        code:
        public async Task CreateAsync(AuthenticationTokenCreateContext context)
        {
        var userid = context.Ticket.Properties.Dictionary["as:client_id"]; //error here

        The error : “The given key was not present in the dictionary”
        I’m trying to set it exactly as your code suggests, using the AtuhenticationProperties under the GrantResourceOwnerCredentials method.
        But what the Dictionary contains is two rows one with .issued and other .expires properties, but nothing with “as:client_id”

        Your help please.

        • says

          Make sure you are including the “as:client_id” to the AuthenticationProperties class as the code below inside GrantResourseOwnerCredentials method
          var props = new AuthenticationProperties(new Dictionary
          {
          {
          “as:client_id”, (context.ClientId == null) ? string.Empty : context.ClientId
          },
          {
          “userName”, context.UserName
          }
          });

          var ticket = new AuthenticationTicket(identity, props);

          • says

            That’s exactly there, still same prob.

            var props = new AuthenticationProperties(new Dictionary
            {
            {
            “as:client_id”, (context.ClientId == null) ? string.Empty : user.UserId //context.ClientId
            },
            {
            “userName”, context.UserName
            }
            });

            var ticket = new AuthenticationTicket(identity, props);

          • says

            I was thinking to use OwinContext.Set instead and on CreateAsync just .Get
            e.g.
            context.OwinContext.Set(“as:client_id”, client.ClientId);

            Can that work?

            Thanks!

  14. Atul says

    Thank you Taiseer for such a great post.I am trying to follow the similar approach for one of our web api.I am able to do the bit where we generate the token but when i pass the same from fiddler i seem to be always getting http UnAuthorized code back.Below is what i am passing in the request header :

    http://localhost:34209/api/Orders
    Content-Type: application/json
    Host: localhost:34209
    Authorization: Bearer rPC8a5a0kle36F4M3heaSKMFOxfQK81aUrDqgULC4xMwm2H58HutH5OehrE8KXvfUp8eZk4AD8y6bpZVyL7KquIez51u85oLpxAz7KJLgDxAJTMH9Nr9lJyftlDhekqIS-QobSzSSPIAf0SeBTp7SYXxLswmN7ETne42IUDS-r4b536FCX2X1NUD2VCK9_M6pcOAl1ICdyFC7MwmwVUDe87j4pIcZiilINjvFRXTcJKxV4S-iUR63xYnjrzzU_yh

  15. says

    Hey Taiseer,
    Is it a good idea to make the repositories diposable? Because for each request to that controller, the repository and its underlying context also gets disposed. Is that good from performance point?

  16. Roger says

    This architecture was very easy to integrate with Phone Gap, the client application is completely separate from the server, thanks

  17. Arturo Hernandez says

    Hello, Taiseer.

    Thank you very much for your post. I do have a small problem. I still need to change the client_id, but it is replaced by xxxxxxx rather than ngAuthApp. This very odd to me. I see that the ChallengeResult class calls Request.GetOwinContext().Authentication.Challenge(LoginProvider); to generate a response. But I can’t see why the code is not taking the client_id in the original request.

    • says

      Hi Arturo,
      The value for client_id is always “xxxxxxx” or its empty? Make sure you are setting the key in request to “client_id” and you are encoding the request using “x-www-form-urlencoded”

      • Arturo Hernandez says

        Finally I did a seach by xxxxxx. And I found I needed to set my ClientId. It’s confusing that the client_id is set on the first URL. But is ignored by when creating the redirect.

        //Configure Google External Login
        googleAuthOptions = new GoogleOAuth2AuthenticationOptions()
        {
        ClientId = “xxxxxx”,
        ClientSecret = “xxxxxx”,
        Provider = new GoogleAuthProvider()
        };

  18. HDC says

    Can I have in the same application an MVC web site and a WebApi, and secure the WebApi using token based authentication and the web site cookies? Can I use both simultaneously? is it recommended? I did a proof of concept and so far it seems to work.

    • says

      Sure you can mix both, it is like the default template for MVC 5 which mixes the both, my recommendation is to split them if possible because it will be easier to manage and you know your API is protected by tokens and your MVC app by cookies.

      Who knows maybe in future your API grows and the number of clients (mobile apps, SPA) increases and you want it to have standalone API.

      • HDC says

        Thanks for responding so fast. By the way, this is the best tutorial not only for OWIN but in general that I have seen in a lot of time. If there was an OSCAR for tutorials you should get one. Every required step is clearly explained and actually works!

  19. Jeff says

    Thank you for the wonderful post this help me on understanding/starting on the token based authentication.

    I tried recreating your sample on my local machine minus Account Controller and Orders Controller because I only want to test the token generation, I host the web api on my local IIS and tried using Postman to generate a token but i am encountering a 404 error on http:/localhost/webapisecurity/token , is this because I did not implement the Controllers?

    Thank you for the help

    • says

      Hi jeff, glad it was useful,
      Well make sure that the property TokenEndpointPath = new PathString(“/token”)” is set to your correct token URI. I can see you have “webapisecurity” in URI. The controllers do not have affect on this.

  20. Austen says

    I enjoyed this tutorial, however I have a question that may seem basic. Sending request to this API, it must be x-www-form-urlencoded. Is there a way to change this so that it just accepts JSON?

    Thank you

  21. Joy says

    Hi Taiseer,

    What happens if we don’t delete the Global.asax.cs from the project as you mentioned in Step 4. Can’t we use Global.asax.cs along with Owin Startup class? Why should we delete Global.asax.cs? Can you please elaborate on this?

    Thanks!

    • says

      Hi Joy,
      What events you are using in global.asax file? if its only the application_start then you can move this to Startup.cs class and you can delete it. The Startup class only runs once when the application is bootstrapped(started/iis reset)

    • says

      Hi Alex, well I’ve tested it on major browsers including iPad, what exactly didn’t work? Token generation and consumption is not related to any front-end UI technology. Please elaborate more to help you.

  22. Kapo says

    Dear Taiseer

    Thank you for very nice tutorial. A while ago i started new project so i implemented your token authentication in it. Everything is working as it should except its taking too long to generate token (for example on GoDaddy hosting server it can take up to 5-10 seconds). Do you have any idea why is that happening?

    • says

      Hi Kapo,
      That’s strange, obtaining a token only do a single DB hit to validate username/password. If its public website please drop me the link and if you want a test credentials on my email so I check.

  23. says

    Hi Taiseer. Thank you for this great post, It really helped me a lot, but I have a problem with orders controller in different web api .
    In your example I tried to move orders controller in differet web api from where I generated token. Same machine, client allowed origin column set to my host.
    When I’m trying to call my api on orders the error 401 unauthorized appears and return to login page, not logged, if i don’use Authorize attribute on orders all work fine and after login oders page appear with all order. Cors is enabled.
    I read in prevoius post that you tried and for you worked, do you have any code example to download.
    Thanks

  24. says

    Amazing tutorial. Really give some light on how to work with Authentication Cookies, Bearer tokens and CORS.
    In my case the situation is different. I have created 3 different projects

    1) ASP.NET MVC to provide views
    2) Web API to retrieve Tokens and secure User CRUD operations
    3) Web API to retrieve normal data using [Authorize]

    The only problem I faced is to retrieve a bearer token, not from the /Token endpoint, but from the Login within my ASP.NET MVC application. For example, if I go straight into MySecureApi/Token of course I get a valid token that I can send back to my ProductApi/Get and it works on a CORS environment.
    The problem happens when I login in MVC, I still can’t understand how I can get back a Token from my Coockie Login. I can see the coockie generated correctly inside Chrome but I don’t understand how I can retrieve a bearer token from there.

  25. says

    AWESOME APP, the is a little bug with a version of google chrome in IOS. The file AuthComplete window.opener==null so it never close the new tab and not call authCompletedCB(fragment);

  26. AL says

    Can the Identity System be modified to use details other than username and password credentials such as only Identifying a user based on Name, date of Birth, email and a randomly generated code?

  27. OwinNewBie says

    Hi,Thanks for the wonderful post. Is it possible to replace ASP.Net Identity with my own Table for authentication ? I have a table called Logins where i store all the userids and passwords and my authrepository pings that table to see if a user exists.
    How can i accomplish this task without using UserManager or Identity ? Or is it absolutely required to use Identity ?

  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. 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

  33. 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?

  34. 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.

  35. 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.

  36. 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?

  37. 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.

Trackbacks

Leave a Reply