How to configure "accept Terms and Conditions" on Keycloak registration page - keycloak

I use Keycloak 1.7.0-Final. The user must agree with Term and Conditions at registration.
I enabled "Terms and Conditions" in Authentication > Required actions, But nothing is shown on the registration page.
Also, I cannot find where to configure specific Terms and Condition files for each language.
Could you help?
Thank you.

By default existing users cannot have this page. You need to configure "Terms and Conditions" as "Default Action", then this will be applied by default for all new users.
For existing users, you need to put it manually unser "Users" > "Required actions".
Dont forget to customize the terms page under //themes/base/login/terms.ftl

You will see terms and conditions once the user has filled in the registration form and submits registration. You will have to override the terms.ftl (build your own theme) page if you want it customized and add your own messages locale - see Keycloak Docs - Themes ...

Enable terms and conditions
Regularly you must enable "Terms and Conditions" in Authentication > Required Actions as Enabled and Default Action. By default, this will show a dedicated page after the registration form page, using the template terms.ftl.
Using a checkbox for accepting terms and conditions in the registration page
For this purpose you must specify terms and conditions as Enabled, but not a Default Action. Otherwise you will see the dedicated page using terms.ftl. The problem here is that Keycloak has not a way to enable a checkbox to accept the terms and conditions in the registration page.
Nonetheless, doing a little of reverse engineering I found that when you accept the conditions the user will have an attribute called terms_and_conditions:
In order to reproduce this, you just need to create a custom attribute, named terms_and_conditions, with a numeric value, that seems to be the current time (Date.now()). Being that said, you need an HTML like:
<form>
<!-- other inputs -->
<div>
<input
type="checkbox"
id="terms"
name="user.attributes.terms_and_conditions"
value="<generated value, e.g. 1668029792010>" />
<label for="terms">I accept the terms and conditions</label>
</div>
<div>
<button type="submit">Create user</button>
</div>
</form>
This approach should also be valid if you create that user using the API.
i18n
If your are using a checkbox in the registration page, you can use the standard internationalisation strategy: using the messages properties files. It would probably have a link that reference the content of the "terms and conditions" in the current language. To get the lang code to construct the URL use ${locale.currentLanguageTag}.
Show a page for each language
On the other hand, if you want to use the typical Keycloak strategy using terms.ftl, then you must use the same layout as always and the text will change using the internationalisation.
But if the content of the terms and conditions is very long, then it should be better to create pages for each language, e.g. terms-en.ftl, terms-fr.ftl, etc. These ftl files will only contain the content in the corresponding language and they will be loaded using a code like:
<#include "terms-fr.ftl" />
e.g.
<#if (locale.currentLanguageTag!"en") == "en">
<#include "terms-en.ftl" />
<#else>
<#include "terms-es.ftl" />
</#if>
I hope this helps

You can use Keycloakify to create a theme.
Here is the section related to customizing Terms and conditions.

Related

Preventing user from modifying their name in Keycloak

In Keycloak, by default, users are able to change their first and last name in the account manager page. However, is it possible to disable this behavior?
Removing both fields in the theme results in those values not being sent and the form failing, and a hand-crafted POST request would defeat this method anyway.
I came across a similar problem and after reading this SO post, came to know that although you can disable/hide fields in ftl, you cannot disable form validation
For e.g I hid firstname field , but still cannot submit. Same was the result with disable as well:
I am not aware about disabling a particular field in some other way. However there is a workaround in which you can disable the entire account modification flow (Password can still be changed by Forgot Password option).
Bu default, account modification is enabled, but you can disable it for a particular realm by going to Realms -> Clients -> Account.
The result of this will be, the account page will be inaccessible:
You can remove the client role 'manage_account' for client 'account'.
In Keycloak, by default, users are able to change their first and last
name in the account manager page. Is it possible to disable this
behavior?
That can be done out-of-the-box (since Keycloak 14) by using the user profile functionality. First, the preview feature declarative-user-profile has to be enabled. For that start the server with:
--features=declarative-user-profile.
for the Quarkus version, or with
-Dkeycloak.profile.feature.declarative_user_profile=enabled
for the Wildfly version.
Bear in mind that:
Declarative User Profile is Technology Preview and is not fully
supported.
After starting the server with the aforementioned option, go to the Keycloak Admin Console and:
Go to the according Realm;
Go to the tab General;
Set User Profile enabled to ON
A new tab named User Profile (top right) will show up; click on it, and a set of configurable attributes will be shown.
Click on firstName, and then go to Permissions
In that section the permissions can be changed, accordingly. For example, if one sets Can user edit? to OFF, then when the user tries to change the firstName field in the account UI, that UI throws the following warning message:
The field First name is read only.
The same configuration can also be applied to the lastName attribute.
For the new Keycloak UI the workflow is exactly the same as the one I have just described. More information about the feature can be found in the official keycloak documentation (link)
You can use readonly property to disable email you can just change the following line:
<input type="text" class="form-control" id="email" name="email" readonly autofocus value="${(account.email!'')}"/>

Better Honeypot Implementation (Form Anti-Spam)

How do we get rid of these spambots on our site?
Every site falls victim to spambots at some point. How you handle it can effect your customers, and most solutions can discourage some people from filling out your forms.
That's where the honeypot technique comes in. It allows you to ignore spambots without forcing your users to fill out a captcha or jump through other hoops to fill out your form.
This post is purely to help others implement a honeypot trap on their website forms.
Update:
Since implementing the below honeypot on all of my client's websites, we have successfully blocked 99.5% (thousands of submissions) of all our spam. That is without using the techniques mentioned in the "advanced" section, which will be implemented soon.
Concept
By adding a invisible field to your forms that only spambots can see, you can trick them into revealing that they are spambots and not actual end-users.
HTML
<input type="checkbox" name="contact_me_by_fax_only" value="1" style="display:none !important" tabindex="-1" autocomplete="off">
Here we have a simple checkbox that:
Is hidden with CSS.
Has an obscure but obviously fake name.
Has a default value equivalent 0.
Can't be filled by auto-complete
Can't be navigated to via the Tab key. (See tabindex)
Server-Side
On the server side we want to check to see if the value exists and has a value other than 0, and if so handle it appropriately. This includes logging the attempt and all the submitted fields.
In PHP it might look something like this:
$honeypot = FALSE;
if (!empty($_REQUEST['contact_me_by_fax_only']) && (bool) $_REQUEST['contact_me_by_fax_only'] == TRUE) {
$honeypot = TRUE;
log_spambot($_REQUEST);
# treat as spambot
} else {
# process as normal
}
Fallback
This is where the log comes in. In the event that somehow one of your users ends up being marked as spam, your log will help you recover any lost information. It will also allow you to study any bots running on you site, should they be modified in the future to circumvent your honeypot.
Reporting
Many services allow you to report known spambot IPs via an API or by uploading a list. (Such as CloudFlare) Please help make the internet a safer place by reporting all the spambots and spam IPs you find.
Advanced
If you really need to crack down on a more advanced spambot, there are some additional things you can do:
Hide honeypot field purely with JS instead of plain CSS
Use realistic form input names that you don't actually use. (such as "phone" or "website")
Include form validation in honeypot algorithm. (most end-user will only get 1 or 2 fields wrong; spambots will typically get most of the fields wrong)
Use a service like CloudFlare that automatically blocks known spam IPs
Have form timeouts, and prevent instant posting. (forms submitted in under 3 seconds of the page loading are typically spam)
Prevent any IP from posting more than once a second.
For more ideas look here: How to create a "Nuclear" honeypot to catch form spammers
We found that a slight (though simple) variation on the suggestions here made a huge difference in the effectiveness of our contact form honeypot. In short, change the hidden field to a text input, and make the bot think it's a password. Something like this:
<input type="text" name="a_password" style="display:none !important" tabindex="-1" autocomplete="off">
You'll note that this mock-password input keeps to the same basic guidelines as the checkbox example. And yes, a text input (as opposed to an actual password input) seems to work just fine.
This apparently minor change resulted in a drastic drop in spam for us.
One suggestion to really force the no-autocompletion :
change autocomplete="off" by autocomplete="nope" OR autocomplete="false"
Since the given value is not a valid one (values for autocomplete are only on or off), the browser will stop trying to fill the field.
For more details, How to Turn Off Form Autocompletion.
Hope this helps.
SYA :)
If you are using Ruby on Rails, you can try invisible_captcha gem. A solution based on this honeypot technique.
It works pretty well! At least for small/medium sites... I'm using it in production, for years, in several Rails apps with very good results (we hardly receive spam since its implementation in "contact" forms, sign-up, etc).
It also provides some extras (already listed in https://stackoverflow.com/a/36227377/3033649):
time-sensitive submissions
IP based spinner validation
Basic usage
In your form:
<%= form_for(#user) %>
<%= invisible_captcha %>
...
<% end %>
In your controller:
class UsersController < ApplicationController
invisible_captcha only: [:create]
...
end
And you're done! Hope it helps!

PHP form handler-using "required" instead "isset" when not filled

Is it good to use "required" in input like this:
Name:<input type="text" name="name" required>
Or should I remove it and use "isset" in PHP? If I understand properly, both show you error, when you want to proceed next without filling input's, but required just awares you, while isset throw's you mostly to new page and reset the form(not good if you only forgot to fill one input).
Or should I remove it and use "isset" in PHP?
Why do you feel the two are mutually exclusive? Use both.
The required HTML attribute provides a smoother client-side user experience. It allows some basic validation without having to re-engage the server. It does not, however, do anything to validate incoming requests in server-side code. isset (among lots of other potential logic) can and should be used server-side to do just that.
Use client-side validation logic to present users with a better user experience. Use server-side validation logic to actually validate the user input before conducting business logic. Validation can live in lots of places for lots of reasons.

How does Chrome detect Credit Card fields?

In some forms, Chrome autofill prompts with Credit card autofill.
EDIT:Adding screenshot. This is not the same as browser autocomplete. You need not have entered the value in the same form before.
How should I write my HTML form so the browser detects these as Credit card fields and triggers this behavior?
An example of it working with a Stripe form would be ideal.
This question is pretty old but I have an updated answer for 2019!
You can now tell your browser which fields are for credit card info just by naming the <input> correctly.
The following answer is from my original answer from here: https://stackoverflow.com/a/41965106/1696153
Here's a link to the official current WHATWG HTML Standard for enabling autocomplete.
Google wrote a pretty nice guide for developing web applications that are friendly for mobile devices. They have a section on how to name the inputs on forms to easily use auto-fill. Eventhough it's written for mobile, this applies for both desktop and mobile!
How to Enable AutoComplete on your HTML forms
Here are some key points on how to enable autocomplete:
Use a <label> for all your <input> fields
Add a autocomplete attribute to your <input> tags and fill it in using this guide.
Name your name and autocomplete attributes correctly for all <input> tags
Example:
<label for="frmNameA">Name</label>
<input type="text" name="name" id="frmNameA"
placeholder="Full name" required autocomplete="name">
<label for="frmEmailA">Email</label>
<input type="email" name="email" id="frmEmailA"
placeholder="name#example.com" required autocomplete="email">
<!-- note that "emailC" will not be autocompleted -->
<label for="frmEmailC">Confirm Email</label>
<input type="email" name="emailC" id="frmEmailC"
placeholder="name#example.com" required autocomplete="email">
<label for="frmPhoneNumA">Phone</label>
<input type="tel" name="phone" id="frmPhoneNumA"
placeholder="+1-555-555-1212" required autocomplete="tel">
How to name your <input> tags
In order to trigger autocomplete, make sure you correctly name the name and autocomplete attributes in your <input> tags. This will automatically allow for autocomplete on forms. Make sure also to have a <label>! This information can also be found here.
Here's how to name your inputs:
Name
Use any of these for name: name fname mname lname
Use any of these for autocomplete:
name (for full name)
given-name (for first name)
additional-name (for middle name)
family-name (for last name)
Example: <input type="text" name="fname" autocomplete="given-name">
Email
Use any of these for name: email
Use any of these for autocomplete: email
Example: <input type="text" name="email" autocomplete="email">
Address
Use any of these for name: address city region province state zip zip2 postal country
Use any of these for autocomplete:
For one address input:
street-address
For two address inputs:
address-line1
address-line2
address-level1 (state or province)
address-level2 (city)
postal-code (zip code)
country
Phone
Use any of these for name: phone mobile country-code area-code exchange suffix ext
Use any of these for autocomplete: tel
Credit Card
Use any of these for name: ccname cardnumber cvc ccmonth ccyear exp-date card-type
Use any of these for autocomplete:
cc-name
cc-number
cc-csc
cc-exp-month
cc-exp-year
cc-exp
cc-type
Usernames
Use any of these for name: username
Use any of these for autocomplete: username
Passwords
Use any of these for name: password
Use any of these for autocomplete:
current-password (for sign-in forms)
new-password (for sign-up and password-change forms)
Resources
Current WHATWG HTML Standard for autocomplete.
"Create Amazing Forms" from Google. Seems to be updated almost daily. Excellent read.
"Help Users Checkout Faster with Autofill" from Google in 2015.
From this answer https://stackoverflow.com/a/9795126/292060, it looks like Chrome is either matching a regex pattern on the field name, or the form is explicitly using the x-autocompletetype attribute, like this (This example uses "somename" to avoid mixing issues matching on the name):
<input type="text" name="somename" x-autocompletetype="cc-number" />
Practically, you could do both, picking a name that matches, and the x-autocompletetype:
<input type="text" name="ccnum" x-autocompletetype="cc-number" />
Do you have a view-source of the input box in your screenshot? That would show if it's matching on the name or on the x-autocompletetype attribute.
The answer I linked to has several links for more information; I didn't repeat them here.
Some other comments:
I know Chrome pops a question whether to save the credit card information (I don't), but I don't know if it is popping that question regardless of how it detected it. That is, I'm not sure if Chrome will autocomplete separate fields of credit cards along with other fields, or if it needs to save the whole thing as a credit card.
Your question was how to do it, not whether to. But from the comment in your question, I agree that you might not want to autocomplete the credit card fields. Personally I find it disconcerting when it happens, even knowing it's local in my browser (I especially feel this way about the CVV, and get a surprising amount of resistance when I report it). However, there are posts that find it frustrating when a customer wants to use it, has Chrome set up with credit cards, and a website blocks it.
Thanks #goodeye for directing me to the correct answer.
To trigger the Credit Card autofill,
SSL must be enabled on your form
Most variants of standard credit card field names should work if SSL is enabled.
Here is a link to the regexes Chrome uses to trigger detection
As of 04-12-2022 (from the link above)
/////////////////////////////////////////////////////////////////////////////
// credit_card_field.cc
/////////////////////////////////////////////////////////////////////////////
// ... snipped ...
const char kCardNumberRe[] =
"card.?number|card.?#|card.?no|cc.?num|acct.?num"
"|nummer" // de-DE
"|credito|numero|número" // es
"|numéro" // fr-FR
"|カード番号" // ja-JP
"|Номер.*карты" // ru
"|信用卡号|信用卡号码" // zh-CN
"|信用卡卡號" // zh-TW
"|카드"; // ko-KR
Chrome is using autocomplete attribute in inputs for autofill. This will probably be used by other browsers in future if not yet.
autocomplete's actual use is to say whether autocomplete is enabled or not by specifying autocomplete="off". But chrome uses the same for autofill.
Autofill and autocomplete are different, so don't get confused.
Autofill is what chrome uses to fill up forms from what is stored in your autofill settings in your chrome browser.
Autocomplete is what all browsers use to remember what you may have entered previously in the same form by suggesting values as you type. So when you use autocomplete="off" on an input, browser stops suggesting these values.
Coming back to the solution, for autofill to work use cc-number for card number, cc-name for card holder name, cc-csc for cvc and cc-exp for card expiry date in your autocomplete attribute.
Here is a sample that will be compatible with chrome autofill:
<div>
<label for="frmNameCC">Name on card</label>
<input name="ccname" id="frmNameCC" required placeholder="Full Name" autocomplete="cc-name">
</div>
<div>
<label for="frmCCNum">Card Number</label>
<input name="cardnumber" id="frmCCNum" required autocomplete="cc-number">
</div>
<div>
<label for="frmCCCVC">CVC</label>
<input name="cvc" id="frmCCCVC" required autocomplete="cc-csc">
</div>
<div>
<label for="frmCCExp">Expiry</label>
<input name="cc-exp" id="frmCCExp" required placeholder="MM-YYYY" autocomplete="cc-exp">
</div>
If you have credit cards saved in your chrome browser right now, try clicking Run code snippet button above and you can see chrome autofill in action.
Source: https://developers.google.com/web/updates/2015/06/checkout-faster-with-autofill
Chrome also scans thru placeholders.
Example: <input placeholder='dd-mm-yyyy'/> will trigger it to become a credit card field.

Does Alfresco Share provide any mecanism for Inter Dashlet Communication?

I am trying to figure out how to perform some inter dashlet communication with Alfresco Share.
Here a simple use case:
We do have 2 dashlets, let's call them A and B. I want to be able to fill in a field "name" (let's say with value "Toto") in A and click on submit button. After clicking on submit button in A. B should be updated with greeting like " Good Morning Toto".
Thank you for you answers.
Thanks for your answer. Can you elaborate a bit regarding "let dashlet_b.get.html.ftl post something to dashlet_a.post.html.ftl" ?
In dashlet_b.get.html.ftl you have something like that I guess :
<form id="..." action="" method="POST">
<input id="name" type="text" name="name" value=""/>
<input type="submit" id="send" value="Send" /></form>
When you submit the form it's gonna look for dashlet_b.post.js right ? How do you actually tell to send the form to dashlet_a.post.js ?
To create these dynamic dashlets it is not enough to use the server side dashlet webscript. You need javascript logic in the browser to notify the other dashlet of changes. This is how Alfresco usually does that:
Browser Javascript Dashlet A:
YAHOO.Bubbling.fire("interDashletMessage",
{
message: "Hello World."
});
Browser Javascript Dashlet B:
YAHOO.Bubbling.on("interDashletMessage", function(layer, args) {
var message = args[1].message;
alert(message); // or write it to the dashlets HTML content
});
This will send the message from dashlet A to dashlet B using a custom event called "interDashletMessage".
If your dashlet B only displays a few messages it could be enough to send the data over using the events. If it is more complex your dashlet A needs to post it's data to the repository first, then trigger the "refresh" event and have dashlet B refresh it's content from the repository. This will involve multiple webscripts you may need to write.
That's quite simple I guess.
Each Dashlet is in fact a webscript. So you can have multiple webscript for different usage. Like I've got dashlet_a.get.html.ftl and dashlet_a.post.html.ftl.
In fact these two are the same webscript, one just acts on a post and the other on get.
So what you could do, is let dashlet_b.get.html.ftl post something to dashlet_a.post.html.ftl. Hence you are submitting value(s) from b to a.
The next step is to refresh dashlet_a, one way is to do a full page refresh, but that's not nice.
Whats better is the following:
In dashlet_a.post.html.ftl you just set through YUI/JQuery the value of the field which is defined in dashlet_a.get.html.ftl.
Take a look how the default configurable dashlet do it, like the webview. If you put something in the config, the value directly is shown.