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. Bill Fleming says

    Hi Taiseer,

    In your article “AngularJS Token Authentication using ASP.NET Web API 2, Owin, and Identity” could I switch out the Bearer token with something similar you published about json web tokens?

    Basically I have a website that I’m writing in Angularjs (first time using AngularJS) and I want to authenticate the users against my ASP.Net Identity db and also protect my web api resources by using the techniques you have placed in your series via json web tokens.

    Thanks for the articles and direction.

    Bill Fleming

    • says

      The OAuth 2.0 didn’t specify format type for the token (string). Read the OAuth 2.0 specification here.
      The token should use the “Bearer” scheme when you send it in Authorization header for sure.
      So the answer is yes you can use JWT tokens instead of default tokens issued by Web API.

  2. Shane says

    This article has been very useful to me.

    Considering your expertise on the subject, I thought I might email you with a question I had that I am unable to find an answer for.

    The question is simple; Is there a way to define the clientID inside a Access / Bearer token using OWIN? (or for that matter, any other data at all besides just the claim and username)

    For example, when I use this token to access a protected API, I would like to know the clientID that made the request to get the token in the first place. This way I can log better details on my protected resource about who the client was that made the request.

    The next question would be how would one get this data on the client side once the client has passed it to me.

    I am currently storing this data inside a claim, and while this works, it is a terrible hack that I would like to solve in a correct manor.

    Thanks for your time.

    • says

      Hi Shane,
      I’ve just answered the same question on SO, I guess it is your question too :) Well my answer is not complete, you need to construct the Authentication ticket to be able to access “AuthenticationProperties” object which contains your client_id. Check the answer here

  3. says

    Thanks for this post!

    I’m having an issue when I try and get the authenticated user’s ID or username via the identity methods. For example: User.Identity.GetUserName() is returning null.. any ideas?

  4. Rajesh says

    Thank you Taiseer, I really excited your oAuth implementation using OWIN. After my deep analysis oAuth framework i have suggested to use OWIN to my project. But our Architect is not accepting OWIN instead he suggested to use DotNetOpenAuth. I request you to please give some best features are available in OWIN. This will help us to choose best one oAuth library.

  5. Marinko says

    Hi Taiseer,
    I’ve generated token as you suggested using POST request: http://ngauthenticationapi.azurewebsites.net/token?Accept=application/json&Content-Type=application/x-www-form-urlencoded

    When I tried to get orders using GET request:

    http://ngauthenticationapi.azurewebsites.net/api/Orders?Accept=application/json&Content-Type=application/json&Authorization=Bearer 0Ock7gfDyryUVEPL-8qlvRv1wNR6KUqyJgNRR9y0F8UJia71ssKQdlXDzfeIx4koaWKcjig3J92CAqyRXqsCLMUA_iZQR6sE0OwsE4iPcHYn9OPGp246DfTwAYDMyy2W3OofLo8ItiP8qpXNwKS2f7VDntbScZse9qK139uG469umqGA4bp14I4cbiiJsoj7sIvxFcGNN9O3z9NT6-evdNPYSEWtpUXLaKx_K1nyTYpGVa5DoZH9fxYpEfzPPKEjM9VrQxtwCE51nhoQXM_BYysV9WD5HjXzqYAlBc-ljat_HjxIP4hJNoyU7_JzgWtQMeLb8g

    I got an error:
    {
    “message”: “Authorization has been denied for this request.”
    }

    Could you tell me where I was wrong?

    Thanks

    • says

      You are not setting the Authorization header correctly, you are passing it as a query string, make sure to set it correctly as I dedcribed in the post, try to use PostMan which ease the process of compiling requests.

        • says

          Hi Mark,
          I do not recommend passing the token in query string because it will appear in browser history and get logged in server logs, but i guess you can do this if you override Authorize attribute and read the token and called unprotect, if there is no urgent need for this my recommendation is to stick with the authorization header. Good luck :)

  6. says

    First of all thanks to your posts. Very well explained. We are also planning to use claims in our project for authorisation. If I need to retrieve claims (e.g. Role which you are adding as one of the claim ) in client side then how do I retrieve it? We are using local. Storage (angularjs)

    • says

      Hi Punit,
      Glad post was useful, what you need to do is to return the claims with the response when you calling the endpoint “/token”. You can add them in the AuthenticationProperties dictionary as the code highlighted here. And in your AngularJS app you need to store them in local storage as I did for the token and this post might be helpful to show you how you can befit from the roles to protect the Angualr UI views. Again you need to keep in your mind that all the security checks should be done on server side.
      Hope this answers your question.

      • says

        Hi Taiseer,

        Is AuthenticationProperties only way to do so? We are adding claims into ClaimsIdentity so I was thinking how to fetch those? Our data is something below like this which we want to send to client-
        “role”: [
        "Admin",
        "Broker"
        ],

        Thanks,
        Punit

        • says

          Hi,
          If you do not want to store them in AuthenticationProperties dictionary then you can add a “Role” claim and store them in AspNetUserClaims table if you are using ASP.NET Identity, to retrieve them you can read my answer to this SO question.

          • says

            Hi,

            This is also to do check on server side. My scenario is like this- We have lot of view and UI elements and those can be viewed based on the permission level user has. We want to fetch our whole permission set into client side and do hide/show views/ui elements. Now I can go ahead and add all this as part of AuthenticationProperties and do that. On a client side we can fetch it from localstorage. The reason to ask to do it through claims as it provides much better level of code than AuthenticationProperties . If we can fetch claim in a client side then it would be easier as they are available in server also to validate.

            Let me know if I am making sense or not?

          • says

            Hi Punit,
            As I told you can store them in the claims, my recommendation is to add new end point where you can call it after you successfully authenticate the user and provide the token for the user, in this endpoint you can read all the claims for the authenticated user as the code below and return it as JSON object, then in your AngularJS application you can do you logic for hiding the views or links you want.

            [Authorize]
            [Route("")]
            public IHttpActionResult Get()
            {
            ClaimsPrincipal principal = Request.GetRequestContext().Principal as ClaimsPrincipal;

            var roles = principal.Claims.Where(c => c.Type == ClaimTypes.Role).First().Value;

            return Ok(roles);
            }

  7. says

    In this context is it possible to get back username of the authenticated user, let’s say I want to sent back department, and their phone number as well – if it’s attached to the claims of the identity it’s not sent back….

    • says

      Yup you can and I’m already returning the username when your request “/token” end point, you can return it like this. But notice that this will increase the token size, so be reasonable on what you are putting in the “AuthenticationProperties”. If you want to return complex object or lot of information please check my answer to this SO question.

  8. Nayas Subramanian says

    Hi,
    Could you tell Role based Authorization and authentication. if i put [Authorize] i can get the order details but if i put [Authorize(Roles="Admin)] i am not getting.

    Help is deeply appreciated
    Nayas Subramanian

  9. Jason says

    One of the best tutorial i’ve found on web.api security to be used with angularjs front end.
    I have followed this tutorial but ran in 2 problems:

    1. the first one is when i try to generate a token , i got ” The key ‘Access-Control-Allow-Origin’ is already present in the dictionary”. So I modified SimpleAuthorizationServerProvider.cs to remove the header before readding it in.
    context.OwinContext.Response.Headers.Remove(“Access-Control-Allow-Origin”);
    context.OwinContext.Response.Headers.Add(“Access-Control-Allow-Origin”, new[] { “*” });

    this allow me to call /token successfully to generate a token

    2. Current issue i am now facing and would really appreciate it if you can offer some help/direction in troubleshooting:

    When using the generated token to call /api/orders i keep getting “{
    “message”: “Authorization has been denied for this request.”
    }”

    this is what i use to do the get request in postman:
    i use postman just like you do , having 3 headers in my get request: Accept, Content-Type both set to application/json
    Authorization set to bearer WDrR0r401IAW-Lodh_jkBwiRzOwdcRqSuEJV3UlrWmaCcR4Rp9Y0tW1JU6Bacwih-Ln2dPZxmnHfQjBRko85yacxkZdqlzr7HczmEx-EPGHfZCg2_s7WWFUUzRi4Ba9jlLcdVrp4ylf8Lj83oL8dSsVmuD3pvtTP4a5iNwBiIUFfc4UfKPkufrzOj4M0vQnmlYa5Oizlq12I0egC_nNr5A4GjhEhxJ7F0_OqeH-sM6E

    after bearer is a space and the token that was returned.

    thank you for your help

    • says

      Hi Jason,
      Glad it was useful.
      Regarding the first point, I’m already configuring CORS and it reads the value from the DB, you might complete to part 3 to see how you can configure this dynamically.
      Second point: That is strange, anyhow I’ve created PostMan collection for you which contains the 2 requests (/token) and (/api/orders) and tested it successfully. You can invoke it and make sure your requests look like this collection.

    • says

      Hi Eric,
      As I stated in the article, or maybe part 2, there is no logout with tokens, you need to leave the token until it dies (expires) that’s why it is good practice to use refresh token and issue short long lived access tokens. What you can do is to delete the token from client store so app user next time will not be authenticated and will be forced to login again and obtain a new token.

  10. says

    Hi,

    How can i validate token values before authorization by owin middleware? User with token may be banned by admin but its token is still valid therefore user will be authroized. How can I prevent this?

  11. Rajesh says

    Hi Taiseer,is there any reason behind to keep TokenEndpoint in Startup.cs file? please refer below code i am asking. if we keep this in to application Startup?

    OAuthAuthorizationServerOptions OAuthServerOptions = new OAuthAuthorizationServerOptions()
    {
    AllowInsecureHttp = true,
    TokenEndpointPath = new PathString(“/token”),
    AccessTokenExpireTimeSpan = TimeSpan.FromDays(1),
    Provider = new SimpleAuthorizationServerProvider()
    };

    app.UseOAuthAuthorizationServer(OAuthServerOptions);

    //Token Consumption
    app.UseOAuthBearerAuthentication(new OAuthBearerAuthenticationOptions());

    • says

      Hi, Yes it should be on Startup class because in this class you register the middlewears needed in your request pipeline, I guess I’ve described this clearly as well what is the use of IAppBuilder too.
      Hope this answers your question.

  12. says

    hey thanks for your great post, you said “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” . I did everything like you said but database was not created at my local machine

    • says

      Hi Cuma,
      hat I suspect that you didn’t configure connection string in web.config correctly, check it and make sure you are using the same DB context initialization strategy I’m using.
      Hope this answers your question.

      • says

        Hey i figured out problem by changing datasource to localhost, but there is another question :) although when I run your web api project which I downloaded from github it creates user and other authentication related tables when I try to run web api project owin tables was not created automatically . What is the reason? can you guess?

  13. Bri says

    Hi Taiseer,

    Thanks you for this great tutorial,
    I am looking for a way to issue a Token after user register – so I will not have to pass him on to Login page.

    Call Login once registered.
    How should I implement it?

    • says

      Hi Bri,
      Usually you want to validate that user email provided is valid, so you send confirmation email to his email and asks him to login again, that is the normal process I recommend.
      Anyhow if you want to generate token after registering the user directly, then you need to issue separate HTTP request using HttpClient, not straight forward way tho.

  14. Luis says

    When logging in I can see that the method GrantResourceOwnerCredentials in the class SimpleAuthorizationServerProvider is called. However I don’t see the connection between the actual url (in my case “http://localhost:26264/token”) and the above mentioned method. Can you please tell me what I might be overlooking?

    • says

      The Auth middleware is responsible for this, and this depends on the grant_type you set, so if you tried to set grant_type=refresh_token then another method will be called, move to part three and check how we can use refresh tokens.

  15. Roi Sadeh says

    great post,
    i only have one problem with it, why do you use entity framework for this scenario,
    is there an example with out using entity framework ?

    Regards,
    Roi Sadeh

  16. BunsingIpad says

    Very informative tutorial.

    Just have a UI issue though (pardon me as I am only beginning to learn more on the CSS/Bootstrap thing).

    I noticed that when I browse the application (http://ngauthenticationweb.azurewebsites.net/) on a mobile device, the menu items which should be accessible via a button on the top right hand side of the screen does not show up anymore. This can also be reproduced if you reduce the browser width to something smaller. The menu becomes a 3 horizontal bar icon but clicking on it does not show the menu items.

    Not sure what needs to have it fixed, but would surely appreciate your answer.

    Overall this is a very good post.

    • says

      You are correct, for strange reason I can’t figure yet the menu is not working on mobile. But in my other SPA tutorial using AngularJS it is working, i guess you might need to add bootstrap.js, not sure but give it try if you want :) thanks for your comment.

    • says

      Hi Rodrigo, SPA is not confidential client, you can’t store the client secret in JS application, as well I’m not using Client Credentials flow here, I’m somehow using the Implicit flow and not storing client secret at all, just depending on pre registered redirect URI for this client then return an access token directly.

  17. Chris says

    Thank you so much for writing such an informative tutorial. I started with Visual Studio 2012 and used the MVC 4 Web Application (Web Api) template. I removed all the presentation-layer stuff and updated all the remaining packages with NuGet and then followed your tutorial and all works great!

    My end goal is to learn more about the new identity stuff (that is mentioned in the Scott Allen article) so I can use my own tables and pick-and-choose the fields I will be using. It’s going to be very exciting playing with that and OAuth.

    Great job again!

  18. Akinsanya Olanrewaju says

    Thanks for this article

    Haven follow the tutorial to Step 7: i intend to test it by posting to the api “/api/account/register” using the sample data, when i post the data via postman or fiddler to the end point: http://ngauthenticationapi.azurewebsites.net/api/account/register it work fine without error, but when i post uisng the sample in the github or following the tutorial directly,
    I dont know what am doing wrong please help me

    This is the error from postman with, 400 Bad Request as the status code
    {
    “message”: “The request is invalid.”,
    “modelState”: {
    “userModel”: [
    "Unexpected character encountered while parsing number: W. Path '', line 1, position 6."
    ]
    }
    }

    Thanks.

  19. says

    I’m using Emails as UserNames and out of the box it doesn’t play nice with Identity Framework. I’m having some issues setting AllowOnlyAlphanumericUserNames = false in the UserManager.

    Users can successfully register using an email address that contains special characters (ie. +,-) as I added this line in the RegisterUser method: _userManager.UserValidator = new UserValidator(_userManager) { AllowOnlyAlphanumericUserNames = false };

    However, the users can’t login. The special characters are stripped from the UserName when performing the lookup on the database. Any ideas as to where I should be setting AllowOnlyAlphanumericUserNames = false ?

  20. Batuta Batuta says

    Hi Taiseer,

    The application when viewed from a mobile device does not show the menu items, which I assume would become a button where the items are shown in a dropdown. I wonder what could be the cause of this? Hopefully you can look into this (as my css understanding is really a noob at this point).

    Thanks,.

  21. AL says

    Dear Taiseer,

    Thank you so much for writing such an informative tutorial, your sample run like a charm; I’m trying to secure ( https) some of the pages), can you advise in forcing https in some of the pages ( login registers) via controller or angularjs.

    Thanks;

    AL

    • says

      Hi AL, glad you liked it.
      You need to enforce https first on the server side for end point (/token) by setting (AllowInsecureHttp) to false in this class. Now to force HTTPS on other Api end points, you can check how to create [EnforceHttps] attribute here, lastly from your front end application you can servce the views using https only and you do this configuration from IIS.
      Hope this answers your question.

  22. says

    Hi. First of all, thank you for this example. It is really great. I am experimenting similar problems than above. I get “XMLHttpRequest cannot load http://localhost/AngularJSAuthentication.API/token. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://localhost:32150′ is therefore not allowed access. The response had HTTP status code 500.”

    It only happens under IIS, it works fine in ISExpress.

    I do not use refresh tokens and the client record is never used, so the problem is not the AllowedOrigin in Client table. (in any case I set * in this column). It happens entering an non-existing user name and password in the login view.

  23. says

    Hi Taiseer,
    Great article .. I came across it as I am trying to (foolishly perhaps) get the VS Tools for Cordova to do this very thing in a mobile app..
    I realise that Cordova users are mainly Node oriented, but as long as we are getting JSON back right? I really didn’t want to add Node to the list of things I need to learn on top of JavaScript/Angular.. (background is C# and MVC).. any way..

    I tried to get your sample moved over to a Cordova app.. but am having real difficulty getting the response object back valid.
    I am using my own site api, and it returns the same (almost) as yours.
    Here is an example of my response object..
    JSON
    .expires=Wed, 31 Dec 2014 10:41:41 GMT
    .issued=Wed, 17 Dec 2014 10:41:41 GMT
    access_token=rmTWeHtzTc0W4zKGsIij6GuHWtpOZ-kc3NBCYh4QX9jYdBMvrF_WxBs1usIRIsNORCJOZTpdQ8gBBg1m5r2ECBsGrmuN8fUgwq5cH1Hz5WIpeTajz99l5TPdX7xAHuV962_d3bdg19M59ZTr67jg1Nxg5N565ljqa8Mui-twZ8ZKNwSBcZvq5koqz2iuKAqwBXc-zVDza3i_r3JYtFTPZyWvJHuSfEOvHbLZz7OzucbZrLD3_zHt4KT4wVCCAD3tFP11L3wtpoU0kibjPgLpiZP_97ctpoCyCvHAMqGg48e8s4PmZJx5gs-PTbWO2iXHJRiLNk4MQ3Pg0wWWDoaki-AHTR-SfF7j46_eBQ4_vptCwIZE7FD0rLsGtvbE1qkxBdEUuvomyLpJ7CoINIROcH_iKUMd1DnrsStXwO6KkpHLk04enolhsZ74bYRYk3jtdHZ9i8yG8dIQDOtsR33dXMNOF_bO_etLD_7tmfPP6cW55dDm-rrbnWozAD0LzwQYwwdgiomAJl4_qYX3qlPD9A
    expires_in=1209599
    token_type=bearer
    userName=admin@mybizzylife.com

    Which looks right ish.. but I am getting to the ‘.error’ on every response.. I realise this might be because I don’t quite have the same response as you have, but I can’t see where you set that up.. I am unable to set a break on getting to the reponse object too.. and where you define what the response should be.. sorry if this is a stupid question, I realise this is probably as much to do with my learning of all the tools.. but Ive been struggling for a while now and any help would be appreciated..

    As an aside, I wondered if this was a possible deviation for your tutorial as there is absolutely nothing out there for folks wanting to use Angular – Cordova and Oauth signin..?
    Rgds Brett

    • says

      Hi Brett,
      Your response looks fine, there is nothing wrong with it, but what do you mean you are getting the “.error” in every response? Is this something related to Cordova?
      If you need to customize the response nodes, you need to over the “TokenEndpoint” in class “SimpleAuthorizationServerProvider”, and anything you add it to the the “AuthenticationProperties” dictionary will appear in the response.
      Hope this helps.

  24. says

    Hey there. Thank you for a great tutorial. I have a problem, though. I am try to send out emails for confirmation to the users that register. Now I have implemented the code inside the AuthRepository.cs. But I get an error when trying to use the UrlHelper class to generate the confirmation url to be sent out in the email. I get an exception that Routecollection parameter cannot be null. Now since we delete the Global.asax that registers and maps the routes/routecollection, it will be null. Can you please throw some light on how to go about doing it?

    Here is my code for your review. Thanks for your help in advance.

    This is the AccountController.cs


    [AllowAnonymous]
    [Route("Register")]
    public async Task Register(UserModel userModel)
    {
    if (!ModelState.IsValid)
    {
    return BadRequest(ModelState);
    }

    IdentityResult result = await authRepository.RegisterUser(userModel);
    IHttpActionResult errorResult = GetErrorResult(result);

    if (errorResult != null)
    {
    return errorResult;
    }

    return Ok();
    }

    This is the AuthRepository.cs


    public async Task RegisterUser(UserModel userModel)
    {
    IdentityUser user = new IdentityUser
    {
    UserName = userModel.UserName,
    Email = userModel.UserName
    };

    IdentityResult result = await userManager.CreateAsync(user, userModel.Password); //var result

    if (result.Succeeded)
    {
    try
    {
    var provider = new DpapiDataProtectionProvider("TestWebAPI");
    userManager.UserTokenProvider = new DataProtectorTokenProvider(provider.Create("EmailConfirmation"));
    var code = await userManager.GenerateEmailConfirmationTokenAsync(user.Id);
    UrlHelper urlHelper = new UrlHelper();
    var callbackUrl = urlHelper.Action
    (
    "ConfirmEmail", "Account",
    new { userId = user.Id, code = code },
    protocol: "http"
    );

    await userManager.SendEmailAsync(user.Id, "Confirm your account", "Please confirm...." + "click here");
    }
    catch (Exception ex)
    {
    throw new Exception(ex.ToString());
    }
    }
    return result;
    }

    It fails at the point where I generate the callbackurl. I get this exception: “Value cannot be null.\r\nParameter name: routeCollection”

    This is the stacktrace:


    at System.Web.Mvc.UrlHelper.GenerateUrl(String routeName, String actionName, String controllerName, RouteValueDictionary routeValues, RouteCollection routeCollection, RequestContext requestContext, Boolean includeImplicitMvcValues)
    at System.Web.Mvc.UrlHelper.GenerateUrl(String routeName, String actionName, String controllerName, String protocol, String hostName, String fragment, RouteValueDictionary routeValues, RouteCollection routeCollection, RequestContext requestContext, Boolean includeImplicitMvcValues)
    at System.Web.Mvc.UrlHelper.Action(String actionName, String controllerName, Object routeValues, String protocol)
    at TestWebAPI.AuthRepository.d__1.MoveNext() in d:\Workspace\VKalpa 2.0\Projects\Test\WebAPI-0.2\TestWebAPI\TestWebAPI\AuthRepository.cs:line 44

    • says

      You are welcome, glad you liked it.
      I guess you are facing the issue because you are using Mvc UrlHelpers not “System.Web.Http.UrlHelper”, the below code is working on my project, just make sure you are importing the correct name spaces.

      string code = await UserManager.GenerateEmailConfirmationTokenAsync(currentUser.Id);
      var callbackUrl = new Uri(Url.Link(“ConfirmEmailRoute”, new { userId = user.Id, code = code }));
      await UserManager.SendEmailAsync(user.Id, “Confirm your account”, “Please confirm your account by clicking here“);

      • says

        Hey Taiseer,

        Thank you for the reply. Yes, I have used the MVC UrlHelper. Since I am implementing the email solution in a Web API project, I do not have access to the Url class. It works perfectly in a MVC 5 web app, though.

        I solved it by taking some ques from you and other forums.

        Here is my code. Let me know of your thought.


        public async Task RegisterUser(UserModel userModel)
        {
        IdentityUser user = new IdentityUser
        {
        UserName = userModel.UserName,
        Email = userModel.UserName
        };

        var result = await userManager.CreateAsync(user, userModel.Password);

        if (result.Succeeded)
        {
        try
        {
        var provider = new DpapiDataProtectionProvider("TestWebAPI");
        userManager.UserTokenProvider = new DataProtectorTokenProvider(provider.Create("EmailConfirmation"));
        var code = await userManager.GenerateEmailConfirmationTokenAsync(user.Id);

        var newRouteValues = new RouteValueDictionary(new { userId = user.Id, code = code});
        newRouteValues.Add("httproute", true);
        UrlHelper urlHelper = new UrlHelper(HttpContext.Current.Request.RequestContext, RouteTable.Routes);
        string callbackUrl = urlHelper.Action(
        "ConfirmEmail",
        "Account",
        newRouteValues,
        HttpContext.Current.Request.Url.Scheme
        );

        string emailTitle = "Please confirm your account";
        string emailBody = "Please click Here to confirm your email";

        await userManager.SendEmailAsync(user.Id, emailTitle, emailBody);
        }
        catch (Exception ex)
        {
        throw new Exception(ex.ToString());
        }
        }

        return result;
        }

        Thanks again for your brilliant tutorial. It’s wonderfully explained.

        Best,
        Ram Iyer

  25. says

    For some reason, my post gets deleted. I was asking how I would implement a email confirmation sent on successful user registration. I tried implementing this:

    …..
    IdentityResult result = await userManager.CreateAsync(user, userModel.Password); //var result

    if (result.Succeeded)
    {
    try
    {
    var provider = new DpapiDataProtectionProvider(“TestWebAPI”);
    userManager.UserTokenProvider = new DataProtectorTokenProvider(provider.Create(“EmailConfirmation”));
    var code = await userManager.GenerateEmailConfirmationTokenAsync(user.Id);
    UrlHelper urlHelper = new UrlHelper();
    var callbackUrl = urlHelper.Action
    (
    “ConfirmEmail”, “Account”,
    new { userId = user.Id, code = code },
    protocol: “http”
    );

    await userManager.SendEmailAsync(user.Id, “Confirm your account”, “Please confirm….” + “click here“);
    }
    }
    catch (Exception ex)
    {
    throw new Exception(ex.ToString());
    }
    }

    I get an exception at the callbackUrl line: “Value cannot be null.\r\nParameter name: routeCollection”. Not sure what I am doing wrong. Can you please throw some light?

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

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

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

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

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

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

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

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

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

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