Keycloak: Indicate user is temporarily locked - single-sign-on

After a user has failed to log in too many times in too short a time; Is there a way to have the Keycloak login screen tell the user that they are temporarily locked, so they can know they have to wait and try again later?
At the moment it continues to tell them their password is wrong, so they will probably keep trying, and may end up being told their correct password is incorrect.
Ideally I'd like to be able to do this with only changes to the login theme, and without making extra API calls.

Yes It's available in the UserRepresentation returned by
GET /{realm}/users/{id}
You can also check brute force status on
GET /{realm}/attack-detection/brute-force/users/{userId}
The latter will only show if it's temporary disabled
You can make it without any extra API calls just use
Admin REST APIs (Get Users and Get Representation Of User)
it returns inconsistent values of attribute enabled after Max Login Failure" attempts exceeded
Description
Different returning values of parameter "enabled" (for given{uid}) between following two admin REST API requests after Max Login Failure" attempts exceeded.
Get representation of the user
GET /admin/realms/{realm}/users/{id} => "enabled":false
Get users
2.1 GET /admin/realms/{realm}/users => "enabled":true
2.2 GET /admin/realms/{realm}/users?search={string} => "enabled":true
Get status of a username in brute force detection =>
GET
/admin/realms/{realm}/attack-detection/brute-force/usernames/{username}
=> ("disabled":true)
Note: GUI Admin console returns user=disabled and locked after Max Login Failure attempts.

Related

AddUserToGroup (UserGroup.asmx) returns "success" but user not added (SharePoint 2016)

In SP2016 I'm making a call to the AddUserToGroup method of UserGroup.asmx. My function adds a user to a SharePoint permission group called "Supervisors".
If I supply a valid user account (in i:0#.w|domain\\username format), the call returns success, and almost always adds the user to the group. Sometimes, however, the user does not get added (although the call still returns success).
If I add a subsequent call to the GetGroupCollectionFromUser method, it returns a list of groups which include the target "Supervisors" group. But the user has not actually been added, and a refresh of the page will reflect that. How could that be?
The problem is not specific to a user, domain, or anything else that I can tell. The same user account may fail one time and succeed the next (returning success both times). The exact same problem occurs whether I use ASMX or REST (!!!). Verbose ULS logs have also not shed any light on the issue.
Has anyone seen this issue before?

Own authentication service uses too late

Once again I created my own authentication service. This is registered and is also called. After submitting the login form (EXT:felogin) you get back to the same page - but Felogin continues to show the login form. After a page reload, the logged-in state is recognized correctly and the status display is displayed.
The same form works correctly with a normal, local FE user.
When debugging authUser() correctly returns 200.
What could that be?
Besides returning 200 by authUser(), having a valid FE-User (at least with uid, pid, username, usergroup) is necessary. My FE-User was broken.
TYPO Documentation - Authentication services:
One important thing to know is that the TYPO3 CMS authentication process needs to have users inside database records (“fe_users” or “be_users”).

Facebook PHP SDK - getLoginUrl() - state value

I am using the PHP SDK getLoginUrl() function which works perfectly to log the user in. Once the user is redirected back to my page, the URL can come in two forms, see in the following link subsection 3: http://developers.facebook.com/docs/authentication/server-side/
Part of the return URL is a ?state= value. This value is supposed to be used to prevent Cross Site Request Forgery: http://developers.facebook.com/docs/reference/dialogs/oauth/
Though, using the getLoginUrl() method I can never set a state value as it is not one of the parameters: http://developers.facebook.com/docs/reference/php/facebook-getLoginUrl/
So how can I utilize the state-value to log a user into facebook and prevent CSRF?
So how can I utilize the state-value to log a user into facebook and prevent CSRF?
This is being automatically handled by the Facebook PHP SDK. If you were about to write your own API calls to Facebook, you would need to submit the state manually (if desired) as per Facebook's OAuth documentation.
When you create a login url with BaseFacebook::getLoginUrl(), the first thing the function does is to establish CSRF token state1, which creates a hash using PHP's core mt_rand(), uniqid() and md5() functions and also stores the value as a session variable.
When the user gets redirected back to your page the, FBSDK checks if the submitted state matches the state value in the session. If the values indeed match, the state is cleared from the Facebook object and from the session, so all subsequent getLoginUrl() requests would get a new state variable.2
Theoretically you could use your own state value with FBSDK by writing it to fb_<your_app_id>_state session variable before constructing the Facebook-object, as the BaseFacebook's constructor and establishCSRFTokenState() both check if the state already exists in the session.
But that would probably introduce more complexity than is necessary.
see BaseFacebook::establishCSRFTokenState()
see BaseFacebook::getCode()

FB.api('/page_id/admins/') throws (#210) Subject is not a page

So I have a page, and am trying to create an app that determines whether or not a user is an admin of that page. The documentation states to use page_id/admins/user_id, which I am. However, it keeps throwing the error "Subject is not a page," which is obviously is, and even when I get just the page, it's type is set to "page." Why am I getting this error, and how would I fix it?
You should use the Page access token when making this call - see https://developers.facebook.com/docs/reference/api/page/#page_access_tokens
The "subject" in this case is the page so you should use that access token.

What's the best action persistence technique for a Catalyst application?

I'm writing a Catalyst application that's required to have a fairly short session expiration (15 minutes). I'm using the standard Catalyst framework authentication modules, so the user data is stored in the session -- i.e., when your session expires, you get logged out.
Many of the uses of this application will require >15 minutes to complete, so users will frequently submit a form only to find their session state is gone and they're required to log back in.
If this happens I want to preserve the original form submission, and if they log in successfully, continue on and carry out the form submission just as if the session had not expired.
I've got the authentication stuff being handled by an auto() method in the controller -- if you request an action that requires authentication and you're not currently logged in, you get redirected to the login() method, which displays the login form and then processes it once it's submitted. It seems like it should be possible to store the request and any form parameters when the auto method redirects to the login(), and then pull them back out if the login() succeeds -- but I'm not entirely sure of the best way to grab or store this information in a generic/standard/reusable way. (I'm figuring on storing it in the session and then deleting it once it's pulled back out; if that seems like a bad idea, that's something else to address.)
Is there a standard "best practices" or cookbook way to do this?
(One wrinkle: these forms are being submitted via POST.)
I can't help thinking that there's a fundamental flaw in mandating a 15 minute timeout in an app that routinely requires >15 minutes between actions.
Be that as it may, I would look at over-riding the Catalyst::Plugin::Session->delete_session method so that any contents of $c->request->body_parameters are serialised and saved (presumably to the database) for later recovery. You would probably want some rudimentary check of the POST arguments to ensure they're what you're expecting.
Similarly, create_session needs to take responsibility for pulling this data back out of the database and making it available to the original form action.
It does seem like a messy situation, and I'm inclined to repeat my first sentence...
UPDATE:
Whether you use delete_session or auto, the paradoxical issue remains: you can't store this info in the session because the time-out event will destroy the session. You've got to store it somewhere more permanent so it survives the session re-initialization. Catalyst::Plugin::Session itself is using Storable, and you should be able to with something along these lines:
use Storable;
...
sub auto {
...
unless (...) { #ie don't do this if processing the login action
my $formitems = freeze $c->request->body_parameters;
my $freezer = $rs->update_or_create(
{user => $c->user, formitems => $formitems} );
# Don't quote me on the exact syntax, I don't use DBIx::Class
}
...
my $formitems = $c->request->body_parameters
|| thaw $rs->find({$user => $c->user})->formitems
|| {} ;
# use formitems instead of $c->request->body_parameters from here on in
The underlying table probably has (user CHAR(x), formitems TEXT) or similar. Perhaps a timestamp so that nothing too stale gets recovered. You might also want to store the action you were processing, to be sure the retrieved form items belong to the right form. You know the issues for your app better than me.
I would store the form data as some sort of per user data in the model.
Catalyst::Plugin::Session::PerUser is one way of doing that (albeit somewhat hackishly). I would reccomend using the session plugin only for authentication and storing all the state info in the model that stores your user data instead.
And I totally agree with RET's opinion that the 15 minute limit seems really counter productive in this context.
I came across this whilst searching CPAN for something entirely unrelated.
Catalyst::Plugin::Wizard purports to do exactly what you need. The documentation suggests it can redirect to a login page whilst retaining the state of the previous action.
NB: I haven't used it, so can't vouch for its effectiveness.
In the end, we ended up grabbing the pending request (URL+params) in the auto(), serializing and encrypting it, and passing it via a hidden form element on the login page. If we got a login request with the hidden element populated, we decrypted and deserialized it and then redirected appropriately (making sure to pass through the standard "can this user do this thing" code paths).
You could always have some javascript on the client that keeps the session from expiring by making a small request every few minutes.
Or you could have AJAX check for an active session before posting the form and presenting the user with a new login box at that time if needed.