Keycloak password reset link still works after generating a second one - keycloak

I am using Keycloak as an identity provider. I was testing the forget password flow and I noticed that if I try the forget password twice before setting the new password, two emails are sent. Everything ok. But then, I can use both links I get in the email inbox to reset the password.
The first link shouldn't work anymore after the second one is generated.
I tried to go over the keycloak options but I cannot find anything regarding invalidating the links after new ones are generated.

Related

Can you send a link to the specific page where a user resets their password via Keycloak's API?

We have a PHP/MySQL based User Management System and are integrating it with Keycloak version 16 where we will store users credentials.
Our application does not allow users to self register. We create user accounts on the system. When we do this we do NOT specify a password because we want users to set up their own password.
The current system sends 2 separate emails in 2 different circumstances regarding passwords:
If it's a completely new user who does NOT have an existing password, we send them a link to set up a password.
If it's an existing user who already has a password, the system allows them to reset it, e.g. if they forget their password and can't login.
Keycloak seems to cater for scenario (2) because the login forms have a forgotten password link which opens a form where the user can enter their email address and receive a link which lets them do (2).
Unfortunately it doesn't deal with scenario (1) very well and that's where our problem starts. This has been asked a while ago Send password forgotten mail but it seems that Keycloak didn't support this very well in 2020 and perhaps still doesn't now.
Our "workaround" to this was that we added custom email templates and a custom page (reference: Themes on https://www.keycloak.org/docs/latest/server_development/#emails) which includes wording that caters for both scenarios, e.g. "set your password" rather than "reset your (existing) password". The result of this is that our email and form now reads appropriately for both scenarios (1) and (2).
The problem
We want to be able to send a link to the user that allows them to set their initial password to cover scenario (1).
We know that this page exists because on the login page for Keycloak there is a link to the forgotten password form that handles scenario (2). However, the form requires the user to enter their email address and submit the form. The user then receives an email from Keycloak which contains a URL to the page where they can do this. The URL has the following format:
https://example.com/auth/realms/foo/login-actions/action-token?key=...
The key= contains a ~945 character token. Going to the URL above redirects to the form where the user can reset their password. This next URL does not contain a token but a cookie has been set in the browser - by the previous URL - which makes it functional:
https://example.com/auth/realms/foo/login-actions/required-action?execution=UPDATE_PASSWORD
We can't send either of these URLs to the user because the first one (containing key=) has no API method for us to find out what it is - it's only possible to generate this by going through the "forgotten password" step during login, in the browser.
The second URL (/login-actions/required-action...) won't work either because it relies on the previous URL (containing key=) setting the cookie in the browser. If you try and go to this second URL directly (i.e. bypassing the first URL) it will error.
So neither of these URLs will work because we can't find what the first one is programmatically, and we can't use the second one without knowing the first one.
I found https://lists.jboss.org/pipermail/keycloak-user/2018-October/015910.html and the suggestion is using the Keycloak API to trigger a password reset email. This works - sending an HTTP PUT request containing 'UPDATE_PASSWORD' along with the relevant user ID sends the user an email. The request endpoint has the format PUT /{realm}/users/{id}/execute-actions-email which is documented on the link above.
Up to here all is fine - the user gets an email. However, this email does NOT contain a link that goes directly to the "reset password" page! Instead it sends them an email containing the following text:
Your administrator has just requested that you update your account by performing the following action(s): Update Password. Click on the link below to start this process.
Link to account update
When the user clicks "Link to account update" it then shows them a web page like this:
It is only when they click on the link on this page (the one that says "click here to proceed" on the screenshot) that they arrive at the form where they can reset their password.
This is a really poor user experience because the user gets sent a (badly worded) email with a link to... a page with another link! It should just take them to the password reset page directly. What's more frustrating is the fact that Keycloak is clearly capable of generating/sending the exact email we'd like in this scenario: the one which gets sent when a user manually does a password reset via their browser.
So the problem seems that Keycloak's API doesn't support this incredibly important and common use-case of a user being able to set an initial password, in a user-friendly manner.
I am adding the js script in the template to automatically click "click here to proceed". It's ugly but at least the user doesn't see the page

Locked out of GSuite Admin after domain verification

I have signed up for Gsuite Essentials and attempted up upgrade to Gsuite Enterprise. I only have a single email address eg a#abc.com. I had already been using this account as a normal google account. (no gmail though).
I couldn't get the admin console to show the upgrade option, but found I needed to verify my domain. So I added the TXT record to my domain abc.com, which would then let me verify.
I could then log in to the admin console as a#abc.com and clicked on the upgrade option and completed the process. This then let my a#abc.com user have access to Gmail. I have not transferred any domain settings over to google, that is all still externally hosted.
I can now no longer log in to the admin console, it says that my a#abc.com account doesn't have the rights and I need to log in as the administrator. There is no other account linked to the Gsuite settings, so there is no other administrator. I can still log in to the normal google account and do the same functions as previous.
I have now removed the TXT record hoping that would cancel it out again.
How do I get access to the admin side again?
Side note: What I am mostly worried about is that I put my credit card details into the signup, but can't get into the admin page and can't contact any form of support. It is literally impossible to get support to use the serve I paid for.
First thing first, the txt records are a string for the only purpose to verify the ownership of the domain therefore deleting them won't change anything you only need this record for the verification process and once is done you can delete them.
As an example is like a text message sent to your mobile phone, if you delete the message nothing will happen right?
I tell you this so you won't more time on the domain DNS zone settings because the issue is not there and you won't solve the problem.
There may be few things that may have happened.
The first thing you should do is to navigate in an Incognito page, make sure that is the only incognito page that you have opened and log in with a#abc.com.
Try to run different test in incognito, the issue really looks like that you are logged in with multiple Google Accounts and when you go do admin.google.com it picks up the wrong one. That's why you should go in incognito.
EDIT
Use as reference this link Here.
Follow the steps in Paragraph 'I'm taking control from another admin' here the steps:
Go to the G Suite Essentials sign-up page.
2, Sign up using your email address at the domain you're verifying.
Use an address where you can get mail.
Follow instructions in the Setup Wizard to become the admin who manages G Suite Essentials for all users at your organization.
If this didn't solve the issue then you should contact the Google Support and they will tell you what happened.
The thing is that if you can't access the Google Admin you won't be able to contact the Google Support, hence you should follow this:
.1 Can't sign in to the Admin console: https://support.google.com/a/answer/6335621?hl=en

How to make Moodle include user passwords in the e-mails it sends?

I'm looking for a way to make Moodle 2.9 include user passwords in the introductory e-mails it sends upon manual upload of CSV table with new user data.
So far it is sending introductory e-mails with text that is set up in the local_welcome plugin that is configurable via
Plugins/Local Plugins/Moodle welcome
This text contains fields such as [[username]], [[fullname]] which get replaced by the actual values, but no such field as [[password]].
I have tried including both [[password]] and {$a->newpassword} in the text but neither works, Moodle does not replace these strings with the actual password; these strings are sent verbatim instead. This happens irrespective of whether the passwords are uploaded via the CSV or generated.
So far I had no luck finding a solution to this on the web. The official help page on this function is unfortunately empty:
https://docs.moodle.org/29/en/admin/setting/local_welcome
Strangely enough, when I create just one user by hand in Moodle via
Users/Add a new user,
the e-mail it sends to the user is not that from plugin local_welcome. A string defined somewhere in the moodle php files is used. This contains string {$a->newpassword} and it works as expected; the user obtains both username and password.
How do I make bulk upload behave similarly? I'm looking for any doable way to make this work. If my question is not clear, please ask in the comments.
Sending plain password over email is not secure that's why Moodle prevent it.While uploading user record you can follow these steps,
enable Generate password and notify user.
or,
set your own password and enable Force password change.
It depends on configuration of bulk upload
Password field: (...) If omitted, a password will be generated for
each user (during the next Cron job) and welcome e-mails sent out.
https://docs.moodle.org/29/en/Upload_users#Fields_that_can_be_included
Just udate all existing users with the same password using csv file. Then use Moodle welcome to send bulk email with their different user name using [[username]] and then type the default password you chose in csv. And it is better to force change password after first login

Password change update password manager best practice

What is the best practice for dealing with a user changing their password and letting their password managers getting the notice of the change?
If a user request a "forget password" link, the user gets often redirected to a specific page where he can set a new password. After filling this info in, the password is being set on the backend and gets redirected to the logged-in homepage.
But this doesn't pops up or updates the in-browser save password dialog/system/keychain/manager. They mostly get triggered when there is also a text field on the form.
I could redirect it to the login page, but that seems a bit stupid since the user just entered their password, and have to do it again.
I notice this with linkedin a lot and google as well, that when I changed my password, some pages still try autofilling my old password and I get a notice that my password is incorrect.
Does anyone knows how exactly cross-browser all these system work? Or isn't there a standard for triggering/updating password managers? And what seems the best practice? If you log a user auto in after a change, there is a quite big change he again forgets it in a few days. It's bizar how many people enter wrong passwords at a login screen.

What is a secure and efficient method for website users to reset their password?

Many sites implement different methods and I am having a hard time deciding on which method would work best for my site.
My user profiles contain the following data:
username
password (in hash/digest form)
email
I'd like the password reset method to be secure, user-friendly, and efficient.
You should add two fields, reset_code and reset_expiry
This is the process for a secure password reset functionality.
User selects "Forgot password".
User prompted for email/username.
If valid, generates a GUID, and stores it in reset_code and also stores Now()+24 hours in reset_expiry in the database against that particular user.
Then it sends an email to the email address with a link to confirm the password reset. This email would contain a link to your website with the user's username AND reset_code embedded. (This stops a malicious user resetting a third parties password just by knowing their email)
Once the user clicks on the link in the email, they will be directed to your website.
Your website will validate that: the username and reset_code matches, and the current time hasn't exceeded the reset_expiry time.
If all is okay, we can complete the password reset. This can be done by either:
a) Onscreen a new randomly generated password
b) A new randomly generated password via email
c) The ability to enter a password of his/her own choosing
You should not store the passwords of your users, not even in encrypted form. You should only store the hash/digest necessary for authentication. Then, you can't "recover" the password (because you don't know it), you can just reset it, and/or give the user a temporary one-time password that allows him to set a new password.
Update: if you are doing the above, the standard procedure is to have a "require-password-reset" form. The user enters his id (typically his email) and a "token" (eg, a random string) is generated, stored in some table with some expiration date, and sent to his email along with a link to the "password-reset" form. In this form the token is checked, the user is allowed to enter a new password, and instructed to attempt a new login.
Update 2: A small privacy issue might arise: What should we do if the user id (email, user name, or whatever) entered in the request form does not exist in our database? To output a message "User does not exist. Check the id and retry." may be ok, but in some cases it would cause a privacy problem: anyone can check if other someone is registered in your database! If you want to avoid that, you must output the same message ("a mail has been sent with instructions...") even if the user wasnt found (and hence a mail was not actually sent).
Similar privacy issues advise to just output the message "login incorrect : bad user or password" when the user tries to login unsuccessfully - don't disclose if it was an incorrect user or password.
I agree with Leonbloy. Storing the password leads to trouble like the Gawker incident from a few weeks ago (1.5 million userid/pwd combinations were discovered and published).
You should, however, have a "reset password" function that e-mails the new password to the original e-mail address used to open the account.
There should be no provision for changing the e-mail address during the password reset. If the user doesn't have access to the old e-mail account anymore, too bad. Abandon the account and start over.
And use a good Captcha on the reset screen.