ASP.NET Identity 2.1 is the latest membership and identity management framework provided by Microsoft, this membership system can be plugged to any ASP.NET framework such as Web API, MVC, Web Forms, etc…
In this tutorial we’ll cover how to integrate ASP.NET Identity system with ASP.NET Web API , so we can build a secure HTTP service which acts as back-end for SPA front-end built using AngularJS, I’ll try to cover in a simple way different ASP.NET Identity 2.1 features such as: Accounts managements, roles management, email confirmations, change password, roles based authorization, claims based authorization, brute force protection, etc…
The AngularJS front-end application will use bearer token based authentication using Json Web Tokens (JWTs) format and should support roles based authorization and contains the basic features of any membership system. The SPA is not ready yet but hopefully it will sit on top of our HTTP service without the need to come again and modify the ASP.NET Web API logic.
I will follow step by step approach and I’ll start from scratch without using any VS 2013 templates so we’ll have better understanding of how the ASP.NET Identity 2.1 framework talks with ASP.NET Web API framework.
The source code for this tutorial is available on GitHub.
I broke down this series into multiple posts which I’ll be posting gradually, posts are:
- Configure ASP.NET Identity with ASP.NET Web API (Accounts Management) – (This Post)
- ASP.NET Identity 2.1 Accounts Confirmation, and Password/User Policy Configuration – Part 2
- Implement OAuth JSON Web Tokens Authentication in ASP.NET Web API and Identity 2.1 – Part 3
- ASP.NET Identity Role Based Authorization with ASP.NET Web API – Part 4
- ASP.NET Web API Claims Authorization with ASP.NET Identity 2.1 – Part 5
- AngularJS Authentication and Authorization with ASP.NET Web API and Identity – Part 6
Configure ASP.NET Identity 2.1 with ASP.NET Web API 2.2 (Accounts Management)
Setting up the ASP.NET Identity 2.1
Step 1: Create the Web API Project
In this tutorial I’m using Visual Studio 2013 and .Net framework 4.5, now create an empty solution and name it “AspNetIdentity” then add new ASP.NET Web application named “AspNetIdentity.WebApi”, we will select an empty template with no core dependencies at all, it will be as as the image below:
Step 2: Install the needed NuGet Packages:
We’ll install all those NuGet packages to setup our Owin server and configure ASP.NET Web API to be hosted within an Owin server, as well we will install packages needed for ASP.NET Identity 2.1, if you would like to know more about the use of each package and what is the Owin server, please check this post.
1 2 3 4 5 6 |
Install-Package Microsoft.AspNet.Identity.Owin -Version 2.1.0 Install-Package Microsoft.AspNet.Identity.EntityFramework -Version 2.1.0 Install-Package Microsoft.Owin.Host.SystemWeb -Version 3.0.0 Install-Package Microsoft.AspNet.WebApi.Owin -Version 5.2.2 Install-Package Microsoft.Owin.Security.OAuth -Version 3.0.0 Install-Package Microsoft.Owin.Cors -Version 3.0.0 |
Step 3: Add Application user class and Application Database Context:
Now we want to define our first custom entity framework class which is the “ApplicationUser” class, this class will represents a user wants to register in our membership system, as well we want to extend the default class in order to add application specific data properties for the user, data properties such as: First Name, Last Name, Level, JoinDate. Those properties will be converted to columns in table “AspNetUsers” as we’ll see on the next steps.
So to do this we need to create new class named “ApplicationUser” and derive from “Microsoft.AspNet.Identity.EntityFramework.IdentityUser” class.
Note: If you do not want to add any extra properties to this class, then there is no need to extend the default implementation and derive from “IdentityUser” class.
To do so add new folder named “Infrastructure” to our project then add new class named “ApplicationUser” and paste the code below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
public class ApplicationUser : IdentityUser { [Required] [MaxLength(100)] public string FirstName { get; set; } [Required] [MaxLength(100)] public string LastName { get; set; } [Required] public byte Level { get; set; } [Required] public DateTime JoinDate { get; set; } } |
Now we need to add Database context class which will be responsible to communicate with our database, so add new class and name it “ApplicationDbContext” under folder “Infrastructure” then paste the code snippet below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class ApplicationDbContext : IdentityDbContext<ApplicationUser> { public ApplicationDbContext() : base("DefaultConnection", throwIfV1Schema: false) { Configuration.ProxyCreationEnabled = false; Configuration.LazyLoadingEnabled = false; } public static ApplicationDbContext Create() { return new ApplicationDbContext(); } } |
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, this default constructor takes the connection string name “DefaultConnection” as an argument, this connection string will be used point to the right server and database name to connect to.
The static method “Create” will be called from our Owin Startup class, more about this later.
Lastly we need to add a connection string which points to the database that will be created using code first approach, so open “Web.config” file and paste the connection string below:
1 2 3 |
<connectionStrings> <add name="DefaultConnection" connectionString="Data Source=.\sqlexpress;Initial Catalog=AspNetIdentity;Integrated Security=SSPI;" providerName="System.Data.SqlClient" /> </connectionStrings> |
Step 4: Create the Database and Enable DB migrations:
Now we want to enable EF code first migration feature which configures the code first to update the database schema instead of dropping and re-creating the database with each change on EF entities, to do so we need to open NuGet Package Manager Console and type the following commands:
1 2 |
enable-migrations add-migration InitialCreate |
The “enable-migrations” command creates a “Migrations” folder in the “AspNetIdentity.WebApi” project, and it creates a file named “Configuration”, this file contains method named “Seed” which is used to allow us to insert or update test/initial data after code first creates or updates the database. This method is called when the database is created for the first time and every time the database schema is updated after a data model change.
As well the “add-migration InitialCreate” command generates the code that creates the database from scratch. This code is also in the “Migrations” folder, in the file named “<timestamp>_InitialCreate.cs“. The “Up” method of the “InitialCreate” class creates the database tables that correspond to the data model entity sets, and the “Down” method deletes them. So in our case if you opened this class “201501171041277_InitialCreate” you will see the extended data properties we added in the “ApplicationUser” class in method “Up”.
Now back to the “Seed” method in class “Configuration”, open the class and replace the Seed method code with the code below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
protected override void Seed(AspNetIdentity.WebApi.Infrastructure.ApplicationDbContext context) { // This method will be called after migrating to the latest version. var manager = new UserManager<ApplicationUser>(new UserStore<ApplicationUser>(new ApplicationDbContext())); var user = new ApplicationUser() { UserName = "SuperPowerUser", Email = "taiseer.joudeh@mymail.com", EmailConfirmed = true, FirstName = "Taiseer", LastName = "Joudeh", Level = 1, JoinDate = DateTime.Now.AddYears(-3) }; manager.Create(user, "MySuperP@ssword!"); } |
This code basically creates a user once the database is created.
Now we are ready to trigger the event which will create the database on our SQL server based on the connection string we specified earlier, so open NuGet Package Manager Console and type the command:
1 |
update-database |
The “update-database” command runs the “Up” method in the “Configuration” file and creates the database and then it runs the “Seed” method to populate the database and insert a user.
If all is fine, navigate to your SQL server instance and the database along with the additional fields in table “AspNetUsers” should be created as the image below:
Step 5: Add the User Manager Class:
The User Manager class will be responsible to manage instances of the user class, the class will derive from “UserManager<T>” where T will represent our “ApplicationUser” class, once it derives from the “ApplicationUser” class a set of methods will be available, those methods will facilitate managing users in our Identity system, some of the exposed methods we’ll use from the “UserManager” during this tutorial are:
Method Name | Usage |
---|---|
FindByIdAsync(id) | Find user object based on its unique identifier |
Users | Returns an enumeration of the users |
FindByNameAsync(Username) | Find user based on its Username |
CreateAsync(User, Password | Creates a new user with a password |
GenerateEmailConfirmationTokenAsync(Id) | Generate email confirmation token which is used in email confimration |
SendEmailAsync(Id, Subject, Body) | Send confirmation email to the newly registered user |
ConfirmEmailAsync(Id, token) | Confirm the user email based on the received token |
ChangePasswordAsync(Id, OldPassword, NewPassword) | Change user password |
DeleteAsync(User) | Delete user |
IsInRole(Username, Rolename) | Check if a user belongs to certain Role |
AddToRoleAsync(Username, RoleName) | Assign user to a specific Role |
RemoveFromRoleAsync(Username, RoleName | Remove user from specific Role |
Now to implement the “UserManager” class, add new file named “ApplicationUserManager” under folder “Infrastructure” and paste the code below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
public class ApplicationUserManager : UserManager<ApplicationUser> { public ApplicationUserManager(IUserStore<ApplicationUser> store) : base(store) { } public static ApplicationUserManager Create(IdentityFactoryOptions<ApplicationUserManager> options, IOwinContext context) { var appDbContext = context.Get<ApplicationDbContext>(); var appUserManager = new ApplicationUserManager(new UserStore<ApplicationUser>(appDbContext)); return appUserManager; } } |
As you notice from the code above the static method “Create” will be responsible to return an instance of the “ApplicationUserManager” class named “appUserManager”, the constructor of the “ApplicationUserManager” expects to receive an instance from the “UserStore”, as well the UserStore instance construct expects to receive an instance from our “ApplicationDbContext” defined earlier, currently we are reading this instance from the Owin context, but we didn’t add it yet to the Owin context, so let’s jump to the next step to add it.
Note: In the coming post we’ll apply different changes to the “ApplicationUserManager” class such as configuring email service, setting user and password polices.
Step 6: Add Owin “Startup” Class
Now we’ll add the Owin “Startup” class which will be fired once our server starts. 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, so add new file named “Startup” to the root of the project and paste the code below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
public class Startup { public void Configuration(IAppBuilder app) { HttpConfiguration httpConfig = new HttpConfiguration(); ConfigureOAuthTokenGeneration(app); ConfigureWebApi(httpConfig); app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll); app.UseWebApi(httpConfig); } private void ConfigureOAuthTokenGeneration(IAppBuilder app) { // Configure the db context and user manager to use a single instance per request app.CreatePerOwinContext(ApplicationDbContext.Create); app.CreatePerOwinContext<ApplicationUserManager>(ApplicationUserManager.Create); // Plugin the OAuth bearer JSON Web Token tokens generation and Consumption will be here } private void ConfigureWebApi(HttpConfiguration config) { config.MapHttpAttributeRoutes(); var jsonFormatter = config.Formatters.OfType<JsonMediaTypeFormatter>().First(); jsonFormatter.SerializerSettings.ContractResolver = new CamelCasePropertyNamesContractResolver(); } } |
What worth noting here is how we are creating a fresh instance from the “ApplicationDbContext” and “ApplicationUserManager” for each request and set it in the Owin context using the extension method “CreatePerOwinContext”. Both objects (ApplicationDbContext and AplicationUserManager) will be available during the entire life of the request.
Note: I didn’t plug any kind of authentication here, we’ll visit this class again and add JWT Authentication in the next post, for now we’ll be fine accepting any request from any anonymous users.
Define Web API Controllers and Methods
Step 7: Create the “Accounts” Controller:
Now we’ll add our first controller named “AccountsController” which will be responsible to manage user accounts in our Identity system, to do so add new folder named “Controllers” then add new class named “AccountsController” and paste the code below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 |
[RoutePrefix("api/accounts")] public class AccountsController : BaseApiController { [Route("users")] public IHttpActionResult GetUsers() { return Ok(this.AppUserManager.Users.ToList().Select(u => this.TheModelFactory.Create(u))); } [Route("user/{id:guid}", Name = "GetUserById")] public async Task<IHttpActionResult> GetUser(string Id) { var user = await this.AppUserManager.FindByIdAsync(Id); if (user != null) { return Ok(this.TheModelFactory.Create(user)); } return NotFound(); } [Route("user/{username}")] public async Task<IHttpActionResult> GetUserByName(string username) { var user = await this.AppUserManager.FindByNameAsync(username); if (user != null) { return Ok(this.TheModelFactory.Create(user)); } return NotFound(); } } |
What we have implemented above is the following:
- Our “AccountsController” inherits from base controller named “BaseApiController”, this base controller is not created yet, but it contains methods that will be reused among different controllers we’ll add during this tutorial, the methods which comes from “BaseApiController” are: “AppUserManager”, “TheModelFactory”, and “GetErrorResult”, we’ll see the implementation for this class in the next step.
- We have added 3 methods/actions so far in the “AccountsController”:
- Method “GetUsers” will be responsible to return all the registered users in our system by calling the enumeration “Users” coming from “ApplicationUserManager” class.
- Method “GetUser” will be responsible to return single user by providing it is unique identifier and calling the method “FindByIdAsync” coming from “ApplicationUserManager” class.
- Method “GetUserByName” will be responsible to return single user by providing it is username and calling the method “FindByNameAsync” coming from “ApplicationUserManager” class.
- The three methods send the user object to class named “TheModelFactory”, we’ll see in the next step the benefit of using this pattern to shape the object graph returned and how it will protect us from leaking any sensitive information about the user identity.
- Note: All methods can be accessed by any anonymous user, for now we are fine with this, but we’ll manage the access control for each method and who are the authorized identities that can perform those actions in the coming posts.
Step 8: Create the “BaseApiController” Controller:
As we stated before, this “BaseApiController” will act as a base class which other Web API controllers will inherit from, for now it will contain three basic methods, so add new class named “BaseApiController” under folder “Controllers” and paste the code below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 |
public class BaseApiController : ApiController { private ModelFactory _modelFactory; private ApplicationUserManager _AppUserManager = null; protected ApplicationUserManager AppUserManager { get { return _AppUserManager ?? Request.GetOwinContext().GetUserManager<ApplicationUserManager>(); } } public BaseApiController() { } protected ModelFactory TheModelFactory { get { if (_modelFactory == null) { _modelFactory = new ModelFactory(this.Request, this.AppUserManager); } return _modelFactory; } } protected IHttpActionResult GetErrorResult(IdentityResult result) { if (result == null) { return InternalServerError(); } if (!result.Succeeded) { if (result.Errors != null) { foreach (string error in result.Errors) { ModelState.AddModelError("", error); } } if (ModelState.IsValid) { // No ModelState errors are available to send, so just return an empty BadRequest. return BadRequest(); } return BadRequest(ModelState); } return null; } } |
What we have implemented above is the following:
- We have added read only property named “AppUserManager” which gets the instance of the “ApplicationUserManager” we already set in the “Startup” class, this instance will be initialized and ready to invoked.
- We have added another read only property named “TheModelFactory” which returns an instance of “ModelFactory” class, this factory pattern will help us in shaping and controlling the response returned to the client, so we will create a simplified model for some of our domain object model (Users, Roles, Claims, etc..) we have in the database. Shaping the response and building customized object graph is very important here; because we do not want to leak sensitive data such as “PasswordHash” to the client.
- We have added a function named “GetErrorResult” which takes “IdentityResult” as a constructor and formats the error messages returned to the client.
Step 8: Create the “ModelFactory” Class:
Now add new folder named “Models” and inside this folder create new class named “ModelFactory”, this class will contain all the functions needed to shape the response object and control the object graph returned to the client, so open the file and paste the code below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 |
public class ModelFactory { private UrlHelper _UrlHelper; private ApplicationUserManager _AppUserManager; public ModelFactory(HttpRequestMessage request, ApplicationUserManager appUserManager) { _UrlHelper = new UrlHelper(request); _AppUserManager = appUserManager; } public UserReturnModel Create(ApplicationUser appUser) { return new UserReturnModel { Url = _UrlHelper.Link("GetUserById", new { id = appUser.Id }), Id = appUser.Id, UserName = appUser.UserName, FullName = string.Format("{0} {1}", appUser.FirstName, appUser.LastName), Email = appUser.Email, EmailConfirmed = appUser.EmailConfirmed, Level = appUser.Level, JoinDate = appUser.JoinDate, Roles = _AppUserManager.GetRolesAsync(appUser.Id).Result, Claims = _AppUserManager.GetClaimsAsync(appUser.Id).Result }; } } public class UserReturnModel { public string Url { get; set; } public string Id { get; set; } public string UserName { get; set; } public string FullName { get; set; } public string Email { get; set; } public bool EmailConfirmed { get; set; } public int Level { get; set; } public DateTime JoinDate { get; set; } public IList<string> Roles { get; set; } public IList<System.Security.Claims.Claim> Claims { get; set; } } |
Notice how we included only the properties needed to return them in users object graph, for example there is no need to return the “PasswordHash” property so we didn’t include it.
Step 9: Add Method to Create Users in”AccountsController”:
It is time to add the method which allow us to register/create users in our Identity system, but before adding it, we need to add the request model object which contains the user data which will be sent from the client, so add new file named “AccountBindingModels” under folder “Models” and paste the code below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
public class CreateUserBindingModel { [Required] [EmailAddress] [Display(Name = "Email")] public string Email { get; set; } [Required] [Display(Name = "Username")] public string Username { get; set; } [Required] [Display(Name = "First Name")] public string FirstName { get; set; } [Required] [Display(Name = "Last Name")] public string LastName { get; set; } [Display(Name = "Role Name")] public string RoleName { get; set; } [Required] [StringLength(100, ErrorMessage = "The {0} must be at least {2} characters long.", MinimumLength = 6)] [DataType(DataType.Password)] [Display(Name = "Password")] public string Password { get; set; } [Required] [DataType(DataType.Password)] [Display(Name = "Confirm password")] [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")] public string ConfirmPassword { get; set; } } |
The class is very simple, it contains properties for the fields we want to send from the client to our API with some data annotation attributes which help us to validate the model before submitting it to the database, notice how we added property named “RoleName” which will not be used now, but it will be useful in the coming posts.
Now it is time to add the method which register/creates a user, open the controller named “AccountsController” and add new method named “CreateUser” and paste the code below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
[Route("create")] public async Task<IHttpActionResult> CreateUser(CreateUserBindingModel createUserModel) { if (!ModelState.IsValid) { return BadRequest(ModelState); } var user = new ApplicationUser() { UserName = createUserModel.Username, Email = createUserModel.Email, FirstName = createUserModel.FirstName, LastName = createUserModel.LastName, Level = 3, JoinDate = DateTime.Now.Date, }; IdentityResult addUserResult = await this.AppUserManager.CreateAsync(user, createUserModel.Password); if (!addUserResult.Succeeded) { return GetErrorResult(addUserResult); } Uri locationHeader = new Uri(Url.Link("GetUserById", new { id = user.Id })); return Created(locationHeader, TheModelFactory.Create(user)); } |
What we have implemented here is the following:
- We validated the request model based on the data annotations we introduced in class “AccountBindingModels”, if there is a field missing then the response will return HTTP 400 with proper error message.
- If the model is valid, we will use it to create new instance of class “ApplicationUser”, by default we’ll put all the users in level 3.
- Then we call method “CreateAsync” in the “AppUserManager” which will do the heavy lifting for us, inside this method it will validate if the username, email is used before, and if the password matches our policy, etc.. if the request is valid then it will create new user and add to the “AspNetUsers” table and return success result. From this result and as good practice we should return the resource created in the location header and return 201 created status.
Notes:
- Sending a confirmation email for the user, and configuring user and password policy will be covered in the next post.
- As stated earlier, there is no authentication or authorization applied yet, any anonymous user can invoke any available method, but we will cover this authentication and authorization part in the coming posts.
Step 10: Test Methods in”AccountsController”:
Lastly it is time to test the methods added to the API, so fire your favorite REST client Fiddler or PostMan, in my case I prefer PostMan. So lets start testing the “Create” user method, so we need to issue HTTP Post to the URI: “http://localhost:59822/api/accounts/create” as the request below, if creating a user went good you will receive 201 response:
Now to test the method “GetUsers” all you need to do is to issue HTTP GET to the URI: “http://localhost:59822/api/accounts/users” and the response graph will be as the below:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 |
[ { "url": "http://localhost:59822/api/accounts/user/29e21f3d-08e0-49b5-b523-3d68cf623fd5", "id": "29e21f3d-08e0-49b5-b523-3d68cf623fd5", "userName": "SuperPowerUser", "fullName": "Taiseer Joudeh", "email": "taiseer.joudeh@gmail.com", "emailConfirmed": true, "level": 1, "joinDate": "2012-01-17T12:41:40.457", "roles": [ "Admin", "Users", "SuperAdmin" ], "claims": [ { "issuer": "LOCAL AUTHORITY", "originalIssuer": "LOCAL AUTHORITY", "properties": {}, "subject": null, "type": "Phone", "value": "123456782", "valueType": "http://www.w3.org/2001/XMLSchema#string" }, { "issuer": "LOCAL AUTHORITY", "originalIssuer": "LOCAL AUTHORITY", "properties": {}, "subject": null, "type": "Gender", "value": "Male", "valueType": "http://www.w3.org/2001/XMLSchema#string" } ] }, { "url": "http://localhost:59822/api/accounts/user/f0f8d481-e24c-413a-bf84-a202780f8e50", "id": "f0f8d481-e24c-413a-bf84-a202780f8e50", "userName": "tayseer.Joudeh", "fullName": "Tayseer Joudeh", "email": "tayseer_joudeh@hotmail.com", "emailConfirmed": true, "level": 3, "joinDate": "2015-01-17T00:00:00", "roles": [], "claims": [] } ] |
The source code for this tutorial is available on GitHub.
In the next post we’ll see how we’ll configure our Identity service to start sending email confirmations, customize username and password polices, implement Json Web Token (JWTs) Authentication and manage the access for the methods.
great post Taiseer.
i was trying to find a way for how to make aspnet identity integrate with my own database schema(to follow the DB team standards ) and i actually hit the wall hard , now finally they released the code of this library ! here https://github.com/aspnet/Identity/.
Thanks Omar for your comment, I agree with you it was hard to integrate ASP.NET Identity with existing database.
Omar this is actually pretty straightforward if you follow the code first approach as you can override the “OnModelCreating” function and then make customizations to the AspIdentity schema from there.
This is excellent Taiseer. Keep up the great work. I can’t wait to see the complete end-to-end with the AngularJS UI. Are you planning to illustrate with a mini CRUD app? Any plans on when your series will be complete? Thanks again. Kind Regards. Walter.
Hi Walter, well I’ll try to blog 2/3 posts per month, so maybe by the end of Feb , hopefully 🙂 Yes it will be simple membership system.
This is great, thank you! I only wish the entire tutorial was complete. I’m just starting out on a new project and this was exactly the approach I was hoping to use. More, more, please!
Next post will be on Monday, thanks and keep tuned.
Excellent.
Hi Taisser
Would it be possible to add prompting a user to change password on first login to your series. I implement auto registration
of accounts with a default password and want users to change to their own personalized credential when they first use the SPA. If not, what would be the best practice to add this functionality with ASPNET identity/OWIN.
Thanks so much for your clear content inspirational blogs. They are a pleasure to go through.Just need the light bulb to go off on the above and I’ll feel in control for the first time 🙂 Mostly due to your blogs.
Cheers
Hi Andrew,
Really happy to hear that posts are useful 🙂 I’m currently writing the part 2, and the use case you asked for is not covered yet, but I guess it can be added easily, let me think about it, and if I didn’t add it to the post we can take this offline later on. So Keep tuned!
Thanks Taisser. Certainly will keep tuned.
Cheers
Can we consume that api from Android and iOS mobile applications too ?
Thank you!
Absolutely, you can use this HTTP Service with any front-end client able to send HTTP requests.
Thank you very much !
I ‘ve already integrated User Authentication from your articles. Looking forward to Role Based Authorization. These are really helpful articles.
Very understandable , clear , easy and very useful.
Cheers ! Will keep tuned too:)
Salaam Taiseer, thank you for the post, I am learning all this websites stuff 🙂 – just so I am clear model factory acts similar to Auto mapper for mapping Model to DTOs?
Salam Bilal,
Thanks for your message, and yes you can use Auto Mapper instead of model factory, but I prefer this pattern which gives me more control over DTOs returned.
Thank you 🙂
Hi, I’m new to your blog and it seems to be that there are two series of posts about the same topic (Asp.net Identity with AngularJS). Could you please explain the differences between the series? Could I implement the solution in your first series or should I wait for this one to be finished? Thanks a lot in advance!
Hi, yes you can depend on the first tutorial, this one I’m building shows the features of ASP.NET Identity and covers different types of Authorization such as Roles and Claims.
Hi
Taiseer, the blog is very useful to me , I also wanted to know the difference between the first series and this one ? Both are token based and both use OWIN.
Great to hear it is useful, this one focus more on Asp.Net Identity features and APIs.
Hi Taiseer,
Please can you give example of Database first approch.
Hi Mahavir,
You mean adding Asp.Net Identity to existing database? You can check this post. I do not have something written for this usecase, still you can use Asp.Net Identity with existing database using Code First approach.
Great tutorial. However, I did run into a problem
Error 1 ‘System.Net.Http.HttpRequestMessage’ does not contain a definition for ‘GetOwinContext’ and no extension method ‘GetOwinContext’ accepting a first argument of type ‘System.Net.Http.HttpRequestMessage’ could be found (are you missing a using directive or an assembly reference?) C:\Projects\AspNetIdentity\AaspNetIdentity.WebApi\Controllers\BaseApiController.cs 20 51 AaspNetIdentity.WebApi
Found the reason: I had to reference System.Net.Http and the System.Web.Http from Microsoft.AspNet.WebApi.Owin
Glad that it worked 🙂
Unfortunately it does not 🙁
Try changing “Request” to “HttpContext.Current”.
Also note, that if you are using WebApi2.2, the location of the extension method “GetUserManager” has changed to: Microsoft.AspNet.Identity.Owin library.
I had the same issue and resolved it using these as using statements:
using AspNetIdentity.Infrastructure;
using System.Web;
using System.Web.Http;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using AspNetIdentity.Models;
Hi! Great post. Unfortunately I’m facing the same issue with missing definition for GetOwinContext(). Would you have a solution for this?
The source code repo has these in the following using statements.
using AspNetIdentity.WebApi.Infrastructure;
using AspNetIdentity.WebApi.Models;
using Microsoft.AspNet.Identity;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using System.Net.Http;
using Microsoft.AspNet.Identity.Owin;
I had resolved it using these references.. -:)
using AspNetIdentity.WebApi.Infrastructure;
using System.Web;
using System.Web.Http;
using System.Net.Http;
using Microsoft.AspNet.Identity;
using Microsoft.AspNet.Identity.Owin;
using AspNetIdentity.WebApi.Models;
Hi, I’ve followed this post (using visual studio 2013) but cannot get the IIS express to find the controllers. I keep getting a 404 when I try to do a GET with postman. http://localhost:63486/api/accounts/users. I have configured application startup to be this project in my solution and I am running the web api application on http://localhost:63486. My code is identical to yours except that I’ve mapped my users db-table to another table than AspnetUsers.
How should I be hosting owin in IIS, I guess following the steps mentioned above should be good enough or am I missing something?
Hey, I had the same problem. You probably forgot to add [RoutePrefix(“api/accounts”)] attribute above the AccountsController.
What a great post!
Dying to see the AngularJS post
Thanks for this great article Taiseer…
Can i use (LocalDb)\v 11.0 instead of default <add name="DefaultConnection" connectionString="Data Source=.\sqlexpress;Initial Catalog=AspNetIdentity; in web.config.
I actually tried to change the data source to localdb but i dont know why database cant be created with this technique..Could you please help me on that?
Hi, it should work without issues, please check this URL and double check that you are not receiving any errors on Package Manager Console when you type “update-database”
These posts are fantastic, as are the first series on this topic. In this particular one, my last test did not reveal that my power user had any claims, unlike the example.
hi
I tried yuor project but don’t work..
I did this :
Download project
Build it and publish on my azure account
Change the url in //var serviceBase = ‘http://ngauthenticationapi.azurewebsites.net/’; with my new url
Start the project web and tried the registration user but don’t work I obtain this error “Failed to register user due to: ”
Where is the error?
You can hel me?
br
Hi,
I replied you by email, please read the post carefully as all the steps implemented successfully and thousand of devs implemented it successfully.
Dude your series simply rocks. I just follow the tutorial step by step, and in exactly 30″ I have a web api OWIN authentication server up and running. Amazing, great job, eager to read the next steps!!
Glad it was easy to follow and implement, keep tuned, the next part is coming soon.
Salaan Taiseer, I am trying to add some abstraction layer but a bit stuck would be able to answer a question http://stackoverflow.com/questions/29195043/null-base-unitofwork-entityframework-with-repository-pattern-usermanager ?
Thanks for the great series of articles Taiseer. They are very informative reads.
May I ask a couple of questions please?
In the Seed() method, what is the benefit of creating a new ApplicationDbContext instead of using the one provided as a parameter?
Wehn you test the GetUsers method via a HTTP GET, you get a response where SuperPowerUser has a couple of claims. How did the claims get in there?
Hi Phil, glad that posts are useful,
For the first question you are right, we can use the context in the parameter, I should fix this but it seems that I took this code from a unit test function I used to test the migration.
Good catch in the the second point 🙂 I added them manually in the table to make sure that identity system is returning claims correctly, I’m currently working on next post which will cover claims in more depth. You can ignore those claims for now.
Regards,
Taiseer
Hello Taiseer, how are you?
I would like to congratulate you on the magnificent work that you have done with Web API, Asp.NET Identity, Angularjs, etc.
Great Job!!! Thanks for share your knowledge with us
You are welcome, glad to know that posts are useful!
Thanks for the tutorial. I followed the steps, and when testing with PostMan to create an account, I got error:
{“message”:”The request entity’s media type ‘multipart/form-data’ is not supported for this resource.”,”exceptionMessage”:”No MediaTypeFormatter is available to read an object of type ‘AccountBindingModels’ from content with media type ‘multipart/form-data’.”,”exceptionType”:”System.Net.Http.UnsupportedMediaTypeException”,”stackTrace”:” at System.Net.Http.HttpContentExtensions.ReadAsAsync[T](HttpContent content, Type type, IEnumerable
1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)\r\n at System.Net.Http.HttpContentExtensions.ReadAsAsync(HttpContent content, Type type, IEnumerable
1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)\r\n at System.Web.Http.ModelBinding.FormatterParameterBinding.ReadContentAsync(HttpRequestMessage request, Type type, IEnumerable`1 formatters, IFormatterLogger formatterLogger, CancellationToken cancellationToken)”}Never mind, forgot to put header there.
Glad it is working!
Great article! Can’t wait for the next part. I am currently running into a problem and was hoping you could point me in the right direction –
I have downloaded the supplied code (using visual studio 2013) but cannot get the IIS express to find the controllers. I keep getting a 404 when I try to contact the controller regardless of the api call I make (create or get users) with postman. I have looked as IIS express and can see it running. The only difference between the downloaded coded and what I am running is that I am using a different DB running under SQL Server. How do I go about debugging this?
Hi Carig, apologies for the late reply. Well that is strange, the DB should do nothing with hitting the API endpoints. You still facing this issue or you were able to resolve it?
Hi Taiseer – thanks for the reply as I know your busy with part 6. I was able to figure it out, the problem was with PostMan. I must have missed your blog on how to use the tool. Now i just need to know how to connect a Web Client to the API, especially dealing with logging in.
Hi Taiseer,
As always, great posts on identity. I think I asked this already, but didn’t see the comment come up. How is this implementation different from your previous series (June 2014) on implementing Identity with ASP.NET Web API? Just trying to understand what the differences are to see what’s best to use for my own project. Thanks!
Hi Trevor, thanks for your comment. This part focus more on ASP.NET Identity features and using JWT instead of default access token format, I recommend you to use JWT but the other is the same.
Hi Taiseer,
I’m following this tutorial, and getting this error when submiting this url “api/accounts/create” (with postman) :
{
“message”: “An error has occurred.”,
“exceptionMessage”: “La référence d’objet n’est pas définie à une instance d’un objet.”,
“exceptionType”: “System.NullReferenceException”,
“stackTrace”: ” à AspNetIdentity.WebApi.Controllers.AccountsController.d__a.MoveNext()
(…)
}
It’s an Internal Server Error (500).
La référence d’objet n’est pas définie à une instance d’un objet == Object reference not set to an instance of an object
(I don’t know how to translate this)
Make sure that the model for “Create User” has no null properties.
Thank you for your quick answer.
You were right, the “CreateUser” funtion was called with a null property.
I cheked it :
public async Task CreateUser(CreateUserBindingModel createUserModel)
{
if (createUserModel == null)
{
return Ok(“CreateUserModel is null”);
}
// it stops here.
I have to change this value, but i don’t know where…
Maybe it’s unfinded ?
What can i do ?
i am also getting the same …. please help resolve>?
“message”: “An error has occurred.”,
“exceptionMessage”: “Object reference not set to an instance of an object.”,
“exceptionType”: “System.NullReferenceException”,
“stackTrace”: ” at Learning.Web.Models.ModelFactory.Create(ApplicationUser appUser) in c:\\Applications\\eLearning.WebAPI-master\\eLearning.WebAPI-master\\Learning.Web\\Models\\ModelFactory.cs:line 36\r\n at Learning.Web.Controllers.AccountsController.d__6.MoveNext() in c:\\Applications\\eLearning.WebAPI-master\\eLearning.WebAPI-master\\Learning.Web\\Controllers\\AccountsController.cs:line 75\r\n— End of stack trace from previous location where exception was thrown —\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter
1.GetResult()\r\n at System.Threading.Tasks.TaskHelpersExtensions.d__3
1.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()\r\n at System.Web.Http.Controllers.ApiControllerActionInvoker.d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter
1.GetResult()\r\n at System.Web.Http.Controllers.ActionFilterResult.d__2.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()”}issue
I was getting this error too… then I realised that its a “POST” method. I needed something to post didn’t I! D’oh!
I used Postman,
selected BODY (Authorization | Headers(0) | Body | Pre-request script | Tests),
selected RAW (form-data | x-www-form-urlencoded | raw | binary)
selected the type as JSON(application/json) – dropdown menu next to “binary”
Then I typed the object into the box below :
{
“Email”: “”,
“UserName”: “”,
“Password”: “”,
“ConfirmPassword”: “”,
“FirstName”: “”,
“LastName”: “”
}
Hope that helps!
Thanks for sharing this. Sure it will help!
What about logging out a user? Would I use the RemoveLoginAsync and pass in the appropriate information?
Never mind, I just realized RemoveLoginAsync is part of the UserManager and don’t want delete the user. I believe the best approach would be to have my Angular application clear out the token when the user logs out, correct?
This is for removing social identity account link, and there is no way to remove/expire self contained access tokens. All you need to do is to clear it from your client application and leave the token until it expires.
Hi!
First of all thanks for this great tutorial, it’s very helpful, but I have a problem that I couldn’t resolve and maybe you can point me in the right direction.
My problem is with the step 4, because my DB is already created, I mean, I have another architecture, and I would like to us that and not the one proposed or auto-generated by your suggested code.
So, how could we adapt this to use our existing db structure and stored procedures? Is that possible?
Thanks and Regards
Hi, you are welcome, glad that post is useful
Well you need to take a look at how to add ASP.NET Idenety to existing DB, maybe this video help, but I never try it my self yet.
Could you please provide sample code for “Log Out”?
Just 1 question. Do I need to enable something in order to not allow or to throw an error when trying to create a user with an email address that already exists in the Db? Right now I am able to create user with same email address that already exists in the Db. Though, it doesn’t allow for same Username, without me enabling something.
Thank you for sharing your brain to us.
-Lester
I guess you need to configure under UserValidator property in class ApplicationUserManager as here https://github.com/tjoudeh/AspNetIdentity.WebApi/blob/master/AspNetIdentity.WebApi/Infrastructure/ApplicationUserManager.cs
It’s already configured to require unique username and email.
Thank you Taiseer. Yes, read it from Part 2. I guess default for Username is unique while Email is non-unique. Thumbs up!
Hi. the code is working on my machine. however got this error message while querying against http://beewestwebapi2.azurewebsites.net/oauth/token.
error:
XMLHttpRequest cannot load http://beewestwebapi2.azurewebsites.net/oauth/token. No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://localhost:50453′ is therefore not allowed access. The response had HTTP status code 400.
client:
$scope.login = function () {
//alert($scope.userName + ” “+ $scope.password);
var req = {
method:’POST’,
url: ‘http://beewestwebapi2.azurewebsites.net/oauth/token’,
//url:’http://localhost:55651/oauth/token’,
header: {
// ‘Content-Type’: ‘application/x-www-form-urlencoded’
},
data: {
username: $scope.userName,
password: $scope.password,
grant_type:’password’
}
};
$http(req)
.success(function (data,status) {
$scope.info = data+” “+status;
})
.error(function (data, status) {
$scope.info = data + ” ” + status;
});
};
any idea pls?
Thanks
resolved. the corrected query should be:
var req = {
method:’POST’,
url: ‘http://beewestwebapi2.azurewebsites.net/oauth/token’,
//url:’http://localhost:55651/oauth/token’,
headers: {
‘Content-Type’: ‘application/x-www-form-urlencoded’
},
data:’username=xxx%40gmail.com&password=yyy&grant_type=password’
//data: $.param({
// username: $scope.userName,
// password: $scope.password,
// grant_type:’password’
//})
};
You didn’t configure CORS correctly so you can’t it from JS app, it should be working from PostMan, so try to read the article again and follow how I\m configuring CORS.
How do I write the tests?
This is an excellent article, very much appreciated.
Glad to hear it was useful 🙂
Awesome posts, Taiseer. I’m running into an issue that probably many others have had before me. On my windows 8.1 machine, I’ve installed Postman (now a standalone) and the interceptor (still in Chrome). Looked for your blog entry on using that but haven’t found it yet. I’m assuming I have to run the owin server before I can access the identity app with Postman. So to begin in VS I start the app using the Chrome client. What Chrome gets back is a 402.14 Forbidden response. The boilerplate solution provided is to go to the IIS Express directory and run appcmd. But when I use %systemroot%\system32\inetserv\appcmd in that directory windows says appcmd is not recognized as an internal or external command. Of course if I try to run it without the path it says the same thing.
The error seems to be thrown in AccountController when it tries to create a new ApplicationUser. Not sure why it would do that _before_ a login screen was displayed.
Any thought readers have would be appreciated.
Hi Chris,
I’m not sure if I got your question correctly, PostMan is REST client like Fiddler where you can compose HTTP requests from, it is not related to Web API or Owin at all.
You need run this project on IIS express or normal IIS and there is no UI at all for the API, once you deploy the application to IIS you start use PostMan, fiddler, etc.. to issue HTTP requests to the API and get results from it.
Hope this clarifies your concern.
Thanks for these sample solutions – these are helping a lot.
I had a question on how to extend the ASP.NET Identity the right way for adding an organizational structure.
So, we do have accounts, roles etc. however they also need to belong to organizations (or groups). It is a SaaS application with multiple tenants that we are hosting on azure. So, we can either:
1) Structure the organization to accounts in the “Resource Server” as opposed to the “Auth/Identity Server” OR
2) Use AD
3) Extend the “Auth/Identity Server” to have Organizations/Groups in them.
I’d be curious to hear thoughts on the above options.
Thanks in advance.
Hi Taiseer,
Great post and series in general. I found it very helpful.
I’m interested in using ASP.NET Identity / WebApi from an Angular client.
Any update on when you might have the final part of your series posted?
Best,
TC
There is a CORS exception when I try to sign up in the demo application http://ngauthenticationweb.azurewebsites.net/#/signup . This happens for me as well when I deploy Web Api to Azure . In local it works fine. Please help.
I’m not facing any issue when I try to register from the demo website. Can you try again and let me know if there is issue happening.
Hi Taiseer I have this issue only in my office network, that too across all browsers and all of my colleagues system. but doesn’t happen at home. Very strange (and confused),any guess?
gotcha Firewall causes the issue. http://jeffmcmahan.info/blog/firewall-causes-cors-to-fail/
I wonder is _AppUserManager on BaseApiController have ever initialized? Or It just wait to be implement in future?
Anyway thanks again for this nice tutorial series.
I followed your tutorial a couple of times but still I get a 404 when I try to test requests. I see that the update-database command created the database without any errors and the seed method was called(I see the first user record in the database). However, I continuously see 404 and the application can’t find my api requests. I even tried by starting with a web api project.
The api MVC routes work but not WebApi routes. Also the owin startup class is called as expected and I have decorated the correct RoutePrefix for class and Route attributes for the Web Api methods in the AccountController, but still no dice.
I have tried to get the application to work both using Local IIS as well as IISExpress.
On my last try I got an error:
“ExceptionMessage”: “Value cannot be null.\\\r\\\nParameter name: context”
So, I stopped in the debugger and found that “Request.GetOwinContext()” returns null. Hopefully, this is enough information for someone to lend a hand.
Thanks!
Hi Jamie,
I feel that you are mixing between Owin middleware and the traditional routes registration, that’s why your Web Api routes are not configured correctly and not being registered. Could you please just download the sample code and try to run it directly without adding MVC components, once you make sure that the Api is working correctly you can add Mvc NuGet packages. It is hard to tell where is the issue happening because there is lot of moving parts.
Hi, what about OpenId? Can it be used with or in the place of ASP.NET Identity?
Hi, when is “AngularJS Authentication and Authorization with ASP.NET Web API and Identity – Part 6” coming up? I just cant wait?
Thanks
Compliments for the post.
I have just one question:
How is possible, in your opinion, secure the method CreateUser that currently it [AllowAnonymous]
[AllowAnonymous]
[Route(“create”)]
public async Task CreateUser(CreateUserBindingModel createUserModel)
Of course AllowAnonymous is correct, because the user still doesn’t exist in our database.
But I am thinking that everyone can “call” this method infinite time in a loop destroying for instance our database.
With cookie session we have more “protection” for these kind of attacks.
Is there any best practice for prevent these situations?
Thank you,
Davide
Hi Davide,
Even if you are using cookies not tokens, you will not have a cookie for anonymous users, so this scenario will happen too, you can think of using captcha or Api rate limiter to make sure that user is not sending for example more than 2 requests per 5 seconds.
Thank you for your reply. Great article great work.
Cookie. Vs tokens and eventually single sign on are the hot topic in London. Your article as far I can see is one of the milestone for understanding tokens and web.api
Hi Taiseer, I would like to thank you for this great article!
You have no idea how much you´ve helped me!
I have followed it up to Part 5 and every thing works smoothly.
I would just like to add a footnote for those starting: Turn off you firewall, because many of the problems that I read above seem to me to be related to it, as it happened to me.
Thanks Carlos for your comment, always happy to help, and thanks for your note!
hey.. really nice article. i followed ur tutorial. but wen i test it through fiddler m receiving an empty object in createUser method.
Hi, make sure your request body is identical to mine, if not that’s why the serializer is not able to parse the request payload and cast it to CLR object.
Would this still work with MVC6 and ASP.NET5? Now that WebAPI and MVC are merged, I’m wondering if any of this (great) series of article is still valid?
Just a little FYI for your readers if the Seed() method does not appear to add the user to the database:
If you attempt to create the user with a password that is too short or otherwise does not meet the minimum password requirements, then the Seed() method will silently fail to generate the user (even when using the -verbose flag on update-database). The simple solution is to ensure that your password is long enough.
E.g.: This will fail to create the user:
manager.Create(user, “demo”);
This, however, will work:
manager.Create(user, “demoPassword”);
That is right, you have to set a password which meets the password policy defined in the ApplicationUserManager class. Thanks for sharing this.
Cheers Taiseer
Looking forward to Part 6 !
hello I enjoy your article. It appears to be concise and exactly what I was searching for.
However, I cannot simply execute ‘enable-migrations’ in PM Console.
I get the error:
System.ArgumentException: The parameter is incorrect. (Exception from HRESULT: 0x80070057 (E_INVALIDARG))
is there something I missed?
thanks,
Figured it out. I mistakenly created a ‘web site’ and not a ‘web application’.
Thanks again for the great article.
m.
Glad to hear it is working now.
I’m not sure what is this error is, did you try searching it on stack overflow?
Excellent article. Is there any news on part 6? Can’t wait to get stuck in.
Hi Taiseer. Great article!
Just one thing. Is it possible to use my custom database for users instead of this default one AspNetIdentity?
Thanks.
You can use any DB store you want, Identity system can be configured to use different stores, this post will help you for sure.
Thanks. The only thing is that I use Microsoft SQL Server, but I guess approach is similar.
Hi Taiseer. Great article!
Just one question. How hard is it to use users table in custom MsSQL database instead of this from default identity db?
Thanks.
Hi Josip,
Are you looking to use ASP.NET Identity on top of MySql database or you want to use your own tables directly?
I am looking to have users, roles and all authentication tables as a part of my database (running on the Microsoft SQL Server) alongside with other tables used in the app.
Great tutorial bro, but i am stuck at step 4, i get an error when i am trying to enable migration; following is the error:
An error occurred accessing the database. this usually means that the connection to the database failed. I Add the connection string exactly as u mentioned in the Web.Config file.. do you have any idea why iam getting this error?
Just forget my Question bro, i had to install SQL Express 🙂
Glad you found the solution 🙂
Hi Taiseer
Have you tried any of this with ASP.NET V5? I’m busy trying to convert my code but am running into issue after issue. I’m wondering if you’ve tried it yet?
From what I can tell, a lot of the assemblies have changed and are still changing, so maybe it’s not a good idea to try using it now. Any thoughts?
Thanks
Sean
Hi,
Do not try, ASP.NET 5 is a totally different platform, many things have changed especially when it comes to authentication and authorization, as well there is no middle ware for generating tokens until now. Web Apis will understand bearer tokens.
If you are referring to ASP.NET identity 3.0 then I didn’t play with it yet, so I have no comments yet.
Do you think you might have an update with ASP.NET 5 any time soon? I have a new project that I might try to move to 5 over the next 3-6 months depending on the release. Still trying to get better handle on ThinkTechture with ASP.NET Identity…Good example/walk through. Really helped me out. Thanks again.
Got any good example/walk through for ThinkTechture with ASP.NET Identity?
Sorry no, but the official documentation for ThinkTecture is pretty good. You can follow up with the it easily. As well there are many Plural Sigh courses covering using ThinkTecture in deep details.
Hi Taiseer,
Really thanks for your tutorials. Why didn’t you use repository pattern approach for CURD operation in this post? you have implemented previously in Token Authentication post?
Hi Arooran,
Thanks for your comment, there is really no reason, just for the sake of keeping the post simple, repository pattern is better way to go.
Hi Taiseer
Thanks for the tutorial…great help!
I’ve few questions here..
1) How can we configure third party caching for tokens ?
2) integrate AFDS/LDAP with Identity, Any sample availble?
Adding one more question to the above..
How the token validation has been done in the above samples…
my use case is I want to cache the token and validate against to cache data….
Is asp.net Identity by default use cache for token(JWT) for further requests????
Thank you for the post.
In the Seed Method is there a reason for not using the context parameter to add the user to the database ?
Thanks.
No reason, you can use the context for seeding too.
What if we already have a user database?
What do you mean Mark? Can you elaborate more?
Hi!
I think I know what he means.
What if we already have a database, and we want to create the Identity Pattern around it? Do we have to create all the fields in each table? (User, for example, has tens of fields: Phone Number, Email Confirmation etc., fields I may not need)
This is what I’m looking for as well…
Hi Taiseer. Following your code I am getting an error “Store does not implement IQueryableUserStore” when I try to retrieve Users using this method GetUsers() in Account controller.
Thanks.
Hi Taiseer,
What is the difference in the API between this series and the one in https://bitoftech.net/2014/06/01/token-based-authentication-asp-net-web-api-2-owin-asp-net-identity/
Thanks
Hi Taiseer,
Any idea why in the Seed method, when I tried to initialise the database with two users e.g. call manager.Create(user1, “password1”); manager.Create(user2, “password2”); it somehow only created the first user in the db?
Oh great series of posts by the way; this is exactly what I need though just get started trying myself.
Thanks.
Happy to hear that posts were useful, to be honest I have no clue why only one user has been created, did the second once throws an exception or just didn’t create it?
Another thing is I think you meant to cache the AppUserManager in the basecontroller class e.g. something like
protected ApplicationUserManager UserManager
{
get { return _userManager ?? (_userManager = equest.GetOwinContext().GetUserManager()); }
}
hi, i made step by step project for web api that you posted in this post, i am not able to hit controller methods in Account controller. do i have to add routing class or anything i am missing?
Hi< please download the Repo from GitHub and compare with your project, there should be something missing or different.
is part 6 available ?
not yet, sorry about this!
Namespaces would have been nice. Spent a lot of time looking for the proper namespace for using statements.
Hi Mike, usually Namespaces will be imported in the top of the file, always refer to the GitHub codebase for complete working example.
Taiseer
Thanks for this tutorial; it’s hard to find a good guide that explains all of this without relying on the premade templates in VS.
I noticed the GET request for all users at the end of part 1 lists claims and roles in your example, and the GitHub project has those controllers in place. Did I miss an important step in this part, or are those pieces included later?
Thanks again,
Joe
Hi Joe,
Happy to hear that posts were comprehensive and useful.
Maybe I missed something in the steps, but always refer to the GitHub for the updated code.
Thanks
Hi,
I had downloaded this project from Github its build successfully, when i send the request from PostMan my breakpoints hit on Account controller CreateUser method by using URL “http://localhost:59822/api/accounts/create”, but my CreateUser Method parameter “createUserModel” is null and received following exceptions
{
“message”: “An error has occurred.”,
“exceptionMessage”: “Object reference not set to an instance of an object.”,
“exceptionType”: “System.NullReferenceException”,
“stackTrace”: ” at AspNetIdentity.WebApi.Controllers.AccountsController.d__3.MoveNext() in C:\\AspNetIdentity.WebApi-master\\AspNetIdentity.WebApi\\Controllers\\AccountsController.cs:line 72\r\n— End of stack trace from previous location where exception was thrown —\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter
1.GetResult()\r\n at System.Threading.Tasks.TaskHelpersExtensions.d__3
1.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter1.GetResult()\r\n at System.Web.Http.Controllers.ApiControllerActionInvoker.d__0.MoveNext()\r\n--- End of stack trace from previous location where exception was thrown ---\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter
1.GetResult()\r\n at System.Web.Http.Controllers.ActionFilterResult.d__2.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter`1.GetResult()\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()”}
I did not see any fields on PostMan where i fill data. Is there i missing something?
Hi, you request model is empty, check the request fields you are sending and make sure it matches the User Model.
I had the same problem and still have it.
Hi Abu, I found what is wrong here. In the AccountsController you have the method:
public async Task CreateUser(CreateUserBindingModel createUserModel)
And if you were using an MVC form it would be ok, but if you are using Postman you have to modify the method something like this:
public async Task CreateUser(string Email, string Username, string FirstName, string LastName,
string Password, string ConfirmPassword)
In order to function well. I did this change and when my breakpoint stops the program I can see the values send via postman in the parameters of the method.
I hope I was clear in my explanation.
Thanks for sharing your response, Guillermo 🙂
Greet post, thanks!
How can get token from Post? That’s why get call is failing 401
Great Post. Thanks
But Get call is failing 401 [Authorization has been denied for this request]. How can get token from post?
You are welcome, I really do not know what si wrong at your end, pleae download the repo and compare your code with it. It is working perfectly at the repo.
Great post, thank you!
Get the same error when calling http://localhost:59822/api/accounts/users in PostMan. I downloaded the repo and compiled from there.
That is strange, can you check that you are using the same NuGet packages I used, then you can upgrade them and trace if the error was due using a newer version of NuGet packages?
Greetings,
Thank you very much for this useful tutorial.
I followed this part of your tutorial step-by-step. However, I have tried testing the methods added to the API especially the ‘Create’ method using PostMan, but creating a user didn’t go well. I am getting the following error and I don’t know why.
{
“message”: “An error has occurred.”,
“exceptionMessage”: “Object reference not set to an instance of an object.”,
“exceptionType”: “System.NullReferenceException”,
“stackTrace”: ” at AspNetIdentity.WebApi.Controllers.AccountsController.d__3.MoveNext() in D:\\Practice\\AspNetIdentity\\AspNetIdentity.WebApi\\AspNetIdentity.WebApi\\Controllers\\AccountsController.cs:line 59\r\n— End of stack trace from previous location where exception was thrown —\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Threading.Tasks.TaskHelpersExtensions.d__3`1.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ApiControllerActionInvoker.d__0.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Controllers.ActionFilterResult.d__2.MoveNext()\r\n— End of stack trace from previous location where exception was thrown —\r\n at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)\r\n at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)\r\n at System.Web.Http.Dispatcher.HttpControllerDispatcher.d__1.MoveNext()”
}
Could you please tell me why I am still getting this error?
Hi Mohammed,
Put a breakpoint inside the create method and check if the UserModel is filled correctly and it is not null, maybe it is not binding correctly when you set those properties.
Hi Mohammed, I found what is wrong here. In the AccountsController you have the method:
public async Task CreateUser(CreateUserBindingModel createUserModel)
And if you were using an MVC form it would be ok, but if you are using Postman you have to modify the method something like this:
public async Task CreateUser(string Email, string Username, string FirstName, string LastName,
string Password, string ConfirmPassword)
In order to function well. I did this change and when my breakpoint stops the program I can see the values send via postman in the parameters of the method.
I hope I was clear in my explanation.
One more thing, can I use this Web API with my ASP.NET WebForms project? I have an existing project and I would like to include this to it.
Yup you can, you need to install the needed NuGet packages and you are good to go. Yet I don’t recommend you going this path unless there is no other option and you have to mix both projects together.
Hi what is AngularJSAuthentication.ResourceServer doing in this scenario ? and how do you start all applications at once for debugging purposes ?
Hi, you can start multiple projects at one time by right click on solution, properties, then select “Multiple Startup Projects”
Hi Taiseer, this is a great blog, I’m really new about web api and I want to lean more about it, also I want to do all yours tutorial becouse it seem great, but in this moment I have a problem when I do this : enable-migrations and add-migration InitialCreate and the error is the follow:
A network-related or instance-specific error occurred while establishing a connection to SQL Server. The server was not found or was not accessible. Verify that the instance name is correct and that SQL Server is configured to allow remote connections. (provider: SQL Network Interfaces, error: 26 – Error Locating Server/Instance Specified)
I don’t why, I need Sql Server 2012 Express for example?, can you help? please. sorry for the bad English.
Hi Ernesto, thanks for your message, can you check the connection string you used in webc.config, it seems you are not able to connect to the SQL express instance. If this didn’t work there are many other reasons for this, better to check answers on StackOverflow as this is a common issue.
Hello Taiseer Joudeh,
I like your Post very much, I always like to learn with step by step approach it always gives great understanding.
I am having one doubt.
Here you extended BaseAPIController with API Controller class so it became WebAPI Application and used WebAPI packages.
I want to implement same functionality but to my web application. I want to implement ASP.Net Identity with cookie based authentication.
Can i use it in same way?
Your posts are really good. Thank you for helping
Hi Nirav,
yes you can do this with cookies authentication, the ASP.NET Identity WebSite is full of a useful resource to implement this
Hi Taiseer,
Great series, and so needed …
I am running into an issue. I am trying to AppUserManager.AddClaimAsync(…) from within a WebApi controller but data is not persisted (saved) to DB unless Request.GetOwinContext().Get().SaveChanges() is called explicitly. Have you seen such behavior?
I see that Seed in DB Migration logic does not SaveChanges() explicitly … so where is difference coming from?
Thanks
Hello Taiseer Joudeh,
Thanks for a good tutorial.
I have tried testing oauth/token from ionic project, but i’ve got this error.
XMLHttpRequest cannot load http://localhost:10315/oauth/token. Response to preflight request doesn’t pass access control check: No ‘Access-Control-Allow-Origin’ header is present on the requested resource. Origin ‘http://localhost:8100’ is therefore not allowed access. The response had HTTP status code 400.
How can i implement a cross-origin HTTP request.
Taiseer Joudeh,
I just make a little modify you source code and my ionic project work well.
In Startup.cs at Configuration i move
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
to the first line and at CustomOAuthProvider.cs
at GrantResourceOwnerCredentials i comment this two line
//var allowedOrigin = “*”;
//context.OwinContext.Response.Headers.Add(“Access-Control-Allow-Origin”, new[] { allowedOrigin });
but i have one more question, because i’m new in asp.net.
There is a sample for web admin tools for asp.net identity?
Hello Taiseer,
What a fantastic post, a really great help.
One thing I am struggling with is that I would like to find a user by a different field value such as AppUserManager.FindByPhoneNumberAsync(Id). However I am struggling to work out how to extend the AppUserManager. Any help would be very gratefully received.
Thanks
Thank you so much Taiser for this post, actually it fills the gaps that I had in Asp.Net Identity.
Keep Going …
Thank you Nadeem for your comment. appreciate it.
Test Comment
Hi,
First of all, this is a good article and it helps me a lot. I am now implemented it in my API project. now I have a requirement to integrate to some external authentication specifically LinkedIn but having trouble implementing it.
Do you have any leads or info that would help me?
Thanks!
Hi Calma,
Could you please check this URL, it might help.
Hi Taiseer Joudeh,
Thanks for your tutorial. It is very useful for a beginner like me.
I am looking for next tutorial: AngularJS Authentication and Authorization with ASP.NET Web API and Identity – Part 6
Thanks.
Thanks for your message. I need to update this soon.
Hello Taiseer,
Thanks for the excellent tutorial. I really appreciate for all your efforts.
Actaully, I am eagerly waiting for the last section – “AngularJS Authentication and Authorization with ASP.NET Web API and Identity – Part 6”
Thanks,
Hi
Thanks for your tutorial. It is very useful for a beginner like me.
Thanks.
You are most welcome, glad it was useful 🙂
Has anyone been able to get Refresh Tokens to work with this more recent tutorial (ASP.NET Identity 2.1 with ASP.NET Web API 2.2 (Accounts Management) ? I have tried following the earlier tutorials that included Refresh Tokens but I have not been able to figure out how to apply Refresh Tokens to this newer tutorial.
The older tutorials make use of a “AuthRepository” class but the newer version here seems to make use of “CustomOAuthProvider” class. I have not been able to figure out how to integrate the methods needed for Refresh Tokens into the CustomOAuthProvider. Any help someone could offer would be most welcome. Thank you!
I hope my email answer was sufficient 🙂 Let me know if you need further help.
Taiseer Joudeh,
I too had the same difficulty. Can you please post the solution in a blog post or send the same answer by email. Thanks.
I forwarded the answer to your email, I hope it is the right one you are looking for. Thanks.
Hello,
may I also ask you to forward me the mail as I am also struggling with that part.
Thanks,
Oliver
Hi Taiseer Joudeh,
Really love your tutorials! They help so much! I’m also wondering about how to implement refresh tokens. Would you be so kind to forward me that email as well?
Thanks! Please keep this up!
Hello Frank, did you take a look at the previous posts where I cover refresh tokens?
I would also like to know about the refresh ability specifically in how to use it to deny access to a user that may have been rejected after the token was originally granted.
Hi,
I am trying to convert to project to VB but I am struggling at the point where the Startup Method ConfigureOAuthTokenGeneration is being executed.
I converted the C# Code
app.CreatePerOwinContext(ApplicationDbContext.Create);
app.CreatePerOwinContext(ApplicationUserManager.Create);
to
app.CreatePerOwinContext(Function() ApplicationDbContext.Create)
app.CreatePerOwinContext(Of ApplicationUserManager)(Function() ApplicationUserManager.Create)
but when the server starts, it complains about the two parameters “options and “Context” not being present.
Which is correct, the ApplicationUserManager Class has only one signature for the method “Create”, which needs options and Context as parameters.
public static ApplicationUserManager Create(IdentityFactoryOptions options, IOwinContext context)
What am I doing wrong?
Thanks,
Oliver
Found solution by myself. For reference if someone else gets into this:
app.CreatePerOwinContext(Function() ApplicationDbContext.Create)
app.CreatePerOwinContext(Of ApplicationUserManager)(Function() ApplicationUserManager.Create)
has to be
app.CreatePerOwinContext(AddressOf ApplicationDbContext.Create)
app.CreatePerOwinContext(Of ApplicationUserManager)(AddressOf ApplicationUserManager.Create)
Great tutorial. Thank you!
You are welcome Pat, happy to help!
I just ran into a scenario that I have not seen mentioned previously so I thought I’d ask about it.
If the username field contains an email address, neither of the functions GetUserByName or GetUserById are called. I receive a 404 error. I tried encoding the email field and it still returned a 404.
Just curious if anyone else has run into this previously and there is a known work around.
Thanks for the article it helped me greatly to quickly understand oauth.
Hello Mike,
What do you mean that method “GetUserByName” is not called? This is something you have control over, right? I do not think you need to encode anything as you are doing form post when you login and your are not sending the email in the URL, right?
I tried your first part, word for word, but I am getting a 404 File not Found error when I try to use your testing links. I am sure I am using the correct localhost port.
I put break points thought out the project and NONE of them get hit when I attempt to call the API though Chrome app Postman.
So what have you missed? Do we need a global.asax file to kick off the API?
Hi, I am facing this type of error. I tried to resolve it, but I can’t.
Error ‘Microsoft.Owin.IOwinContext’ does not contain a definition for ‘GetUserManager’ and no extension method ‘GetUserManager’ accepting a first argument of type ‘Microsoft.Owin.IOwinContext’ could be found (are you missing a using directive or an assembly reference?) C:\AspNetIdentity\Controllers\BaseApiController.cs
After resolving above error I am facing this error
Could not load file or assembly ‘System.Web.Http, Version=5.2.2.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35’ or one of its dependencies. The located assembly’s manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)
Hi!
My issue is same this link:
http://stackoverflow.com/questions/19764233/merge-mydbcontext-with-identitydbcontext
Please help me!
Thank you so much!
Hi Taisser,
how can i assign user to some role during account/register api?
Thanks for this great post. Can you tell me the difference with your previous web api 2 + angular series? For my new projecr, which series should i follow?
Great article! I have a question. If it’s possible to use a user table with its own name instead of AspUser? Thanks.
Sure you can do this, you can use any structure you want and you can get rid of ASP.NET Identity at all
Hi Taiseer, Can you work on angular js application having both individual accounts and organisational accounts authentication. So that users can login with their personal(custom) accounts and Microsoft accounts(Microsoft active directory). Thank you.
This is a great series. The examples work as advertised using the packages specified and provide ample background for troubleshooting breaking changes in the future.
Thanks for the article. I am getting the error “value cannot be null” on Request object in BaseAPIController in the line “get { return _appUserManager ?? Request.GetOwinContext().GetUserManager(); }”
Hi Taiseer,
Please help i am getting the following error
The following errors occurred while attempting to load the app.
– No assembly found containing an OwinStartupAttribute.
– No assembly found containing a Startup or [AssemblyName].Startup class.
To disable OWIN startup discovery, add the appSetting owin:AutomaticAppStartup with a value of “false” in your web.config.
To specify the OWIN startup Assembly, Class, or Method, add the appSetting owin:AppStartup with the fully qualified startup class or configuration method name in your web.config.
Hi,’
I just followed everything, owinstartup error resolved deleting and adding startup class
I am not getting any build error, only runtime error. I have created couple of project but both the project same. Can you check please.
Thank you.
Hi,
I am getting the following error.
Most likely causes:
The directory or file specified does not exist on the Web server.
The URL contains a typographical error.
A custom filter or module, such as URLScan, restricts access to the file.
Hi,
After a long struggle, i issue solved, due to [RoutePrefix(“api/accounts”)] not added in Account controller.
Thank you
Sorry for not replying earlier, happy to hear all is working as excepted now.
You are the man, it’s a rocking tutorial thank you so much.
You are welcome Waddah, thanks for your comment 🙂