Web Api 2 Authentication Tutorial Video

by sunil ravulapalli /21. January 2014 05:24 /asp.net-web-api /Comments (0)


Customize authentication to my own set of tables in asp.net web api 2?

by sunil ravulapalli /20. December 2013 03:32 /asp.net-web-api /Comments (0)

Assuming your table is called AppUser, convert your own AppUser domain object to IUser(using Microsoft.AspNet.Identity) like this

using Microsoft.AspNet.Identity; 
public class AppUser : IUser 
{ 
    //Existing database fields 
    public long AppUserId { get; set; } 
    public long AppUserName { get; set; } 
    public string AppPassword { get; set; } 
    [NotMapped] 
    public virtual string Id 
    { 
       get
       {
          return AppUserId;
       } 
    } 
    [NotMapped] 
    public string UserName 
    { 
        get { return AppUserName; } 
        set { AppUserName = value; } 
    } 
}

Implement the UserStore object like this

	using Microsoft.AspNet.Identity;
	public class UserStoreService : 
		IUserStore<AppUser>, IUserPasswordStore<AppUser>, 
		IUserSecurityStampStore<AppUser>
	{
		CompanyDbContext context = new CompanyDbContext();

		public Task CreateAsync(AppUser user)
		{            
			throw new NotImplementedException();
		}

		public Task DeleteAsync(AppUser user)
		{
			throw new NotImplementedException();
		}

		public Task<AppUser> FindByIdAsync(string userId)
		{
			throw new NotImplementedException();
		}

		public Task<AppUser> FindByNameAsync(string userName)
		{
			Task<AppUser> task = 
			context.AppUsers.Where(apu => apu.AppUserName == userName)
			.FirstOrDefaultAsync();

			return task;
		}

		public Task UpdateAsync(AppUser user)
		{
			throw new NotImplementedException();
		}

		public void Dispose()
		{
			context.Dispose();
		}

		public Task<string> GetPasswordHashAsync(AppUser user)
		{
			if (user == null)
			{
				throw new ArgumentNullException("user");
			}

			return Task.FromResult(user.AppPassword);
		}

		public Task<bool> HasPasswordAsync(AppUser user)
		{
			return Task.FromResult(user.AppPassword != null);
		}

		public Task SetPasswordHashAsync(AppUser user, string passwordHash)
		{
			throw new NotImplementedException();
		}

		public Task<string> GetSecurityStampAsync(AppUser user)
		{
			throw new NotImplementedException();
		}

		public Task SetSecurityStampAsync(AppUser user, string stamp)
		{
			throw new NotImplementedException();
		}
	}

If you have your own custom password hashing you will also need to implement IPasswordHasher. Below is an example where there is no hashing of the password(Oh no!)

	using Microsoft.AspNet.Identity;
	public class MyPasswordHasher : IPasswordHasher
	{
		public string HashPassword(string password)
		{
			return password;
		}

		public PasswordVerificationResult VerifyHashedPassword
		(string hashedPassword, string providedPassword)
		{
			if (hashedPassword == HashPassword(providedPassword))
				return PasswordVerificationResult.Success;
			else
				return PasswordVerificationResult.Failed;
		}
	}

In Startup.Auth.cs replace

	UserManagerFactory = () => 
		new UserManager<IdentityUser>(new UserStore<IdentityUser>());

with

	UserManagerFactory = () => 
                new UserManager<AppUser>(new UserStoreService()) { PasswordHasher = new MyPasswordHasher() };

In ApplicationOAuthProvider.cs, replace IdentityUser with AppUser In AccountController.cs, replace IdentityUser with AppUser and delete all the external authentication methods like GetManageInfo and RegisterExternal etc.

How to call an Authenticated Web Api 2 method

by sunil ravulapalli /18. December 2013 08:28 /asp.net-web-api /Comments (0)

Do a HTTP GET on the this URL

http://localhost:15718/api/Account/UserInfo

with the HTTP HEADER

Authorization: Bearer zt3Ma_gzOxRi53YgCciMe1H1j6Uss.........

The bearer token is from login using http://localhost/token. You can get more information here.

You should get a HTTP RESPONSE 200 with following data

{
    "UserName":"johnsmith",
    "HasRegistered":true,
    "LoginProvider": null
}

How to do User Login into Web Api 2

by sunil ravulapalli /18. December 2013 08:22 /asp.net-web-api /Comments (0)


Do a HTTP POST to the URL

http://localhost/token

with the HTTP HEADER

content-type: application/x-www-form-urlencoded

and HTTP BODY

username=johnsmith&password=supersecret&grant_type=password

You should get HTTP RESPONSE 200 and return data as

{
    "access_token":"zt3Ma_gzOxRi53YgCciMe1H1j6Uss...........",
    "token_type":"bearer",
    "expires_in":1209599,
    "userName":"sunil",
    ".issued":"Tue, 17 Dec 2013 17:58:05 GMT",
    ".expires":"Tue, 31 Dec 2013 17:58:05 GMT"
}

How to do User Registration using Web Api 2

by sunil ravulapalli /18. December 2013 08:15 /asp.net-web-api /Comments (0)

Do a HTTP POST to the URL 

http://localhost/api/Account/Register

with HTTP HEADER

content-type: application/json

and the HTTP BODY

{
  "UserName": "johnsmith",
  "Password": "supersecret",
  "ConfirmPassword": "supersecret"
}

You should get a HTTP RESPONSE 200

ASP.NET Web Api custom IHttpActionResult for HTTP Forbidden

by sunil ravulapalli /13. November 2013 06:06 /asp.net-web-api /Comments (0)
    public class ForbiddenActionResult : IHttpActionResult
    {
        private readonly HttpRequestMessage _request;
        private readonly string _reason;
        public ForbiddenActionResult(HttpRequestMessage request, string reason)
        {
            _request = request;
            _reason = reason;
        }

        public Task<HttpResponseMessage> ExecuteAsync(CancellationToken cancellationToken)
        {
            var response = _request.CreateResponse(HttpStatusCode.Forbidden, _reason);
            return Task.FromResult(response);
        }
    }

You can use it like this:

public IHttpActionResult Get(long accountId)
{
    var payOffQuoteStatus = _payOffQuoteService.GetPayOffQuote(accountId);

    if (payOffQuoteStatus.IsEligibleForPayOffQuote)
          return Ok(payOffQuoteStatus.PayOffQuote);
    else
          return new ForbiddenActionResult(Request, payOffQuoteStatus.ReasonForIneligibility);
}

Unit Test ASP.NET Web Api IHttpActionResult

by sunil ravulapalli /13. November 2013 05:57 /asp.net-web-api /Comments (0)

Suppose the web api action looks like this

public IHttpActionResult Get(long accountId) 
{ 
       var payOffQuoteStatus = _payOffQuoteService.GetPayOffQuote(accountId); 

       return Ok<PayOffQuote>(payOffQuoteStatus.PayOffQuote); 
}

then the test would look like this

            //Arrange
            var payOffQuoteServiceMock = new Mock<IPayOffQuoteService>();
            payOffQuoteServiceMock.Setup(poqs => poqs.GetPayOffQuote(It.IsAny<long>()))
                                  .Returns(new PayOffQuoteStatus
                                      {
                                          IsEligibleForPayOffQuote = true,
                                          PayOffQuote = new PayOffQuote {BalanceOutstanding = 14225.68m}
                                      });
            var payOffController = new PayoffQuoteController(payOffQuoteServiceMock.Object);
            payOffController.Request = new HttpRequestMessage();
            payOffController.Request.Properties.Add(HttpPropertyKeys.HttpConfigurationKey, new HttpConfiguration());
            
            //Act
            var httpActionResult = payOffController.Get(12345678);

            //Assert
            OkNegotiatedContentResult<PayOffQuote> contentResult = httpActionResult as OkNegotiatedContentResult<PayOffQuote>;
            Assert.IsNotNull(contentResult);

            var payOffQuote = contentResult.Content as PayOffQuote;
            Assert.IsNotNull(payOffQuote);
            Assert.AreEqual(14225.68m, payOffQuote.BalanceOutstanding);

Unit test ASP.NET Web Api attrubute routing

by sunil ravulapalli /13. November 2013 03:50 /asp.net-web-api /Comments (0)

Most of the stuff is standard expect you need to call config.EnsureInitialized() after WebApiConfig.Register(config)

            //Arrange            
            var request = new HttpRequestMessage(HttpMethod.Get, "http://localhost.com/api/v1/account/12345678/info");
            var config = new HttpConfiguration();

            //Act
            WebApiConfig.Register(config);
            config.EnsureInitialized();
            var route = WebApi.RouteRequest(config, request);

            //Assert
            Assert.AreEqual("InfoController", route.Controller.Name);
            Assert.AreEqual("Get", route.Action);

Inject dependency into WebApiConfig class in ASP.NET Web Api using Ninject

by sunil ravulapalli /31. August 2013 01:46 /asp.net-web-api /Comments (0)


First you have to make the WebApiConfig into a non static class as shown below.
Notice, that the dependency I want to be inject is IAccountsService.

public class WebApiConfig
{
	private static IAccountsService _accountsService;
	public WebApiConfig(IAccountsService accountsService)
	{
		_accountsService = accountsService;
	}

	public void Register(HttpConfiguration config)
	{
		var authentication = CreateAuthenticationConfiguration();
		config.MessageHandlers.Add(new AuthenticationHandler(authentication));

		config.Routes.MapHttpRoute(
			name: "DefaultApi",
			routeTemplate: "api/{controller}/{id}",
			defaults: new { id = RouteParameter.Optional }
		);

		config.EnableSystemDiagnosticsTracing();
	}

	private AuthenticationConfiguration CreateAuthenticationConfiguration()
	{
		var authentication = new AuthenticationConfiguration
		{
			RequireSsl = false,
			EnableSessionToken = true
		};

		// Basic Authentication
		authentication.AddBasicAuthentication(_accountsService.ValidateAccountUsingSiteCredential);

		return authentication;
	}
}

Now, in the Global.asax file modify the Application_Start as follows

protected void Application_Start()
{
	AreaRegistration.RegisterAllAreas();

	//WebApiConfig.Register(GlobalConfiguration.Configuration);
	DependencyResolver.Current.GetService<WebApiConfig>().Register(GlobalConfiguration.Configuration);
	FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
	RouteConfig.RegisterRoutes(RouteTable.Routes);
	BundleConfig.RegisterBundles(BundleTable.Bundles);
}

That's it! You are good to go!

Enable CORS in Asp.net web.api using Thinktecture.IdentityModel

by sunil ravulapalli /24. August 2013 05:10 /asp.net-web-api /Comments (0)

Refer to http://sunilrav.com/post/Enable-Basic-Authetication-in-Aspnet-webapi-using-ThinktectureIdentityModel to enable basic authentication.
Add this method in WebApiConfig class

private static void ConfigureCors(HttpConfiguration config)
{ 
  var corsConfig = new WebApiCorsConfiguration(); 
  corsConfig.RegisterGlobal(config); 
   corsConfig
      .ForAllResources()
      .ForAllOrigins()
      .AllowAllMethods()
      .AllowAllRequestHeaders()
      .AllowAll();
}

Call ConfigureCors in Register method in WebApiConfig class

public static void Register(HttpConfiguration config)
{ 
  var authentication = CreateAuthenticationConfiguration();  
  config.MessageHandlers.Add(new AuthenticationHandler(authentication));   
  ConfigureCors(config); 
  config.Routes.MapHttpRoute(  name: "DefaultApi",  
           routeTemplate: "api/{controller}/{id}",  
           defaults: new { id = RouteParameter.Optional } );
  config.EnableSystemDiagnosticsTracing();
}

Make sure your web.config looks like this

<system.webServer> 
  <modules runAllManagedModulesForAllRequests="false">  
    <remove name="WebDAVModule" /> 
  </modules> 
  <handlers>  
    <remove name="WebDAV"/>  
    <remove name="OPTIONSVerbHandler"/>  
    <remove name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" />  
    <remove name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" />  
    <remove name="ExtensionlessUrlHandler-Integrated-4.0" />  
    <add name="ExtensionlessUrlHandler-ISAPI-4.0_32bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness32" responseBufferLimit="0" /> 
    <add name="ExtensionlessUrlHandler-ISAPI-4.0_64bit" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" modules="IsapiModule" scriptProcessor="%windir%\Microsoft.NET\Framework64\v4.0.30319\aspnet_isapi.dll" preCondition="classicMode,runtimeVersionv4.0,bitness64" responseBufferLimit="0" />  
    <add name="ExtensionlessUrlHandler-Integrated-4.0" path="*." verb="GET,HEAD,POST,DEBUG,PUT,DELETE,PATCH,OPTIONS" type="System.Web.Handlers.TransferRequestHandler" preCondition="integratedMode,runtimeVersionv4.0" /> 
  </handlers>
</system.webServer>