Hi,

I wanted to block the user after 3 wrong attempts of login and then send users the email with the link to get themselves unblocked. For blocking after 3 attempts, I have already changed the site properties for maxfirstbackoffattempt and maxsecondbackoffattempt but have no idea how can I unblock the user once he clicks on the link in the email. Please help!!


Thanks in advance,

Shivya Pant

Hi Shivya,

You have two actions in the Users espace called User_Unblock and IPAddress_Unblock. You can use these in an action of the screen that you send to your users to unblock them.

I believe they also need to be invoked by a user with the UserManager permission. Since this is a bit contrary to your self-service unblocking use case, you might have to clone them and adapt them by removing this validation.

Hi Afonso,

Thank you for your reply. But I guess it is not that easy to manipulate these methods, they have a lot of dependencies. 


Regards,

Shivya Pant

Hi Shiva,

Why not just try, it is not that difficult.

Regards,

Daniel

Shivya Pant wrote:

Hi Afonso,

Thank you for your reply. But I guess it is not that easy to manipulate these methods, they have a lot of dependencies. 


Regards,

Shivya Pant

You won't be manipulating them - since the Users module is a System module you can't do any changes to the existing code, Service Studio will always force you to clone the module:

You can then create a clone and remove the UserManager permission checks inside the Unblock methods:

There's no risk to any existing dependencies because you aren't making changes to the current code.

Hi Afonso,

Thank you for your reply again. Will try this out and will let you know. 

Regards,

Shivya Pant

Afonso Carvalho wrote:

Hi Shivya,

You have two actions in the Users Espace called User_Unblock and IPAddress_Unblock. You can use these in an action of the screen that you send to your users to unblock them.

I believe they also need to be invoked by a user with the UserManager permission. Since this is a bit contrary to your self-service unblocking use case, you might have to clone them and adapt them by removing this validation.


Hi Afonso,

I tried implementing the solution but still, it is asking for the User Manager role. I am attaching the file for your reference. 

Thanks & Regards

Shivya Pant

Your changes look correct. Are you referencing your new, cloned actions in your code, or are you pointing to the old ones? Are you calling them in a Screen in a new application, or are you trying to use one of the existing screens from the Users application?

Afonso Carvalho wrote:

Your changes look correct. Are you referencing your new, cloned actions in your code, or are you pointing to the old ones? Are you calling them in a Screen in a new application, or are you trying to use one of the existing screens from the Users application?


Hi Afonso,

Actually, I was referencing the methods of the Users, my bad!! Thank you for your support and guidance so far. Now, I am able to get the status. I have already set the cloneofusers site properties MaxUsernameAttemptsFirstBackoff to 2 and 

MaxUsernameAttemptsSecondBackoff to 1 

but every time I am checking the User_GetBlockedStatus it always shows unblocked even after the third attempt. If you can please guide what else should I set?


Thanks & Regards

Shivya Pant

Your server won't look at those site properties because the original Users is your User Provider - what this means is the only purpose of your clone should be to provide those two Unblock methods you are using in your code. Everything else should be done through Users:

 - Configure the original Users site properties to perform the limits you want;

 - In your code, when you want to unblock specific users, use the new actions from the cloned Users espace.

Let us know if you need any more help.

Sorry, I've also just noticed this: I assumed the LoginAttempt Entity that the Unblock methods use is a System Entity, but it is not: it belongs to the Users module. Did you completely isolate the Unblock methods that you need?

I think what's happening is, when you clone the Users to get your Unblock method clones, you are also cloning the LoginAttempt Entity, and since this is a blank Entity with nothing writing to it (your original Users espace is what controls your users, not your clone), nothing happens.

What you need to do is, clone both Unblock actions, but then make sure that they use the LoginAttempt Entity of the original Users espace, and not the cloned Entity inside your Users clone.

Hi Afonso,

But the cloneofusers is using the  LoginAttempt Entity of the Users only. I have also cloned the User_GetBlockedStatus to check the status. 


Thanks & Regards

Shivya Pant

It's a little trickier to diagnose then: if you corrected the Site Properties on the original Users espace and if you're already using the original LoginAttempt in your clone, I'd advise you to call both methods - the original and your clone, and compare results. Try to see where they differ while debugging - it's possible we both missed something that still needs to be changed.

Hello Shyvia and Afonso,

Aren't you both overcomplicate something that possibly is simple?

You have the action to unblock a user. If the action requires a user with a UserManager role (not sure), just do this in the action that should unblock a user:

1. Log in dynamically with a special user that has the UserManager role (you can use the Login action from System)

2. Execute the unblock

3. Log out and redirect to the Login page.

You can also have a user that does not have the UserManager role. In this case, in the action, before login with this user, Grant the UserManager role (it is public, you can reference it from Users), execute the action and at the end Revoke the UserManager role from this user.

I don't think you need to clone the Users at all.

Cheers.

Hi Afonso Carvalho,

I'm currently helping Shivya implementing this feature - I followed your approach and it's working.

You mentioned that when we clone the users module, the LoginAttempt entity is also cloned - which is true - so we need to make sure that our server actions inside the clone use the original entity and not the cloned one. However, how can I achieve this? As far as I understand, I can't import as dependency this entity from the Users module, I believe it's not a public entity.

That being said, I manage the get this working by using the Login server action from the clone and not from the original module.

Regardless, I have a question, are there any implications of using a users module clone?

Thanks for your help,

Ricardo

Hi Ricardo, 

You don't achieve. Once you start using a cloned module to deal with Users internal entities, you need to replace the Users for your own cloned module as User Provider of your application. 

Cheers

Eduardo Jauch wrote:

Hi Ricardo, 

You don't achieve. Once you start using a cloned module to deal with Users internal entities, you need to replace the Users for your own cloned module as User Provider of your application. 

Cheers

Hi Eduardo,

Do I need to replace other actions like CheckUser_Existence, Create_User, and others with the CloneOfUsers actions also? 

Also, are there any implications of using the clone and not the Users directly?

Thanks & Regards

Shivya Pant

Hi Shyvia,

The Users module is just a front end for the Users API. But as it is a System module, you can't change it. If you clone it because you need to use things that are not available to reference (are not public), then you need to start using it as the User Provide (afaik).

The implication is that you will be using a new User Provider. This is not problematic per se.

But I am not convinced that you NEED to do it.

You can implement your own attempts control and keep using the Users as User Provider and the Users Login, for example.

Cheers.

Eduardo Jauch wrote:

Hi Shyvia,

The Users module is just a front end for the Users API. But as it is a System module, you can't change it. If you clone it because you need to use things that are not available to reference (are not public), then you need to start using it as the User Provide (afaik).

The implication is that you will be using a new User Provider. This is not problematic per se.

But I am not convinced that you NEED to do it.

You can implement your own attempts control and keep using the Users as User Provider and the Users Login, for example.

Cheers.

Hi Eduardo,

Thanks again for your response. Actually, I also tried using the grant UserManager action but it did not work. I don't know why?


Thanks & Regards

Shivya Pant


I checked the actions and they do require the UserManager role, otherwise they'll throw an Exception.

Those are all valid alternatives, in that they'll work and perform what Shivya is asking. To me, it's a matter of architectural preference. Creating a special user that you then become dependent on for your logic does not look very clean to me - it's adding another dependency to your application that you'll have to keep track of.

Same with granting a Role only to revoke it within the context of the same action - I admit this last one comes out to feeling, but it doesn't strike me as correct to use a Role only to bypass a restriction and then to immediately remove it. A Role identifies a User as having permission to take a restricted action or view restricted information. Granting and removing it afterwards means your User is not entitled to have it. It has all the classic signs of a code smell.

Implementing your own version of login attempts control looks a more solid option, but would be the most complex out of the three.