Setting tenant from login page - identityserver3

In our login process with identity server we need additional input on the login page itself that will influence the tenant where user is authenticated. So we can't send this information in the acr_values that is stored in the SignInMessage cookie, but we need to somehow modify the tenant based on the user input on the login page. However, when IUserService.AuthenticateLocalAsync is called, the SignInMessage is created based on the initial values sent to /authorize endpoint.
Any tips on how to achieve this?

You can control the <form> in the login page, then in your user service you can access the form post body (by injecting the OwinEnvironmentService).

Related

Is there a possibility to automatically login by clicking on verify email link triggered by /send-verify-email

If Keycloak's self-registration form is used, once submitted, it will send an email verification link to that newly registered user.
Once the user clicks the link, his email will be verified, and it will redirect him to the redirectUri from his client and provide the authorization code, which is perfect.
The problem arises when I don't want to use Keycloak's registration form, instead I have a custom registration mobile form, which sends the user data. Those data is then sent to the Keycloak by Admin REST create user API.
Once the user is created, by triggering /send-verify-email or /execute-actions-email APIs none of them are returning authorization code in the end. Yes, they do redirect to the redirectUri which you specified, but I need authorization code as well, in order to be logged in automatically upon clicking on the link.

Keycloak: Disable username/password login for external IDP

How to disable username/password login for external IDP ?
I know that I can use custom theme to hide http form, but I want to do it properly.
As far as I know I have to create at least custom First Broker Login and Browser authentication flow, right?
After first login from IDP I have to create user in Keycloak, but do not leverage password option.
Also Browser flow must be updated to not show username/password form, right?
Can anyone provide proper example ?
Thanks
You can use a custom authentication provider to achieve your goal.
Instruct Keycloak to assign a specific user attribute to all users arriving from the IDP.
Build an authentication provider which checks for that user attribute and denies access.
Add the authentication provider to the Browser login flow.
Optionally adjust templates files to hide login fields and show a user-friendly error if the user fails step 2.
Further details here: https://groups.google.com/g/keycloak-user/c/N9cuqXIBrSA/m/sycLxTZbCAAJ
May not be 100% suitable to this case, but found next one working fine for our case without need to compile and deploy "custom authentication provider". In our app we suppress keycloak login form and offer own custom user / password form, and for IdP integration we are using kc_hint to redirect directly to IdP login page. Once user login via IdP we want to disable user name / password login using password grant. There is a trick allows to achieve this in keycloak v15. You can assign "Update User Locale" to "Required User Actions" of the user, from that moments, direct password grant wont let user to login returning "requires action" validation error, which is not supported in our UI, while IdP login still works and skip this "required action" nor reset it after login. Of course you may need some scheduled curl script allows to set this for users automatically via users REST API : read users attributes or IdP link integration, if found specific Idp related user attribute or IdP integration link, and "requires action" array is empty, set it to "Update Locale".
Of course this all works as long as you hide keycloak login form and use your own. for all using keycloak login form, login using name / password will work and can bypass "Update locale" requirement (not sure why, perhaps because realm does not have locales configured)
Try this costum Authentication flow
By Automatically linking brokered account, the user won't have to set a password. as for the username it will be automatically imported from the identity provider.

Keycloak secure user registration

I want to secure my user registration page with keycloak but couldn't think of any approaches while reading the docs.
Use case:
The registration page for new users shouldn't be public. New user get an invitation email from the admin. The email contains a link to the registration page.
I thought about using an initial access token (like for client registration) and add it to the link to the registration page. Afaik there is nothing like that for user registration?
Are there any other ways to do it?
I think you've got two options to implement it:
First
You know the e-mail of the destination user before sending the invitation, so you would let the admin create a user in keycloak with the e-mail itself as the username. Then the admin should check 'Verify e-mail', 'Update profile' and 'Update password' as required actions, so keycloak will send an activation mail (you can customize the e-mail template) and user will be required to fill his data and set a password.
If you don't want the admin to access keycloak directly, you could do it via the user management API.
Second
Implement this logic in your application. Write a user data form which is publicly accessible using a code (it might be some UUID). When admin sending the invitation mail, link a random code to the address, so when user enters the page, you can verify it. Then you'll need to save the data in keycloak as a new user, using the user management API.

IdentityServer4 - redirect after registration

I have a simple setup with IdentityServer4 (custom user store) and Mvc client app. Some pages in the client app are protected. So for example when a user hits /pageX he gets redirected to IdentityServer for authentication. This works fine when the user exists, he just logs in and gets redirected.
If he is not registered, he is asked to register and he gets an activation code via email.
Then he goes to inbox, clicks activation link and is invited to login again.
Now, after activation and login, I would like to redirect him to the /pageX he originally asked.
My problem is - at this point I no longer have a valid returnUrl which contains /pageX encoded somehow. I tried using the returnUrl which works in simple login flow:
returnUrl=%2Fconnect%2Fauthorize%2Fcallback%3Fclient_id%3DmyClientIdt%26redirect_uri%3Dhttp%253A%252F%252Flocalhost%253A5501%252Fsignin-oidc%26response_type%3Did_token%26scope%3Dopenid%2520profile%26response_mode%3Dform_post%26nonce%3D636469643044666440.MmZlNzFlMWYtZThhMS00ZjFlLTgyYjYtMDU5NjRmODBhZmNkMzk1MzJiZWItODY2Yy00NzYwLWE4YjQtOGU5YWU5Y2IxMDJk%26state%3DCfDJ8IK-YquShZdNsC5l0tQGkLIvU-_O1FbdO5RV9KrOZ9hCTixBZc-YeVLkKB2mvHkV9U42U83N7RfFCHywKjdbGRGnpfqwgG08_ip1Pt2sAqfa_sPlwYOO7fSiKUbnk2IpA1BMWvfeXNwIeFB7AMv0q0Y2z7vjCTNWawwNS6m5EM3h9V0uCpHE-1H19VPhE0OQcXmmcaNViWbdmWE14VNTH8MYQaPfE90smHtRwYtbYaYhfj-g4ziXbhN6m_R6PYni1ApazIDUBOowEq6yV9ynF91SM82gohud4Ek3juozL-A4W_dTIBZnj1C5PMmUISWl9yw_UPOvTwsCskVH2OmavgI%26x-client-SKU%3DID_NET%26x-client-ver%3D2.1.4.0)
But if I use this return url after registration, I get a correlation error message.
Any idea how can I return the user back to his original requested /pageX?
The returnUrl (as sampled in the question) is a result of redirection from Authorize Endpoint to Login/Register Page. You need to use IdentityServer Interaction Service to retrieve the actual returnUrl.
var context = await _interaction.GetAuthorizationContextAsync(returnUrl);
context.RedirectUri will hold the actual url (/PageX), where user needs to be redirected after activation.
You can pass context.RedirectUri as a query parameter to the activation link and retrieve it on the activation page. When activation is complete you can redirect the user to the returnUrl.
string activationLink = "<your activation url>?return=" + returnUrl;
Check this docs
Basically this situation can be avoided by not providing a link to click in the confirmation email which will land the user in a different browser tab.
Instead of a link provide an n-digit code in the email and let the user enter the code in the already open browser tab where you still have access to the returnUrl

how to implement passwordless authentication in identityserver3

I'm looking for the correct way to customize or extend identityserver3 to implement passwordless authentication.
the user scenario is
user uses browser to go to website
website detects non-authenticated
user and redirects to idsrv3 instance
idsrv3 asks for email address (or uses a cookie stored one) and if email address matches a known user, sends an email with a link (e.g. like the registration or password reset link)
user clicks on link
idsrv3 instance checks if token in link matches a known user and is not expired
idsrv3 issues token
idsrv3 redirects to original url
after some reading, I think the correct way to customize idsrv3 would be to
create a custom viewservice
checks the emailaddress
generates and stores a token in the user account record
sends an email with a link consisting of a custom grant, the token and a returnurl
create a custom grant and corresponding validator
checks the incoming token and if valid returns a positive validation result linked to a user account
the normal idsrv3 token issuing flow takes over to issue a token and redirect to the returnurl
In my experience, idsrv3 is great, but it can be time-consuming to get things right when customizing and I would like to be sure that I don't hit a brick wall somewhere near the end of the solution.