How to set error messages in specific cases in symfony2 login_check - security

How can I write specific error message in symfony2 when login failed depend on the situation
For example:
When username is not found:
The username 'userxxx' doest not exist.
When username is found but password is wrong:
The password you've entered is wrong! Please try again!
Or: The password for 'userxxx' is wrong! Please try again!
I found a way to alert error message when the username is not found is write a custom userprovider
class UserProvider implements UserProviderInterface {
protected $entityManager;
public function __construct(EntityManager $entityManager) {
$this->entityManager = $entityManager;
}
public function loadUserByUsername($username) {
$user = $this->entityManager
->getRepository('ShopSecurityBundle:User')
->findOneBy(array('username' => $username));
if ($user) {
$service_user = new SecurityServiceUser($user->getUsername(), $user->getPassword(), $user->getSalt(), array($user->getRole()));
//var_dump($service_user); die;
return $service_user;
}
// I throw a BadCredentialsException() here then the error message in security Context will be changed arcodding to the exception message!
throw new BadCredentialsException(sprintf('Username "%s" does not exist', $username));
}
// ...
}
But I dont know how to change the error message when the password is wrong while the username is correct!
Any suggestion?

The clean solution would be adding errors to your form-fields 'username' and 'password' or directly to your form to display a general 'error'.
The quick solution is just passing a variable i.e. 'error' to twig ( as FOSUserBundle does ).
Throw an exception corresponding to your authentication errorr and catch it with a listener.
See how FOSUserBundle solves this in FOSUserBundle\Security\UserProvider and Controller\SecurityController.
An example on how catch the exception in your Listener can be found in the documentation chapter How to create a custom Authentication Provider. ( look at the handle method )
An overview of symfony's security exceptions can be found here.

Related

Trying to get property 'id' of non-object This Error comes in that Function

public function productTrackOrder(Request $request)
{
$order=Order::where('user_id',auth()->user()->id)->where('order_number',$request->order_number)->first();
You can access the user id via the Auth facade.
Auth::id()
However, always do a check to be share that the user is logged in to avoid a non object-error
use Illuminate\Support\Facades\Auth;
// can always check if the user is logged in before running your query
if (Auth::check()) {
$order=Order::where('user_id',Auth::id())-
>where('order_number',$request->order_number)->first();
}

VerifyUserTokenAsync() failed with purpose: EmailConfirmation for user XXXX1145-8bcb-48d6-b8a8-dcb75955b738

I am getting 'Invalid token' error while Email confirmation in .NET core.
Above error is thrown randomly. Clicking the confirmation link for the first time is throwing error and again if we click on the same link email is getting confirmed.
Web application is deployed in Azure. Also in logs we found the below error
VerifyUserTokenAsync() failed with purpose: EmailConfirmation for user XXXX1145-8bcb-48d6-b8a8-dcb75955b738.
Email Confirmation method is below
public async Task<IActionResult> ConfirmEmail(string userid, string token)
{
ApplicationUser user = await _userManager.FindByIdAsync(userid);
if(user != null)
{
IdentityResult result = await _userManager.ConfirmEmailAsync(user, token);
if (result.Succeeded)
{
return Redirect("/Thankyou?status=confirm");
}
else
{
return Redirect("/Thankyou?status=" + result.Errors.ToArray()[0].Description);
}
}
else
{
return Redirect("/Thankyou?status=Invalid User");
}
}
I had the same problem, I solved it by decoding my URL encoded tokens:
var decodedTokenString = Encoding.UTF8.GetString(WebEncoders.Base64UrlDecode(token));
It looks like the user account is already confirmed. You can take a look at the value of User.EmailConfirmed.

Using 2FA for password reset

My application uses Asp.Net Identity and sends a Two Factor code to my Auth app on login. This is pretty standard (as there lots of examples on the net) and uses the SendCode() method. My understanding is that the 'magic' is done by this line:
// Generate the token and send it
if (!await SignInManager.SendTwoFactorCodeAsync(model.SelectedProvider))
{
View("Error");
}
My requirement is to ensure the user goes through the same process of 2FA when they want to change their password after they have logged in.
My issue is that when the code to send the 2FA code is executed:
if (!await SignInManager.SendTwoFactorCodeAsync(model.SelectedProvider))
{
View("Error");
}
I receive the error 'UserID not found':
Server Error in '/MSPortal' Application.
UserId not found.
Description: An unhandled exception occurred during the execution of the current web request. Please review the stack trace for more information about the error and where it originated in the code.
Exception Details: System.InvalidOperationException: UserId not found.
Source Error:
Line 555:
Line 556: // Generate the token and send it
Line 557: if (!await SignInManager.SendTwoFactorCodeAsync(model.SelectedProvider))
Line 558: {
Line 559: return View("Error");
I know SendTwoFactorCodeAsync() calls GetVerifiedUserIdAsync() but my understanding is that the user is verified now that I have already logged in using 2FA.
Does anyone know why I would be getting this error?
Thanks.
I've worked around this by overriding SendTwoFactorCodeAsync() in IdentityConfig.cs. In this override, I first call GetVerifiedUserIdAsync() as per usual but then if that is 0 I get the User's ID from the Current HttpContext.
I am not stating this is the best way but it's what I have done thus far and its got me moving ahead in my aim of having 2FA for login, change password and forgot password.
The code (likely to go through some refactoring if I get feedback) is:
public override async Task<bool> SendTwoFactorCodeAsync(string provider)
{
int userId = 0;
try
{
userId = await GetVerifiedUserIdAsync();
if (userId == 0)
{
userId = Convert.ToInt32(HttpContext.Current.User.Identity.GetUserId());
}
if (userId == 0)
return false;
}
catch
{
return false;
}
var token = await UserManager.GenerateTwoFactorTokenAsync(userId, provider);
// See IdentityConfig.cs to plug in Email/SMS services to actually send the code
await UserManager.NotifyTwoFactorTokenAsync(userId, provider, token);
return true;
//return base.SendTwoFactorCodeAsync(provider);
}

"User not found" Error when creating a child entity using ControllerB action, soon after an aspUser is created in controllerA

After the successful creation of an application user and the following line of code (in Register action in AccountController) :
await SignInManager.SignInAsync(user, isPersistent: false, rememberBrowser: false);
I am trying to add a child object
var controller=DependencyResolver.Current.GetService<AnotherController>();
controller.ControllerContext = new ControllerContext(Request.RequestContext, controller);
var res = controller.Create(
new ChildEntity
{
ApplicationUserId = user.Id,
IsAcative = true
});
my create Method looks like this
public async Task<ActionResult> Create(ChildEntity entity)
{
if (ModelState.IsValid)
{
db.ChildEntity.Add(entity);
await db.SaveChangesAsync();
return RedirectToAction("Index");
}
return View(entity);
}
My object is not created. the return valueres contains the error "user not found" propertyName : "ApplicationUserId"
Can anybody help me to understand what is going on?
ps : i have noticed that the User.Identity.GetUserId() return null !!! (may be fo some other reason, may be my problem is linked to this..)
First and foremost, the user principal is not populated until after the next page load. The sign-in process merely sets the auth cookie. That cookie needs to be sent back and the auth machinery needs to run (as part of the request pipeline), before you can get anything from User.
Second, what you're doing here is just absolutely wrong. If you want to reuse the user creation code, factor it out into another class that all your controllers can utilize. It's absolutely the wrong approach to try to new up a controller inside another action to call an action on that.

NUnit & MVC4 SimpleMembership

I'm having a really difficult time creating unit tests for my MVC4 application, using NUnit. Right now I'm just focusing on this one test in particular, which logs a user in OR creates them if they don't exist, and then logs them in. Here is the test :
[Test]
public void LoginValidUser()
{
//Start up the DB connection
App_Start_DB();
//Setup our default test user
string UserName = "LocalTestUser#penrouse.com";
string Password = "books";
bool LoginWorked = false;
//check and see if our test user exists
if (!WebSecurity.UserExists(UserName))
{
//If not, create them
WebSecurity.CreateUserAndAccount(UserName, Password, new
{
Name = "Local Test User",
IsPromotional = true,
IsAllowShare = true
});
//Log them in
LoginWorked = WebSecurity.Login(UserName, Password);
}
else
{
//This user already exists, just log them in
LoginWorked = WebSecurity.Login(UserName, Password);
}
Assert.IsTrue(LoginWorked);
Trace.WriteLine("Login Valid User Result : " + LoginWorked.ToString());
}
The problem is that every time I attempt WebSecurity.Login(), I get a null reference exception, and the stack trace points to :
System.Web.Security.FormsAuthentication.SetAuthCookie(String userName, Boolean createPersistentCookie, String strCookiePath);
Calling that method directly before the login attempt the does not change the behavior. Thus, I have two questions :
Is there a better way to go about testing these parts of SimpleMembership?
If not, is there a good way to override or mock out the AuthCookie so that the login will work when tested in this way?
Any help\insight would be hugely appreciated.

Resources