Incorrect validation message on Identity 2.0 registration form - asp.net-identity-2

In the 2.0.0 release issue 2040 was marked as Closed and Fix. When a user is registered and the email address already exists, the message returned is:
•Name [] is already taken.
•Email [] is already taken.
This should read Username [] is already taken to prevent confusion.
Will this be corrected or is there another way to address this.
p.s. I have updated to 2.2.0-alpha1 and the issue still exists.

You have to manually add correct error message checking the IdentityResults like below.
private void AddErrors(IdentityResult result)
{
foreach (var error in result.Errors.Where(error => !error.StartsWith("Name")))
{
ModelState.AddModelError("", error);
}
}

Related

Credential Provider accepts old Windows Live account passwords

For one of our customers, we created a custom credential provider which receives a decryption key and the filename of an encrypted file which container the username and password. This mechanism works perfectly for local user accounts. The user is authenticated when needed, and the old password is no longer accepted right after the user changes his password.
However, for windows live accounts the user can sometimes login using his old password after changing his password online (accounts.microsoft.com) and even after logging in to windows with the newly created password. Strange thing is, that the user cannot login by typing his old password. It only works when using the credential provider.
To make it more confusing, sometimes it works as expected and the behavior seems to differ from machine to machine.
My gut feeling tells me, there is something wrong with the code we use to authenticate the user, but I cannot figure out what is going wrong. We already tried to set the OldPasswordAllowedPeriod registry value, but this seems not to work.
We use the following GetSerialization() implementation, to fill the authentication buffer:
public int GetSerialization(...)
{
pcpgsr = _CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE.CPGSR_NO_CREDENTIAL_NOT_FINISHED;
pcpcs = new _CREDENTIAL_PROVIDER_CREDENTIAL_SERIALIZATION();
ppszOptionalStatusText = string.Empty;
pcpsiOptionalStatusIcon = _CREDENTIAL_PROVIDER_STATUS_ICON.CPSI_NONE;
try
{
var inCredSize = 0;
var inCredBuffer = Marshal.AllocCoTaskMem(0);
if (string.IsNullOrEmpty(_username) || _password == null || _password.Length == 0)
{
return SetAuthenticationError(out pcpgsr, out pcpsiOptionalStatusIcon, out ppszOptionalStatusText, "This NFC card has not been registered on this screen.");
}
if (!PInvoke.CredPackAuthenticationBuffer(0, _username, SecureStringToString(_password), inCredBuffer, ref inCredSize))
{
Marshal.FreeCoTaskMem(inCredBuffer);
inCredBuffer = Marshal.AllocCoTaskMem(inCredSize);
if (PInvoke.CredPackAuthenticationBuffer(0, _username, SecureStringToString(_password), inCredBuffer, ref inCredSize))
{
pcpgsr = _CREDENTIAL_PROVIDER_GET_SERIALIZATION_RESPONSE.CPGSR_RETURN_CREDENTIAL_FINISHED;
pcpsiOptionalStatusIcon = _CREDENTIAL_PROVIDER_STATUS_ICON.CPSI_SUCCESS;
pcpcs.clsidCredentialProvider = Guid.Parse(Constants.CredentialProviderUID);
pcpcs.rgbSerialization = inCredBuffer;
pcpcs.cbSerialization = (uint)inCredSize;
RetrieveNegotiateAuthPackage(out var authPackage);
pcpcs.ulAuthenticationPackage = authPackage;
return HResult.S_OK;
}
_logger.LogError($"Failed to pack credentials for: {_username}.");
return SetAuthenticationError(out pcpgsr, out pcpsiOptionalStatusIcon, out ppszOptionalStatusText, "Failed to pack credentials.");
}
_logger.LogWarning("GetSerialization unexpectedly preliminary succesfully buffered credentials");
return SetAuthenticationError(out pcpgsr, out pcpsiOptionalStatusIcon, out ppszOptionalStatusText, "Something unexpected went wrong!");
}
catch (Exception ex)
{
// In case of any error, do not bring down winlogon
_logger.LogError(ex);
return SetAuthenticationError(out pcpgsr, out pcpsiOptionalStatusIcon, out ppszOptionalStatusText, "Something unexpected went wrong!");
}
finally
{
_shouldAutoLogin = false; // Block auto-login from going full-retard
}
}
Can someone point me in the right direction to solve this issue? Or, has someone any idea on what we are doing wrong when authenticating the user, using our custom credential provider?
Thanks in advance!

issue with creating role and channel automatically from private message with bot

Not sure how the create channel and create role isn't working inside the following code, towards the bottom. (EDIT: Nothing is sent to the console and nothing happens regardng the code. It is like it is entirely ignored.) This is a snippet from code that User A challenges User B. User B is messaged, alerting them that a challenge has been issued to them via a Private Message. If the challenge is accepted, I want the bot to 1)Make a role specifically for User A and User B named "User A vs User B" 2) take User A and User B and put them both into that new role and 3) Make a battlefield named "User A vs User B" inside a specific category inside the server the bot is on.
I am unsure if the problem lies in how the bot is trying to make the role and channel in a sever while the bot is talking to the user in a private message instead of on the server. I thought putting the "server" variable as the server ID would help but it doesn't seem to do anything after the accept message.
// Awaits reply from user
if (message.channel.id === '541736552582086656') return target.send("Do you accept the challenge? Please reply with 'accept' or 'deny'.")
.then((newmsg) => {
newmsg.channel.awaitMessages(response => response.content, {
max: 1,
time: 150000,
errors: ['time'],
}).then((collected) => {
// Grabs the first (and only) message from the collection.
const reply = collected.first();
if (reply.content === 'accept'){
reply.channel.send(`You have ***accepted *** the challenge from ${challenger}. Please wait while your battlefield is made...`);
message.author.send(`${target} has accepted your challenge! Please wait while the channel is made for your brawl...`)
/// Problems start here
function createChannel(message){
var server = "SERVER ID";
var name = `${target} vs ${challenger}`;
message.guild.createRole({
role: {
name: `${target} vs ${challenger}`,
color: "#00fffa",
permissions: [] }
}).then(role => {
target.addRole(role, name)
challenger.addRole(role, name)
.catch(error => client.catch(error))
}).catch(error => client.catch(error))
server.createChannel(Name, name).then(
(channel) => {
channel.setParent("CATEGORY ID")
})
} // problems end here
} else if (reply.content === 'deny') {
reply.channel.send("You have ***denied *** the challenge.")
} else {
reply.channel.send("Your response wasn't valid.");
}
})
})
}
I have been wondering if I need to go about making the channel and role in a different way since it is trying to be made from a private message and not inside the server..
Thanks for any and all help! I also apologize if I'm using stack overflow too much for problems like this... You guys are great at helping me see different ways to do things and what I'm doing wrong, so I am learning, but I don't want to feel like I'm abusing it too much.
I think the problem is the fact that you create a function called createChannel with the code to create a rol and channel, but you never call said function.
You can either call the function after you've declared it or (which is in my opinion better) you can remove the following lines
function createChannel(message){
} // problems end here

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);
}

How to set error messages in specific cases in symfony2 login_check

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.

Cannot deserialize some tweets using NewtonSoft.Json

Hi All,
I am running a C# console app that is using the Twitter Stream API. My code is below
JToken json = JObject.Parse(ResponseStream.ReadLine());
For every +- 20 tweets, I get the following error "Error reading JObject from JsonReader".
I copied the json into JSONLint and it is valid, so I am perplexed to why this keeps happening. Has anyone else had this error?
Yes, and it just started happening recently. I believe it is either a bug with NewtonSoft.Json or a change in the twitter api causing it to send bad jsons. I did a packet capture and found the offending character by counting them, but I didn't see anything wrong. I think we will just have to wait for this bug to be fixed.
update
I downgraded Newtonsoft.Json.dll to 4.3.* and it works fine.
I found the issue. Sometimes the stream returns an empty string. Therefore parsing an empty string will throw an error. An example below on how I protected against it:
public static void ProccessTweet(object objMessage)
{
if(objMessage.ToString() != "")
{
var json = JObject.Parse(objMessage.ToString());
if (json["retweeted_status"] == null)
{
var message = ProcessNewTweet(json);
Db.Votes.Add(new FNBVote
{
Message = message,
Entry = Db.Entries.Find(message.Entry.EntryId)
});
return;
}
ProcessRetweet(json);
}
}

Resources