Keycloak Forgot password duplicate emails - keycloak

Keycloak sends out duplicate emails when you hit Forgot password button right after user session expired and you want to login again.
It might be configuration issue with Keycloak but it is quite annoying so any help would be appreciated.
Keycloak client is set to public and used in combination javascript adapter on mobile app.
Steps to reproduce:
Login with your user account using public client.
Wait for your access token to expire and you will need to login again.
Go to login page and instead of login hit Forgot password button.
Enter your email and hit submit.
You get your first forgot password email.
You will be redirected to login-page-expired and on "click here" link.
You get your second password email (which shouldn't happen).
Used Keycloak version is 12.0.1.

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

allow less secure app access in Yahoo mail

I need to allow less secure app access in Yahoo but I can't find the button :(
Any ideas ?
Regards,
Finally found it,
Go to ‘Generate App Password’ then select MacMail(in my case I use it) then copy past the generated code instead of your password.
Tested and working (2021)
The answer already provided by #zackzulg (see below). I have extended it.
'Less secure apps/services' don't support Yahoo's own sign-in method. An app password is a long, randomly generated code that gives a non-Yahoo app permission to access your Yahoo account.
Some older, third-party email apps (that do not use our Yahoo branded sign-in page) require you to enter a single password for login credentials. To access your Yahoo Mail account on these apps, you'll need to generate and use an app password.
Log into your Yahoo email account
Click your name on top right
Click the text 'Account info'
Select 'Generate App Password'
Click 'Get Started'. if its your first time
Add your "App's name" (Any name, for your reference)
Click 'Generate Password'
Copy this password and go to your app and instead of yahoo password enter this one.
What you need to know about 'Generate App Password'
You'll only need to provide this code once to sign in to your third-party app.
It does not replace your normal password.
If you are stop using the app you can delete this password from the same place.
For yahoo smtp configuration for used on third party app,need to generate app password. below step follow
1 Please login to your yahoo account and after login top right side Username show, please hover mouse on this username ,Click on Account information Link.
2 Go to Account Security tab, Go to App password Section, and Click on Generate and manage app passwords, Type app name and click on generate Password.
This is your smtp email password
Now set yahoo smtp configuration
Smtp Address : smtp.mail.yahoo.com
Smtp Port: 587
Smtp Username: Your yahoo Email
Smtp Password: Password is which you generate app password
Enable SSL: True
i get this information from this link
http://w3teachers.com/javascript-problem/How-to-set-up-Yahoo-smtp-configuration-for-use-on-third-party-app
This works as of June 29, 2022. I am using the latest version of java mail (1.6.2) - it has since moved to jakarta and angus so those jars may also work but I didn't try them. Get the jar here.
Set up your smtp settings to use port 465, SMTPS, and STARTTLS with outgoing server smtp.mail.yahoo.com
Generate an app password in Yahoo and use this in place of your usual password. Do this by logging into your yahoo mail account, click on your profile pic, and in the drop down choose "Account Info." Choose "Account Security" and on this page select "Generate App Password". I read something that said you need to use the company name in the app name so that's what I did.
after some time (in my case 2 months) that password stops working and you need to generate a new password for your app. otherwise you get the "too many bad auth attemps" error.

Keycloak automatic login after email confirmation with disabled user

We're using keycloak (KC) with custom providers for the registration flow. At the end of the registration flow, before the confirmation email is sent to the user (as a default KC functionality), we disable the user as it fits our use case.
When user clicks on the email confirmation, mail is confirmed and user is automatically logged in, despite the fact he/she is disabled at that point. Logins after that work as expected (if user is disabled, login is forbidden, else it succeeds).
Upon reviewing Keycloak source, it seems as if session id is sent in the confirmation mail and if session already exists in KC, it is automatically reused and user proceeds as if logged in. If session doesn't exist, "email confirmed" page is shown and user is not logged in (as expected).
To confirm my theory of KC not checking user status (enabled/disabled) in the middle of an existing session, I've disabled a user that's currently been active in the application. User was not logged out or anything of the like.
My conclusion is that when user complets the registration, session exists and that session is then automatically "hijacked" upon clicking on the confirmation link. Nowhere in the middle of that, does KC check if user is actually enabled or not. Same as if you disable user while he/she is logged in and is browsing the protected application.
Does anyone have any workaround of the issue? My next step is somehow to programatically invalidate session at the end of the registration, so user won't have any when clicking on the confirmation mail. I am not sure how to track this bug on KC jira either, since they don't seem to have any public bug tracker. Regardless, this is not the point of this question - my question is if anyone else already had this problem and if yes, how was it solved?
I have solved a similar issue writing a custom Required Action. The required action is triggered after email validation, so you can check if user is enabled or not (Secret question required action example).
In my case if user validation is not ok, I redirect to error page:
Response challenge =
context.form().setError(MessagesIDs.NOT_VALIDATED_ID).createErrorPage(Status.UNAUTHORIZED);
context.challenge(challenge);
return;

Keycloak Implement Reset password flow same as forgot password flow

I am facing an issue with Keycloak:
When user clicks on Forget password button, he is asked to enter basic details. Once details are entered, the user receives a mail with link to change his password. User Changes his password, and is redirected to Login page of the application.
Users account gets locked. Admin uses application to unlock the account. User gets email, clicks on link, and generates new password. User now sees a message : Your account is successfully updated.
What I want to do is that the second flow should work in same way as the first one. i.e when user has given new password, he'd be redirected to login page.
Can someone guide me about how to proceed with this?
Difference I've noticed in two flows is the URL that I receive in both of them is different.
First flow, I get this in mail: http://[keycloak-host]/auth/realms/[realm]/login-actions/reset-credentials?code=[code]
Second flow, I get this URL: http://[keycloak-host]/auth/realms/[realm]/login-actions/execute-actions?key=[key]

Handling users that exist, but try to login through Facebook OAuth / etc

I've got a decent set of existing users on my website who login via their emailaddress as their username.
I'm setting up Facebook OAuth mechanism to allow new users to sign up more conveniently, but I'm not sure how to handle the scenario when a user who already has an email address registered with our system and now tries to login via Facebook.
Should I consider him the same user?
Should I treat him like a new user?
The situation is more complicated by the fact that I dont validate their email addresses (when they login directly into my system), so i cant assume they are the same user.
How do others resolve this conflict, or do other folks simply treat this user connecting via FB as a new entity?
On your login screen, users can have a choice: you may put
new user: signup using facebook
since this is a totally new user account, then you just need to do your facebook connect + request for email permission, etc.
existing user: login by email
Once they do this, let them login using the old-fashioned way. Then once signed in, prompt them to connect this email address to their facebook account. So the flow is login via email then optional facebook connect.
To do this, I assume you've added a field on your database table for user_accounts, that is facebook_user_id or fb_id or user_id, etc. Then on facebook connect, get the logged-in-email, UPDATE table SET fb_id = xxx WHERE email = xx
I've pondered the same issue. I think we'll go with the verified email (Facebook Connect) getting attached to and logged into the existing account with the same email.
Before we connect and log them in we'll explain that the account exist and ask for their password (they signed up using email and password, so they should know it) to ensure it's the right person.
If you support multiple external authentications (Google OAuth, Facebook etc) then you may not have a password, and in that case it gets slightly trickier.
If you do log them in to the existing account without asking for a password, make sure you clear existing sessions to avoid 'anticipation attacks', where an attacker anticipates that the target signs up, creates an account and keep the session after they've signed up and attached to the attackers existing account.