I am developing an application on ASP.NET MVC 4. I am using a TDD approach to develop my application. Initially, I am trying to implement a login module for the application. Technically in order to login,it requires to follow these steps:
Verify user account is not locked and its a valid user. (If user attempt to login multiple times, it must lock the account after 5 unsuccessful attempt. To achieve this, I have a LoginAttempt field in my database, that I update after every unsuccessful attempt)
If account is verified, Validate the user with loginId and password using a third party service.
If verified, User must be redirected to Index page.
To achieve these task, I have created:
// Interface, Controller will interact with
public Interface IAuthenticate
{
bool ValidateUser(string UserId,string Password);
}
// Class that implement IAuthenticate
public class Authenticate : IAuthenticate
{
private IVerifyUser loginVerify;
private IThirdPartyService thirdpartyService;
public Authenticate(IVerifyUser user,IThirdPartyService thirdparty)
{
this.loginVerify=user;
this.thirdpartyService=thirdparty;
}
public bool ValidateUser(string userId,string password)
{
if(loginVerify.Verify(userId))
{
if(thirdpartyService.Validate(userId,password))
return true;
else
return false;
}
else
return false;
}
}
To test my controller Login, DO I have to just create a mock for IAuthenticate or do I have to create mock for IVerifyUser and IThirdPartyService ??
[TestMethod]
public void Login_Rerturn_Error_If_UserId_Is_Incorrect()
{
Mock<IAuthenticate> mock1 = new Mock<IAuthenticate>();
mock1.Setup(x => x.ValidateUser("UserIdTest", "PasswordTest"))
.Returns(false);
var results = controller.Login();
var redirect = results as RedirectToRouteResult;
Assert.IsNotNull(results);
Assert.IsInstanceOfType(results, typeof(RedirectToRouteResult));
controller.ViewData.ModelState.AssertErrorMessage("Provider", "User Id and Password is incorrect");
Assert.AreEqual("Index", redirect.RouteValues["action"], "Wrong action");
Assert.AreEqual("Home", redirect.RouteValues["controller"], "Wrong controller");
}
If you're testing your controller and your controller has a dependency on an instance of IAuthenticate then that is all your have to mock. By mocking it, you are disregarding any actual implementation within it. You are only testing the behaviour of the controller given the end behaviour occuring using IAuthenticate.
In your unit tests tests for your implementation of IAuthenticate you would then mock its dependencies (IVerifyUser and IThirdPartyService) to test how it behaves given a certain end result from either of their methods.
If you need any clarification, please comment! :)
Related
I am migrating users from a legacy user store to ASP.NET Identity 2.0 in my ASP.NET 5.0 web application. I have a means of verifying legacy hashes, but I want to upgrade them at login-time to ASP.NET Identity 2.0 hashes.
I've created a custom IPasswordHasher that is able to detect and verify legacy hashes, and return PasswordVerificationResult.SuccessRehashNeeded at the appropriate time. (If it detects that the hash is not legacy, it simply falls through to the built-in ASP.NET Identity hash verification.)
However, returning PasswordVerificationResult.SuccessRehashNeeded doesn't seem to cause ASP.NET Identity to actually do anything. Is there a configuration option somewhere that would cause the system to re-hash the passwords when IPasswordHasher returns this result?
If the answer is no to the above, then is it recommended that I simply re-hash and update the user manually? Where would I do this? I don't see any place at the controller level where I can see the PasswordVerificationResult.
I'm new to ASP.NET Identity so I'm sure I'm missing something simple. Thank you in advance for any pointers.
It seems rehashing mechanism is not implemented in the built-in user manager. But hopefully you could easily implemented. consider this:
public class ApplicationUserManager : UserManager<ApplicationUser>
{
protected override async Task<bool> VerifyPasswordAsync(
IUserPasswordStore<ApplicationUser, string> store,
ApplicationUser user, string password)
{
var hash = await store.GetPasswordHashAsync(user);
var verifyRes = PasswordHasher.VerifyHashedPassword(hash, password);
if (verifyRes == PasswordVerificationResult.SuccessRehashNeeded)
await store.SetPasswordHashAsync(user, PasswordHasher.HashPassword(password));
return verifyRes != PasswordVerificationResult.Failed;
}
}
If you have implemented IPasswordHasher correctly, when returning a PasswordVerificationResult.SuccessRehashNeeded result, ASP.NET Core Identity will call the HashPassword method automatically for you, successfully authenticating the user and updating the hash in the database.
The class would look something like this:
public class PasswordHasherWithOldHashingSupport : IPasswordHasher<ApplicationUser>
{
private readonly IPasswordHasher<ApplicationUser> _identityPasswordHasher;
public PasswordHasherWithOldHashingSupport()
{
_identityPasswordHasher = new PasswordHasher<ApplicationUser>();
}
public string HashPassword(ApplicationUser user, string password)
{
return _identityPasswordHasher.HashPassword(user, password);
}
public PasswordVerificationResult VerifyHashedPassword(ApplicationUser user, string hashedPassword, string providedPassword)
{
var passwordVerificationResult = _identityPasswordHasher.VerifyHashedPassword(user, hashedPassword, providedPassword);
if (passwordVerificationResult == PasswordVerificationResult.Failed)
{
/* Do your custom verification logic and if successful, return PasswordVerificationResult.SuccessRehashNeeded */
passwordVerificationResult = PasswordVerificationResult.SuccessRehashNeeded;
}
return passwordVerificationResult;
}
}
I've just started programming in C# Webforms (previous experience in VB Webforms) and I am producing a web app that will be a small part of a bigger project.
I have created 3 separate projects, one for the webforms, one for the class library and one for the tests.
I have added all the projects into one solution and added appropriate references, Both the Webforms and Tests projects reference the class library.
I have a class in the class library that finds the username of the logged in user:
public class LoggedInUser
{
public string UserName
{
get { return HttpContext.Current.User.Identity.Name; }
}
}
In the page load event of one of my pages, I use this class to set the text property of a literal to display the name on the screen.
protected void Page_Load(object sender, EventArgs e)
{
LoggedInUser CurrentUser = new LoggedInUser();
LitUser.Text = string.Format(" {0}", CurrentUser.UserName);
}
This works fine.
To be complete I thought I would write a unit test to make sure the logged in username is what I expected.
[TestMethod]
public void Test_Logged_In_User_Name()
{
LoggedInUser actualUser = new LoggedInUser();
string expectedUserName = "myUserName";
string actualUserName = actualUser.UserName;
Assert.AreEqual(expectedUserName, actualUserName);
}
When I run the test it throws the following exception:
System.NullReferenceException: Object reference not set to an instance of an object
on this line:
get { return HttpContext.Current.User.Identity.Name; }
Any thoughts would as always be greatly appreciated.
You'll need to create a wrapper class for HttpContext that abstracts the functionality you need. The reason for this is that HttpContext only exists for web requests and as you are running your unit tests from an application HttpContext will not exist.
Additionally any 3rd party dependency should have a wrapper created for it to assist with testing.
It's worth noting, you also shouldn't need this test at all. In this instance you are testing a 3rd parties code, something you are relying on to be accurate. The purpose of unit tests is to test your own code/logic and if you wrote tests for every 3rd party method you'd never get a product released :).
As for creating a wrapper class, they are not dissimilar from ordinary classes. You'd need to create an interface for the HttpContext class and then create a wrapper something like the below:
public class HttpContextWrapper
{
private readonly IHttpContext _httpContext;
public HttpContextWrapper()
{
_httpContext = HttpContext.Current;
}
public HttpContextWrapper(IHttpContext injectedContext)
{
_httpContext = injectedContext;
}
public string GetName()
{
_httpContext.Current.User.Identity.Name;
}
}
You could then inject a fake implimentation of HttpContext to get your desired results.
Actually, you don't necessarily need to wrap and mock the HttpContext. In your test setup, you can do something similar to the following:
var sb = new StringBuilder();
TextWriter writer = new StringWriter(sb);
HttpContext.Current = new HttpContext(
new HttpRequest("path", "http://dummy", ""),
new HttpResponse(writer)
)
{
User = new WindowsPrincipal(WindowsIdentity.GetCurrent())
};
In this example, I assign a windows principal with the identity of the current user, but in your scenario you may want to assign a specifically crafted principal, e.g. a ClaimsPrincipal or a fake implementation (or a mock).
I've currently got a very simple setup running. This setup consists of an entity-framework project, and an IIS server. The IIS is configured to use windows authentication.
Now in my project, I want to allow only certain users to gain access to certain controllers. Within the organisation I'm working for there's a "permissions" system, a table that contains what users are allowed to access what data. So, I want to get the e-mail with which the user logged in, and check that against the database to see if he has permission.
My plan for doing this was to make a seperate piece of code, that's not accessable from the web, that contains the function "boolean hasPermissions(String email, byte permissions)". But I've got no idea where to place this, nor can I find any information on this. Is what I have in mind the right approach? And if, then how to execute this approach correctly?
You should use windows authentication, using IPrincipal , you will have a user object that you could ask IsInRole for specific role based security instead of bits / booleans
read all about it at Asp.net windows authentication
and how to implement IPrincipal Implement custom security
Code sample:
User object:
public class User : IPrincipal
{
private readonly IPrincipal _user;
public IIdentity Identity { get; private set; }
public User (IPrincipal user)
{
Identity = user.Identity;
_user = user;
}
public bool IsInRole(string role)
{
return _user.IsInRole(role);
}
}
In MVC add a filter
public class CustomAuthenticationAttribute : ActionFilterAttribute, IAuthenticationFilter
{
public void OnAuthentication(AuthenticationContext filterContext)
{
var user= new User (HttpContext.Current.User);
Thread.CurrentPrincipal = user;
}
}
And add that filter to your FilterConfig using
filters.Add(new CustomAuthenticationAttribute());
Then, when using the user object within your application
var user = new User(Thread.CurrentPrincipal);
if(user.IsInRole("admin")) /* do the choka choka */;
I'm implementing an oauth provider using DotNetOpenAuth CTP library. So I have created an mvc3 application, which has an OAuth Controller with 3 methods in it with the purpose of authorizing third party applications. The controller has an IOAuthService which encapsulates all the logic that the library must do to complete certain tasks, however, the service methods return DotNetOpenOAuth objects that have their constructors protected.
I would like to test the behavior of the methods within my OAuthController, for this, I'm trying to mock my service methods but I havent't been able to do this. I have to tell moq library what type of object I'm expecting the service method to return, and since I cannot access constructors of these objects, I'm not able to perform a test over my controller method.
The controller:
public class OAuthController : Controller
{
private readonly IOAuthService _oAuthService;
public OAuthController(IOAuthService oAuthService)
{
_oAuthService = oAuthService;
}
[Authorize, AcceptVerbs(HttpVerbs.Get | HttpVerbs.Post)]
public ActionResult Authorize()
{
ClientApplication requestingClient;
var request = _oAuthService.ReadAuthorizationRequest();
if (request == null)
{
throw new HttpException((int)HttpStatusCode.BadRequest, "Missing authorization request.");
}
var response = _oAuthService.RequestClientAuthorization(GetIdentity().Name, out requestingClient, request);
if (response != null)
{
return response.AsActionResult();
}
var model = new AuthorizeClientApplicationViewModel
{
ClientApplication = requestingClient.Name,
Scope = request.Scope,
AuthorizationRequest = request,
};
return View(model);
}
public virtual IIdentity GetIdentity()
{
return User.Identity;
}
}
I want to test that whenever a third party app has no authorization, a view will pop up to the user asking for his permission to authorize the app. Fot this i need to mock:
_oAuthService.RequestClientAuthorization
The setup of my test method will then look like :
var oAuthService = new Mock<IOAuthService>();
oAuthService.Setup(a => a.RequestClientAuthorization(userName, out client, pendingRequest)).Returns(new OutgoingWebResponse()); // DotNetOpenAuth doesn't allow me to do the **new OutgoingWebResponse**
PD: For this question I only wrote one of the controller methods, but there are 3, and they have similar scenarios.
One possibility is to write a wrapper (the same way ASP.NET MVC abstracts all the HTTP Context specific stuff):
public abstract class OutgoingWebResponseWrapperBase
{
protected OutgoingWebResponseWrapperBase() { }
public abstract ActionResult AsActionResult();
}
and then have a naïve implementation:
public class OutgoingWebResponseWrapper: OutgoingWebResponseWrapperBase
{
private readonly OutgoingWebResponse _response;
public OutgoingWebResponseWrapper(OutgoingWebResponse response)
{
_response = response;
}
public override ActionResult AsActionResult()
{
return _response.AsActionResult();
}
}
Now modify the IOAuthService.RequestClientAuthorization method to return a OutgoingWebResponseWrapperBase instead of OutgoingWebResponse.
Just like that:
public interface IOAuthService
{
...
OutgoingWebResponseWrapperBase RequestClientAuthorization(...);
}
Obviously your controller code will stay absolutely the same. It's just that now you can mock the return type of the RequestClientAuthorization in your unit test because it is an abstract class. You can also mock the AsActionResult abstract method call to return some expected mocked instance and you will assert in your unit test that the controller action that you are testing returned this expected action result.
If the constructor is protected, then a derived type could access it. Can you simply use Moq to create a mock of OutgoingWebResponse (which internally will make Moq derive from it and call the protected constructor I think) and return that from your mock method implementation?
Something like this:
System.Net.HttpWebResponse mockResponse; // get this from somewhere
new Moq.Mock<DotNetOpenAuth.Messaging.OutgoingWebResponse>(mockResponse, 5);
This should let you mock up an OutgoingWebResponse. The next problem becomes, where do you get yoru HttpWebResponse instance, since that too has only a protected constructor. You could continue the chain and mock up that the same what as OutgoingWebResponse, and see how far you get.
I am new to unit testing and I am trying to test some of my .NET membership stuff I been writing.
So I am trying to check my VerifyUser method that checks if the users credentials are valid or not.
So this is what it looks like:
public bool VerifyUser(string userName, string password)
{
bool valid = Membership.ValidateUser(userName, password);
return valid;
}
And now every time I run my unit test it fails. I know I am passing in the right credentials and stuff. Then it dawned on me that maybe my Test Project(that is under the same Solution as my real project) might need its own web.config file with the connection string and stuff. Or an app config file maybe since it is a Application Library project.
So do I just copy the web.config file from my real project and call it a day? Or should I only be taking parts from it? Or am I just way off.
My database is using a custom database with the .net membership merged with my database. So in my config file I had to specify a ManagerProvider and a roleProvider.
This is how my unit test looks like
[Test]
public void TestVerifyUser()
{
AuthenticateUser authenitcate = new AuthenticateUser();
bool vaild = authenitcate.VerifyUser("chobo3", "1234567");
Assert.That(vaild, Is.True);
}
Also later on I have in one of my asp.net mvc ActionResult Methods(the Login View to be exact) I have this:
FormsAuthentication.RedirectFromLoginPage(loginValidation.UserName, rememberMe);
So now how can I write a unit test that would do what a user would do. Say they start at the Home page then click on the login page and log in successfully. I want them to be redirect to the home page.
I am not sure how to represent that in code. I am pretty sure that the RedirectFromLoginPage works and thats now what I am really testing. I am testing the fact that I have 3 things that can happen in the login ActionResult method.
User logs in and gets sent back where they came from.
User fails to login and gets sent back to the LoginView and sees error messages.
User has tried to go to a secure and has been redirect to the login page. If the login successfully the will be redirect back to the secure page via the ReturnUrl.
So I want to do a test to see if these work as they should. So thats why I need to have the user coming from like the home page to see if they get redirected back to it later and if they come from a secure page they get redirect back to that later on.
I am also by the way using NUnit 2.5 and VS2008 Pro.
This is what I am trying to test. I am at the part where I am trying to see if the user is valid or not(the if statement). I have no clue how to test it.
public ActionResult Login(string returnUrl, FormCollection form, bool rememberMe)
{
LoginValidation loginValidation = new LoginValidation();
try
{
UpdateModel(loginValidation, form.ToValueProvider());
}
catch
{
return View("Login");
}
if (ModelState.IsValid == true)
{
bool valid = authenticate.VerifyUser(loginValidation.UserName, loginValidation.Password);
if (valid == false)
{
ModelState.AddModelError("frm_Login", "Either the Password or UserName is invalid");
}
else if (string.IsNullOrEmpty(returnUrl) == false)
{
/* if the user has been sent away from a page that requires them to login and they do
* login then redirect them back to this area*/
return Redirect(returnUrl);
}
else
{
FormsAuthentication.RedirectFromLoginPage(loginValidation.UserName, rememberMe);
}
}
return View("Login");
}
You can test your controllers and much of your custom provider by refactoring your custom membership code into a two layers: a data access repository that only interacts with the database, and a service layer that uses repository components to provide the Membership API. The service layer is where you would validate arguments, hold and enforce parameters like EnablePasswordReset and translate any database exceptions or status codes into a form suitable for controller consumption.
When you specify each layer with its own interface, consumers can write to that interface regardless of how its implemented. When your app is running your provider is of course talking to the database through these interfaces but for testing you can mock the repository or service interfaces. You can test your service layer by mocking the repository level without have to mess with the database or the web.config file, and you can test your controllers by mocking the service layer. If you don't want to refactor the whole provider, you can still test your controllers if you only create the service interface and have your controllers use it.
To be specific, if a little verbose, your repository and service interfaces might look something like:
namespace Domain.Abstract {
public interface IRepository {
string ConnectionString { get; }
}
}
namespace Domain.Abstract {
public interface IUserRepository : IRepository {
MembershipUser CreateUser(Guid userId, string userName, string password, PasswordFormat passwordFormat, string passwordSalt,
string email, string passwordQuestion, string passwordAnswer, bool isApproved,
DateTime currentTimeUtc, bool uniqueEmail);
MembershipUser GetUser(Guid userId, bool updateLastActivity, DateTime currentTimeUtc);
PasswordData GetPasswordData(Guid userId, bool updateLastLoginActivity, DateTime currentTimeUtc);
void UpdatePasswordStatus(Guid userId, bool isAuthenticated, int maxInvalidPasswordAttempts, int passwordAttemptWindow,
DateTime currentTimeUtc, bool updateLastLoginActivity, DateTime lastLoginDate, DateTime lastActivityDate);
//....
}
}
namespace Domain.Abstract {
public interface IUserService {
bool EnablePasswordRetrieval { get; }
bool EnablePasswordReset { get; }
bool RequiresQuestionAndAnswer { get; }
bool RequiresUniqueEmail { get; }
//....
MembershipUser CreateUser(string applicationName, string userName, string password, string email, string passwordQuestion, string passwordAnswer, bool isApproved);
MembershipUser GetUser(Guid userId, bool userIsOnline);
bool ValidateUser(Guid userId, string password);
//...
}
}
namespace Domain.Concrete {
public class UserService : IUserService {
private IUserRepository _userRepository;
public UserService(IUserRepository userRepository) {
_userRepository = userRepository;
}
//...
public bool ValidateUser(Guid userId, string password) {
// validate applicationName and password here
bool ret = false;
try {
PasswordData passwordData;
ret = CheckPassword(userId, true, true, DateTime.UtcNow, out passwordData);
}
catch (ObjectLockedException e) {
throw new RulesException("userName", Resource.User_AccountLockOut);
}
return ret;
}
private bool CheckPassword(Guid userId, string password, bool updateLastLoginActivityDate, bool failIfNotApproved,
DateTime currentTimeUtc, out PasswordData passwordData) {
passwordData = _userRepository.GetPasswordData(userId, updateLastLoginActivityDate, currentTimeUtc);
if (!passwordData.IsApproved && failIfNotApproved)
return false;
string encodedPassword = EncodePassword(password, passwordData.PasswordFormat, passwordData.PasswordSalt);
bool isAuthenticated = passwordData.Password.Equals(encodedPassword);
if (isAuthenticated && passwordData.FailedPasswordAttemptCount == 0 && passwordData.FailedPasswordAnswerAttemptCount == 0)
return true;
_userRepository.UpdatePasswordStatus(userId, isAuthenticated, _maxInvalidPasswordAttempts, _passwordAttemptWindow,
currentTimeUtc, updateLastLoginActivityDate,
isAuthenticated ? currentTimeUtc : passwordData.LastLoginDate,
isAuthenticated ? currentTimeUtc : passwordData.LastActivityDate);
return isAuthenticated;
}
}
The Asp.Net Membership system is designed to work in the context of an Asp.Net request. So, you have three options here.
Most people when faced with such a dependency would write a thin wrapper around it. The wrapper doesn't do anything, just redirects all calls to the underlying dependency. So, they just don't test it. Your AuthenticateUser is such a wrapper. You should probably make all methods virtual or extract an interface in order to make it mockable, but that's another story.
Use TypeMock Isolator and mock Membership.
Use the Ivonna framework and run your test in the Asp.Net context (that would be an integration test).
Unfortunately you can't just copy your web.config or your app.config and have it work that way. The reason is that your assembly is running inside of the NUnit process, not under your application.
To remedy your situation, you're probably going to have to Mock or Stub the Membership members you're calling, or follow a Convention over Configuration approach to the settings you have stored in your web.config.
There are many mocking frameworks out there, but here are a couple: Rhino Mocks, Moq
Also, to follow the Convention over Configuration approach, you could do something like this:
static ConfigurationSettings
{
static String SomeSetting
{
get
{
var result = "HARDCODEDVALUE";
if (ConfigurationManager.AppSettings["SOMEKEY"] != null)
result = ConfigurationManager.AppSettings["SOMEKEY"];
return result;
}
}
You could then use this code like this:
//this is how the old code might look
var mySetting = ConfigurationManager.AppSettings["SOMEKEY"];
//use the setting
//this is how the new code would look
var mySetting = ConfigurationSettings.SomeSetting;
//use the setting
This way your test will work, and when you run it under your application it will use whatever configuration settings you've stored.