C# – ASP.NET Web API and ASP.NET Identity

We got to know with Google, Flickr and Twitter API service in some of my previous posts. All these provide us an authentication scheme so that we can authenticate ourselves and get permissions to 3rd party resources. We have also created our own REST web services by using ASP.NET Web API for publishing data to our clients. However, until now, our web services are all simply public to everyone. Everyone can use them, even our competitors (if there’s any) 🙂 That’s not good and I also received questions if a web service can be protected by using authentication. So in this post I would like to make an introduction about new technology of Microsoft : The ASP.NET Identity. We’ll build a very simple REST web service with ASP.NET Web API and ASP.NET Identity from Visual Studio template and try to access it from a .NET client.

The ASP.NET Identity system is designed to replace the previous ASP.NET Membership and Simple Membership systems. It includes profile support, OAuth integration, works with OWIN, and is included with the ASP.NET templates shipped with Visual Studio 2013.

1. Prerequisites

– ASP.NET Identity is a new identity management system released in Fall of 2013. The current version is 2.0.1 released on May 2014 and should be directly integrated with ASP.NET MVC and ASP.NET Web API template. However the template of these kind of projects are somehow still not updated or not available for all Visual Studio versions. I’m using Visual Studio 2013 Update 2 and my templates are all updated (means that I can use ASP.NET Identity without problems). So if you have another versions of Visual Studio, just follow the steps, if you are stuck at any, that means your templates aren’t updated or your Visual Studio isn’t supported. If that’s your case, then try to search in Internet for solution.
– ASP.NET Identity uses Entity Framework for creating database tables. I’ll also activate Code First feature and Migrations in this sample. If you have no idea what they are, then follow this link to get an overview Entity Framework Code First Basic FAQ
– Last thing, if you don’t even know how to subscribe a public REST web service, then this post is maybe a good start How to consume ASP.NET Web API RC with HttpClient?. Be ready with basic knowledges before getting know with another basic one. 😉

2. ASP.NET Web API with Individual Accounts

As I mentioned above, for our sample, we need a web service and a client. In this section we’ll create a REST Web API which supports authentication. Only authenticated users can access the resources. An anonymous access will get unauthorized error code when trying access data. The web service can be made in some simple steps below.

– Start Visual Studio –> Select Web template –> ASP.NET Web Application. Give your project a name and click on Next

Create ASP.NET Web Application

– Select Web API as your template and Change Authentication to Individual User Accounts

Web API and Individual User Accounts

– After solution was created, go to Package Manager Console, be sure that your project is currently selected and execute Enable-Migrations

Enable-Migrations

– If Migration feature is successfully enabled, you’ll get a new folder named Migrations in your project

Migrations folder

– Under this folder, go to Configuration class and set AutomaticMigrationsEnabled to true

public Configuration()
{
	AutomaticMigrationsEnabled = true;
}

– And that’s all. We’re finished with creating a simple REST web service with authentication feature.
– The Migration feature and AutomaticMigrationsEnabled are set because I want to be sure that the web application will create necessary tables when it starts up. I need this feature for hosting a sample web service for you later. Without enabling this feature I have to copy tables from my local to server because I use local db for debugging and remote SQL Server for publishing. Visual Studio will create tables during debugging but the web application won’t. Unless we explicitly tell him to update database, he won’t do it standard by himself.
– So now let’s run the sample by pressing F5. A successful build will bring us a simple web site like image below

Sample ASP.NET Application

– If we try to access a protected resource through browser, for example

http://localhost:1952/api/values

we’ll get an unauthorized error Authorization has been denied for this request because the ValuesController is protected by this [Authorize] attribute. This attribute will deny all anonymous accesses and ensures only registered users can get through it.

[Authorize]
public class ValuesController : ApiController
{
}

– After some simple steps with template of Visual Studio, we have now a REST web service supporting authentication. The resource protected by Authorize attribute requires a valid identity for accessing it. To consume this resource, the client has to own a valid Token which is only supplied for registered users. How can this Token be generated will be discussed in next part. I also host this sample web application online at following link

http://aspnetwebapiandaspnetidentity.apphb.com/

The sample client will connect to this sample one instead of localhost. The source code of this online sample one is as same as the source code of link at the end. I made this online one for later use (for example demo with Android) and just in case that you can’t bring the source code work at your local host, you can still use this online one for testing the client.

3. .NET client

– We’ve now a REST service supporting authentication and the resources are protected. To get access to resources, we need a valid Token which is only available to registered users. So to get this token we have to register user, get Token with registration data (email, password) and use that Token for accessing resources. The Token is used not only for accessing normal resources but also for querying user info and change user password. We’ll try all these functions in demo like code listing below

private static void Main(string[] args)
{
	IntializeHttpClient();
	RegisterAndGetTokenThenValues().Wait();
	GetUserInfo().Wait();
	ChangePassword().Wait();
	LogOut().Wait();
	Console.ReadLine();
}

3.1 InitializeHttpClient

– Like other ASP.NET Web API services, this service can be consumed by HttpClient class (from Nuget Package Microsoft ASP.NET Web API 2.2 Client Libraries). We just need to initialize an instance of HttpClient with URL of our service

private static string serviceUrl = "http://aspnetwebapiandaspnetidentity.apphb.com/";
private static void InitializeHttpClient()
{
	httpClient = new HttpClient();
	httpClient.BaseAddress = new Uri(serviceUrl);
}

3.2 Register user, get token and use token

– After initializing a HttpClient instance, we can now register user, get token and use token for authenticated request. For more information about content for negotiating you can read more in source code of service at class AccountController and StartUp

3.2.1 Register user

– Location of definition : AccountController –> Register
– URL : api/Account/Register
– POST object : RegisterBindingModel

public class RegisterBindingModel
{
	[Required]
	[Display(Name = "Email")]
	public string Email { 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; }

	[DataType(DataType.Password)]
	[Display(Name = "Confirm password")]
	[Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
	public string ConfirmPassword { get; set; }
}

3.2.2 Get Token

– Location of definition : Startup (File name: Startup.Auth.cs) –> ConfigureAuth
– URL : Token
– POST object: FormUrlEncodedContent

new FormUrlEncodedContent(
	new[]
		{
			new KeyValuePair<string,string>("grant_type","password"),
			new KeyValuePair<string,string>("username",email),
			new KeyValuePair<string,string>("password",securePassword),
		}
));

3.2.3 Use Token to access resources

– HEADER : A request header with format of “Authorization : Bearer YOUR_TOKEN” has to be added to request

private static async Task RegisterAndGetTokenThenValues()
{
	Console.WriteLine("--- Register, Get Token and values ---");
	Console.WriteLine();

	Console.WriteLine("Step 1: Register...");
	reponseMessage = await httpClient.PostAsJsonAsync("api/Account/Register", new RegisterBindingModel() { Email = email, Password = securePassword, ConfirmPassword = securePassword });
	reponseContent = await reponseMessage.Content.ReadAsStringAsync();
	if (reponseMessage.IsSuccessStatusCode)
	{
		Console.WriteLine("Step 1: Register...Sucessfully");
		Console.WriteLine("Step 2: Get Token...");
		reponseMessage = await httpClient.PostAsync("Token", new FormUrlEncodedContent(
										new[]
											{
												new KeyValuePair<string,string>("grant_type","password"),
												new KeyValuePair<string,string>("username",email),
												new KeyValuePair<string,string>("password",securePassword),
											}
			));
		tokenModel = await reponseMessage.Content.ReadAsAsync<TokenModel>();

		if (tokenModel != null)
		{
			Console.WriteLine("Step 2: Get Token...Sucessfully");
			Console.WriteLine("Step 2: Token expires at " + tokenModel.ExpiresAt);
			Console.WriteLine("Step 3: Get values with token...");
			httpClient.DefaultRequestHeaders.Add("Authorization", string.Format("Bearer {0}", tokenModel.AccessToken));
			reponseMessage = await httpClient.GetAsync("api/Values");
			reponseContent = await reponseMessage.Content.ReadAsStringAsync();
			if (reponseMessage.IsSuccessStatusCode)
			{
				Console.WriteLine("Step 3: Get values with token...Sucessfully");
				Console.WriteLine(reponseContent);
				Console.WriteLine();
			}
			else
				Console.WriteLine(reponseContent);
		}
		else
			Console.WriteLine("Get Token failed with status code " + reponseMessage.StatusCode.ToString());
	}
	else
		Console.WriteLine(reponseContent);
}

The code listing above demonstrates exactly how the process works. A user can be registered with a POST to api/Account/Register with his email and password. After registering successfully, he can send a GET to Token with his email and password for requires a valid Token (use SSL for your service because password is sent as plain text in this step). A valid Token will be generated with expired date, that can be used for accessing any protected resources. Just be sure that you don’t forget to attach Token in request header in format of “Authorization : Bearer YOUR_TOKEN”.

3.3 Get user info, change password and logout

With a valid Token we can access protected ValuesController. We can use this Token for others like getting user info, changing password and logging out. Please note that changing password and logging out don’t make token invalid. Token is valid until it expired date. Logging out will clear your cookies and that makes only sense when you use ASP.NET Web API from website. In this case, it doesn’t have any effect on our token.

private static async Task GetUserInfo()
{
	Console.WriteLine("--- Get user info ---");
	Console.WriteLine();
	reponseMessage = await httpClient.GetAsync("api/Account/UserInfo");
	reponseContent = await reponseMessage.Content.ReadAsStringAsync();
	Console.WriteLine(reponseContent);
	Console.WriteLine();
}
		
private static async Task ChangePassword()
{
	Console.WriteLine("--- Change password ---");
	Console.WriteLine();
	Console.WriteLine("Step 1: Change password...");
	reponseMessage = await httpClient.PostAsJsonAsync("api/Account/ChangePassword", new ChangePasswordBindingModel() { ConfirmPassword = newSecurePassword, NewPassword = newSecurePassword, OldPassword = securePassword });
	reponseContent = await reponseMessage.Content.ReadAsStringAsync();
	if (reponseMessage.IsSuccessStatusCode)
	{
		Console.WriteLine("Step 1: Change password...Sucessfully");
		reponseMessage = await httpClient.GetAsync("api/Values");
		reponseContent = await reponseMessage.Content.ReadAsStringAsync();
		if (reponseMessage.IsSuccessStatusCode)
		{
			Console.WriteLine("Step 2: Token is still valid...Sucessfully");
			Console.WriteLine(reponseContent);
			Console.WriteLine();
		}
		else
			Console.WriteLine(reponseContent);
	}
	else
		Console.WriteLine(reponseContent);
	Console.WriteLine();
}

private static async Task LogOut()
{
	Console.WriteLine("--- Logout ---");
	Console.WriteLine();
	Console.WriteLine("Step 1: Logout...");
	reponseMessage = await httpClient.PostAsJsonAsync("api/Account/Logout", new { });
	reponseContent = await reponseMessage.Content.ReadAsStringAsync();
	if (reponseMessage.IsSuccessStatusCode)
	{
		Console.WriteLine("Step 2: Logout...Sucessfully");
		reponseMessage = await httpClient.GetAsync("api/Values");
		reponseContent = await reponseMessage.Content.ReadAsStringAsync();
		if (reponseMessage.IsSuccessStatusCode)
		{
			Console.WriteLine("Step 2: Token is still valid...Sucessfully");
			Console.WriteLine(reponseContent);
			Console.WriteLine();
		}
		else
			Console.WriteLine(reponseContent);
	}
	else
		Console.WriteLine(reponseContent);
	Console.WriteLine();
}

4. Conclusion

Publishing data over REST web service is mobile friendly and can be consumed in any platform. With ASP.NET Identity we can easily operate an identity management system for our web services. It’s pretty easy to use, can be applied to any system and provides useful fundamental functions. ASP.NET Identity also supports OAuth which isn’t in scope of this post, but I hope I can write another post about OAuth and ASP.NET Identity soon.

Source code : https://bitbucket.org/hintdesk/dotnet-asp.net-web-api-and-asp.net-identity

19 thoughts on “C# – ASP.NET Web API and ASP.NET Identity”

  1. Thanks. I can’t believe but there are very few examples regarding ASP.NET Identity for client side applications and specifically non-web applications that need to access a web service.

  2. @Dean Goddard: You’re right. The ASP.NET Identity is pretty new (it’s some months old) so there aren’t many articles. I’ll try to write some more posts about it.

  3. Great article, thank you.
    I’ll use you example to build my app.
    I just have one question, how could I send notification to the android application from the web api ?

  4. Great article. I tried to separate web api for authentication from web api for data, but when try to get data
    from method in web api data protected by [Authorize] attribute i receive un unauthorized error, without Authorize attrubute work fine. Cors is enabled, same machine. How inform the web api for data that user is auyhenticated?
    Thanks in advance
    paolo

  5. @paolo : Make new derived class of AuthorizeAttribute and override function

    protected override bool IsAuthorized(System.Web.Http.Controllers.HttpActionContext actionContext)
    {
    }
    

    to tell if user is authorized. Then use this new attribute instead of Authorize attribute.

  6. Thank you for your answer,
    but when call the second api how check if the caller is authenticated?
    Try to extract token from header and check if is valid and not expired? But if the token change?
    I have a web api that authenticate user with Owin/OAuth and emit a token, then I try to call a method from the web api 2, but in the web api 2 the user isn’t authenticated.
    If use postman and call web api 2 passing bearer token in the header all work fine.

    Thanks and excuse my ignorance

  7. @paolo: What do you mean with “Web API 2”, you mean “AController” call “BController” inside of your web service? If that your case then in AController you have to initialize HttpClient and make a HttpRequest to BController like a normal client. Bearer Token can be extracted from HttpContext and should be used for calling BController.

    However I think this crossing request isn’t good designed. Try to implement a common class and use it in AController and BController instead of making crossing request.

  8. Thank you so much for your quick response. User of Web app call web api A for authentication, web api A authenticate user and emit a token, then user web app call web api B (another domain, same machine, cors enabled) to get, for example,a list of product) . My problem is how web api B check that the user is authenticated? how web api B extract the token from the header, retrieve name or id of user.
    Thanks in advance
    paolo

  9. @paolo: I still don’t understand what you’re trying to do. Does web api A, B use same database? How do you call B from A?

    If A,B use same database then as I told you before, you can extract bearer token in HttpRequest which is currently sent to A. Then attach this token to HttpRequest which you’re going to send it from A to B. At B, token will be verified with same database and it’ll work.

    Explain more what you want to do.

  10. Great example, but i was wondering if you would have an example using oauth and owin using asp.net api’s in visual studio and android studio as the client? I have been looking for an example for the last couple of days but have failed to find one. can you help please?

  11. @Tony: I don’t have any post about ASP.NET Identity OAuth and Android client right now. The topic is still on my tasks list. :(. I saw there are some articles about ASP.NET Identity OAuth in .NET client. You can learn the concept and try to implement it within Android.

  12. Thanks for the reply, yes I am currently trying to implement it in android :S, will you be making a post about this anytime soon? It would help me a lot.

  13. I’ve struggled to find an example for a ‘forgot password’ method using Web API 2. Any search results in a multitude of MVC examples, but it seems Web API is lacking. Is there a reason for this?

    By the way, your blog has some of the clearest examples and tutorials on the web. I really appreciate your work.

Leave a Reply

Your email address will not be published. Required fields are marked *