OIM - PasswordMgmtService.validatePasswordAgainstPolicy : Issue with password history condition in policy being bypassed - oim

I am working on a custom OIG password management requirement for a client.
I am facing issue while validating the password history in policy definition (eg: shouldn't match last 5 passwords used).
For some reason, PasswordMgmtService API's validatePasswordAgainstPolicy method is bypassing the history validation and returning true if user enters any old password.
Below is the code snippet for reference.
public ValidationResult validatePasswordRACFPolicy(String loggedinUserKey, char[] userPassword)
{
PasswordMgmtService pwdMgmtSvc = oimClient.getService(PasswordMgmtService.class);
User usr = new User(loggedinUserKey); //loggedinUserKey is user key of logged in user
ValidationResult valResult = pwdMgmtSvc.validatePasswordAgainstPolicy(userPassword, usr, <App Instance Name>, Locale.getDefault());
IDMLOGGER.log(ODLLevel.FINEST, "Is Password Valid = " + valResult.isPasswordValid()); //this value is true even if user tries to reset password using any older passwords.
return valResult;
}
Eventually, ending up with exception when I try to update the account password on target.
provSvc.changeAccountPassword(Long.valueOf(accountId), userPassword);
//provSvc is ProvisioningService API object, accountId is oiu_key, userPassword is the password entered by user.
Here are the exception details:
GenericProvisioningException An error occurred in oracle.iam.provisioning.handlers.ChangeAccountPasswordActionHandler/execute while changing the password for account with id 1234 and the casue of error is {2}.[[ at oracle.iam.provisioning.util.ProvisioningUtil.createEventFailedException(ProvisioningUtil.java:175) at oracle.iam.provisioning.handlers.ChangeAccountPasswordActionHandler.execute(ChangeAccountPasswordActionHandler.java:84 ... ... Class/Method: tcOrderItemInfo/validatePassword Error : Password Does Not Satisfy Policy

Related

Login social with laravel socialite create password

How to inclues password after login with social network with laravel socialite? (sorry for bad english)
Com criar/incluir senha fazendo login a partir de uma rede social com o laravel socialite?
code on my LoginController
public function handleProviderCallback($provider)
{
$user = Socialite::driver($provider)->stateless()->user();
$authUser = $this->findOrCreateUser($user, $provider);
Auth::login($authUser, true);
return redirect($this->redirectTo);
//return $user->token;
//dd($userSocial);
}
public function findOrCreateUser($user, $provider)
{
$authUser = User::where('provider_id', $user->id)->first();
if ($authUser){
return $authUser;
}
return User::create([
'name' => $user->name,
'email' => $user->email,
'provider' => strToUpper($provider),
'provider_id' => $user->id
]);
}
In the socialite flow, a user will never need a password
You can set password to nullable() in the users migration file.
In 'Account Settings' a user can set a password, leaving the current password empty
Once the password is set, a socialite user can login via both social media or direct
I did two different implementations :
Generate a random password, save it with user object and send you
user an email with the auto generated password.
Create a middleware to check if password is NULL or not set and
redirect user to a form to enter password.
The objective of using the socialite authentification is that the user won't need a password.
BUT if somehow the user want to have a password, like i had earlier in one of my projects, he can easily click on forget password and he will receive a link via email to reset new password

DDD modelisation issue (entity accessing repository)

I am designing the model of the following business needs :
The application must be able to register Users
The steps of the User registration are :
The user enters an email address and confirm
A verification code is sent to the provided email address.
The user must enter the correct verification code to continue
Repeat steps 1-3 for a phone number with verification code by SMS (optional)
The user then enters some personal information and confirm => the account is created
After registration, the user can update his email address or mobile phone number, but must go through the same verification process (code sent which must be entered to confirm the modification)
I ended up with the following model :
Verifiable (interface)
User (entity)
EmailAddress (value type, is a Verifiable)
MobilePhoneNumber (value type, is a Verifiable)
RandomCode (value type)
VerificationCode (entity containing a Verifiable, a RandomCode and a generationDateTime)
VerificationEmail (aggregate containing a VerificationCode, an EmailAddress and a Locale)
VerificationSms (aggregate containing a VerificationCode, a MobilePhoneNumber and a Locale)
Then here come the questions !!
Is it correct to have the Verifiable interface in order to have a VerificationCode instead of having EmailVerificationCode and SmsVerificationCode ? (Although it's not really a part of the ubiquitous language)
As I must persist somewhere the tuple emailAddress/mobilePhoneNumber + randomCode + generationDateTime to be able to retrieve it for verification, is it ok to have a specific entity for this ?
When the user wants to update his email address I was expecting to do something like :
// In the application service
User u = userRepository.findByUid(uid);
u.updateEmailAddress(newEmailAddress, enteredCode);
userRepository.save(u);
// In the User class
public void updateEmailAddress(EmailAddress newEmailAddress, String code) {
// Here comes the direct repository access
VerificationCode v = verificationCodeRepository.findByVerifiable(newEmailAddress);
if (v != null && v.hasNotExpired() && v.equalsToCode(code)) {
this.emailAddress = newEmailAddress;
verificationCodeRepository.delete(v);
}
else {
throw new IncorrectVerificationCodeException();
}
}
but to prevent my entity accessing a repository I ended up with the following code :
// In the application service
User u = userRepository.findByUid(uid);
VerificationCode v = verificationCodeRepository.findByVerifiable(newEmailAddress);
if (v != null && v.hasNotExpired() && v.equalsToCode(code)) {
verificationCodeRepository.delete(v);
u.updateEmailAddress(newEmailAddress);
userRepository.save(u);
}
else {
throw new IncorrectVerificationCodeException();
}
// In the User class
public void updateEmailAddress(EmailAddress newEmailAddress) {
this.emailAddress = newEmailAddress;
}
But it looks like an anemic model and the business logic is now in the application layer...
I am really struggling to correctly design the model as this is my first DDD project, any advice, modelisation suggestion is welcomed...
There is nothing wrong passing a repository as an argument in your updateEmailAddress() method.
But there is a better alternative, a domain service:
Your domain service depends on the repository and encapsulates the logic bound to your verification. You then pass this service to the user entity which is in charge of calling the correct method.
Here is how it could looks like:
class EmailVerificationService {
VerificationCodeRepository repository;
boolean isCodeVerified(EmailAddress emailAddress, String code) {
// do your things with the repository
// return true or false
}
}
Then in the user class:
class User {
// ...
public void updateEmailAddress(EmailVerificationService service, EmailAddress emailAddress, String code) {
if (service.isCodeVerified(emailAddress, code)) {
this.emailAddress = emailAddress;
} else {
// throw business Exception ?
}
}
}
In your application service, you inject the domain service and wire everything, catching the eventual exception and returning an error message to the user.
This is a suggestion of modeling, if you want to take it into account. Hope it could help you. I would model it this way:
User (aggregate root entity)
id
emailAddress (not null and unique)
mobilePhoneNumber (optional)
personalInfo
enabled (a user is created disabled when the registration process starts, and it is enabled when the process ends successfully)
VerificationCode (aggregate root entity) ===> it is associated to a user
id
randomCode
expirationDate
userId
smsOption (boolean) ===> if sms option is true, this verification code will be sent in a SMS to the user (otherwise it will be sent by email to the user)
Static Factory meethods:
forSendingByEmail ==> creates an instance with smsOption false
forSendingBySMS ===> creates and instance with smsOption true
Domain Service: sendVerificationCodeToUser ( verificationCodeId ) ===> checks smsOption to send either an SMS or an email (to the mobilePhoneNumber/emailAddress of the associated userId)
DomainEvent: VerificationCodeWasCreated ===> it has the id of the verification code that has been created
Raised by the VerificationCode constructor
The listener will call the domain service: sendVerificationCodeToUser(verificationCodeWasCreated.verificationCodeId())
THE REGISTRATION PROCESS (application service methods):
(1) The user enters an email address and confirm
public void registerUser ( String email ):
checks that doesn't exists any enabled user with the given email
if exist a disable user with the email, delete it
creates and persist a new disabled user with the email
creates and persist a new verification code associated to the created user for sending by email
(2) A verification code is sent to the provided email address ===> it is done by the domain event listener
(3) The user must enter the correct verification code to continue ===> the user who was sent the email in step (1) has to enter the email again, and the code he received)
public boolean isARandomCodeCorrectForUserEmail ( String randomCode, String email ) {
User user = userRepository.findByEmail(email);
if (user==null) {
return false;
}
VerificationCode vcode = verificationCodeRepository.findByRandomCodeAndUserId(randomCode,user.id());
if ( vcode==null) {
return false;
}
return vcode.hasNotExpired();
}
(4) Repeat steps 1-3 for a phone number with verification code by SMS (optional)
(4.1) The user of step (3) enters mobile phone number (we know the user id):
public void generateCodeForSendingBySmsToUser ( String mobilePhoneNumber, String userId ):
update user of userId with the given mobilePhoneNumber
creates and persist a new verification code associated to the user for sending by SMS
(4.2) The event listener sends the SMS
(4.3) The user who was sent the SMS in step (4.2) has to enter the email of step (1) again, and the code he received by SMS ===> isARandomCodeCorrectForUserEmail(randomCode,email)
(5) The user then enters some personal information and confirm ===> the account is created ===> what I do is enabling the user, since the user is already created, and we know the userId from step (3) or (4.3)
public void confirmRegistration ( PersonalInfo personalInfo, String userId ):
update user of userId with the given personalInfo
enables de the user
THE EMAIL/MOBILEPHONENUMBER MODIFICATION PROCESS:
It is similar to the registration, but the email/mobilePhoneNumber entered at the beginning must belongs to an existing enabled user, and at the end an update of the user is performed, instead of enabling.
ENABLED/DISABLED USERS:
Having enabled and disabled users, makes you taking it into account in authentication and authorization methods. If you don't want to or you're not allowed to have enabled/disabled users, you would have to model another aggregate that it would be UserCandidate or something like that, just with id, email and mobilePhoneNumber. And at the end of the process, create the real user with those values.

Bug in ASP.NET Identity's UserManager

MVC5's UserManager seems to have a bug:
My Code:
public void InsertUser(KoreUser user, string password)
{
var appUser = new ApplicationUser
{
UserName = user.UserName,
Email = user.Email,
LockoutEnabled = user.IsLockedOut
};
userManager.Create(appUser, password);
}
THis code works perfectly fine in almost all cases.. the exception being when the UserName contains a space.. for example:
JohnDoe - fine
John Doe - not fine..
In the latter example, it silently fails; no exception thrown.. what's the problem here?
It isn't a bug. An exception isn't thrown because it's reasonable to expect an invalid username in the land of user authentication.
The default check done when creating a username uses regex pattern ^[A-Za-z0-9#_\.]+$ to validate the name before creating the user. A whitespace character doesn't pass this test.
Another note is that the Create method of Usermanager returns an object of type IdentityResult. Using that object you can check for success and see what errors are being returned in the event that a user is not created.

PasswordCredentials.Password is always empty in PasswordVault

I am trying following code to store username password in windows phone 8.1 PasswordVault it stores data but when I retrieve back password field is always empty.
PasswordVault passwordVault = new PasswordVault();
passwordVault.Add(new PasswordCredential("MyResouceKey", "username", "Password"));
// Retrieval
var credential = passwordVault.FindAllByResource("MyResourceKey");
return credential.Password; /// it is always empty.
the password is always empty
You need to call credential.RetrievePassword() before getting the Password property.
http://msdn.microsoft.com/en-us/library/windows/apps/windows.security.credentials.passwordcredential.retrievepassword

Rails has_secure_password: is it actually hashing the password in the DB?

Using typical Rails 4.1 app with has_secure_password and the User model has a password_digest column in the DB. When I create a new user, I can still access the plaintext password in the console:
# in rails console
> u = User.new(email: "test#test.com", password: "password")
> u.save
> u.password => "password"
> u.password_digest => "xjdk..."
However, when I close the console session and start a new one, I can no longer retrieve the plaintext password:
# close above console session and open a new one
> u = User.find_by(email: "test#test.com")
> u.password => nil
I'm assuming that the plaintext password is only retrievable in the first situation because it's being stored in memory and when I call u.password => "password" it is retrieving the value from memory, NOT the database.
I had always thought has_secure_password stored the (salt + password) as a hash and I thought that meant it was theoretically impossible (if I can use that terminology) to reverse the password_digest and get the original password.
I'm just making sure my assumption that the password is stored as a real hash (ie, can't retrieve original password) is valid. I've read the Rails has_secure_password API but it didn't clarify my question.
You are correct — the DB is only saving the hashed password, not the password itself. You can confirm this by accessing the database directly using the read_attribute method (http://www.rubydoc.info/docs/rails/3.0.0/ActiveRecord/AttributeMethods/Read):
> u = User.new …
> u.read_attribute(:password_digest)
=> # Some hash
> u.read_attribute(:password)
=> nil
Incidentally, also make sure your User model does not have a password column. Otherwise it would save the password directly, defeating the purpose of hashing the password.

Resources