Email validation using regular expression in JSF 2 / PrimeFaces - regex

I have an input field taking an email address:
<h:inputText value="#{register.user.email}" required="true" />
How can I validate the entered value as a valid email address using regex in JSF 2 / PrimeFaces?

All regular expression attempts to validate the email format based on Latin characters are broken. They do not support internationalized domain names which were available since May 2010. Yes, you read it right, non-Latin characters are since then allowed in domain names and thus also email addresses.
That are thus extremely a lot of possible characters to validate. Best is to just keep it simple. The following regex just validates the email format based on the occurrence of the # and . characters.
<f:validateRegex pattern="([^.#]+)(\.[^.#]+)*#([^.#]+\.)+([^.#]+)" />
Again, this just validates the general email format, not whether the email itself is legit. One can still enter aa#bb.cc as address and pass the validation. No one regex can cover that. If the validity of the email address is that important, combine it with an authentication system. Just send some kind of an activation email with a callback link to the email address in question and let the user login by email address.

Here is how:
Using it myself...
<h:inputText id="email" value="#{settingsBean.aFriendEmail}" required="true" label="Email" validatorMessage="#{settingsBean.aFriendEmail} is not valid">
<f:validateRegex pattern="[\w\.-]*[a-zA-Z0-9_]#[\w\.-]*[a-zA-Z0-9]\.[a-zA-Z][a-zA-Z\.]*[a-zA-Z]" />
</h:inputText>
<p:message for="email" />
Daniel.

Here's my version and it works well :
<f:validateRegex pattern="^[_A-Za-z0-9-\+]+(\.[_A-Za-z0-9-]+)*#[A-Za-z0-9-]+(\.[A-Za-z0-9]+)*(\.[A-Za-z]{2,})$" />
And i made a demo here

This one supports unicode domain names in email:
<f:validateRegex pattern="^[_A-Za-z0-9-\+]+(\.[_A-Za-z0-9-]+)*#[\p{L}\p{M}\p{N}.-]*(\.[\p{L}\p{M}]{2,})$" />
... and this one validates email only when email is entered (email is not required field in form):
<f:validateRegex pattern="(^[_A-Za-z0-9-\+]+(\.[_A-Za-z0-9-]+)*#[\p{L}\p{M}\p{N}.-]*(\.[\p{L}\p{M}]{2,})$)?" />

<p:inputText id="email" required="true" label="email" size="40"
requiredMessage="Please enter your email address."
validatorMessage="Invalid email format"
value="#{userBean.email}">
<f:validateRegex
pattern="^[_A-Za-z0-9-\+]+(\.[_A-Za-z0-9-]+)*#[A-Za-z0-9-]+(\.[A-Za-z0-9]+)*(\.[A-Za-z]{2,})$" />
</p:inputText>
<p:watermark for="email" value="Email Address *" />
<p:message for="email" />
<p:commandButton value="test" style="margin:20px"
action="#{userBean.register}" ajax="false" />

Related

ColdFusion CSRF XSS attack prevention

I have implemented the csrfGenerateToken and csrfVerifyToken functions in trying the prevent a CSRF attack.
I have set up the webpage header with these:
set X-XSS-Protection "1; mode=block"
always set X-Frame-Options SAMEORIGIN
X-Content-Type-Options nosniff
Strict-Transport-Security "max-age=63072000" env=HTTPS
I have done some research and proceed as recommended by Adobe doing something like this:
<cfset tokenVar = 't' & lCase( hash( createUUID() & randRange( 1000, 100000 ), 'MD5', 'UTF-8', 250 ) )>
<form action="updateprofile.cfm" method="post">
<input type="hidden" name="f#hash( 'tokenVar', 'SHA-256', 'UTF-8')#" value="#tokenVar#">
<input type="hidden" name="f#hash( 'formToken', 'SHA-256', 'UTF-8')#" value="#csrfGenerateToken( tokenVar, true )#">
<input type="text" name="emailAddress" value="#EmailAddress#">
<input type="text" name="phoneNumber" value="#PhoneNumber#">
<input type="submit" name="btnSubmit" value="Change Profile Info">
</form>
Updateprofile.cfm would have:
<cfparam name="FORM[ 'f' & hash( 'tokenVar', 'SHA-256', 'UTF-8')]" default="0">
<cfparam name="FORM[ 'f' & hash( 'formToken', 'SHA-256', 'UTF-8')]" default="0">
<cfif not csrfVerifyToken( FORM[ 'f' & hash( 'formToken', 'SHA-256', 'UTF-8')], FORM[ 'f' & hash( 'tokenVar', 'SHA-256', 'UTF-8')] )>
<!--- CSRF attack. Clear cookies and kick user out --->
<cfinclude template="clearcookies.cfm">
<cflocation url="signin.htm" addToken = "no">
</cfif>
This will work if 2 accounts are signed in on the same browsers and if one tries to update the other. However, when I simply saved a copy of the resulting html from one of them and save it as csrf-attack.htm locally:
<html><body>
<script>history.pushState('', '', '/')</script>
<form action="http://www.exsample.com/updateprofile.cfm" method="post">
<input type="hidden" name="f41BE6B4E09CBA69BDB76DBB69B493E8D49F5DD9ED230085913397B4C751D4E60" value="t93315a7c3ecb43d4d1b9422da97ffb09">
<input type="hidden" name="f08DFC2607D4119D7B16B4C01DC5C00F54B044DC937257ABC411F9A7E55BB4191" value="A0EED67C55F5E17683E2E1B21FF3454FE690E0B1">
<input type="text" name="emailAddress" value="test#test.com">
<input type="text" name="phoneNumber" value="1-222-3333">
<input type="submit" name="btnSubmit" value="Change Profile Info">
</form>
</body><html>
I processed the original form to update the phone number to 1-333-4444. Then I came back to the form again. At this time a new CSRFToken should have been created because ForceNew was set to true.
Then I go to the static HTML page that I have saved, and simply changed the value of the email address to test2#test.com instead of test#test.com with the old token, then clicked the "Change Profile Info" button, I was able to update it to the site!!
Am I doing something wrong or is it how it works? It seems that the token is useless if I can simply copy the token values and manipulate the content, then post it. How can I mitigate issue like this on the receiving page?
Thanks in advance.
The csrfVerifyToken result will still pass until you generate another CSRF token with the same key, at that point it will get invalidated. So if you are making single use tokens then you need to invalidate the old token by calling csrfGenerateToken with the same tokenVar after you call csrfVerifyToken
I wrote up a blog entry with a code example to illustrate this: https://www.petefreitag.com/item/856.cfm
Jack, 2 points:
First, things will seem to "not protect anything" if your requests (including that html page) are made from the same browser, thus using the same session cookies for the site, thus using the same cf session.
The generated token is saved in the cf session for that user/browser (saved in a way not visible with a cfdump of the session). And the verify is then checking the passed-in token against that. But if you run the "other" code in another browser, it would NOT share the same session (unless you also copied in the user's cookies).
Second, even if you did duplicate the session cookies, the value in that csrf token field (simulating being grabbed by the bad guy who saw the form and "copied it off" to that other page) will be the value that was created when THEY did that...not the value that a real user would have in their session if they'd been to the page that did the csrfgeneratetoken. So the tokens won't match.
Make sense? It's easy to misconstrue what this is does and does not do, and just as easy to get tripped up setting up a demo prove if it "works", if you don't keep all this in mind.
And I may be lacking in my answer, so am open to comments and criticism.

Encoding E-Mail Addresses: EncodeForHTML or EncodeForURL

When a user registers on a site, should we use EncodeForHTML() or EncodeForURL() before storing the value in a DB?
The reason I ask this is that when I send an e-mail to someone that includes a URL that contains an email address as a URL variable, I have to use EncodeForURL(). But if this email address is already encoded using EncodeForHTML(), it will mean I have to Canonicalize() it before using EncodeForURL() on it again.
I would therefore think that EncodeForURL() is probably good, but is it 'safe' and 'correct' when storing the value in a database?
Update: Upon reading the docs it says that EncodeForURL is only for using a value in a URL. Thereofore it seems to make sense that I should store it as EncodedForHTML, but then Canonicalize and re-encode for URL when using it in a URL context. I don't know how much of a performance hit all this encoding is going to take on my server...??
Copying this from my company's internal documentation. Not sure if the images uploaded correctly since imagr is blocked # work. If so, I'll re-upload them later. I'll be publishing this and more related content to a Githib repo in the future.
You should store it as simple text, but make sure you scrub your data on the way in using an AntiSamy library. Once the data is safe, make sure to encode the data on the way out using the proper encoder. And FYI, there's a big difference between the output of encodeForHTML() and encodeForHTMLAttribute().
In the below examples, substitute the variables that define email addresses with data from the DB.
PROTIP: Don't use these encoders in CFFORM tags. Those tags take care of the encoding for you. CF 9 and below use HTMLEditFormat(), CF 10 and above most likely use encodeForHTMLAttribute().
Simple Implementation
A basic implementation is to include a single e-mail address in order to populate the "To" field of a new e-mail window.
CFML
<cfset email = "someone#example.com" />
E-mail
HTML Output
E-mail
CFML with Proper Encoding
<cfset email = "someone#example.com" />
E-mail
Encoded HTML Output
Notice that the "#" symbol is properly percent encoded as "%40".
E-mail
Results when clicked
And if you plan on showing the e-mail address on the page as part of the link:
<cfset email = "someone#example.com" />
#encodeForHTML(email)#
Attack Vector
An advanced implementation includes e-mail addresses for "To" & "CC". It can also pre-populate the body and subject of the new e-mail.
CFML without encoding
<cfset email = "someone#example.com" />
<cfset email_cc = "someone_else#example.com" />
<cfset subject = "This is the subject" />
<cfset body = "This is the body" />
E-mail
HTML Output
E-mail
Results when clicked
Notice that the subject and body parameters contain spaces. While this string will technically work, it is still prone to attack vectors.
Imagine the value of body is set by the result of a database query. This record has been "infected" by a malicious user and the default body message has an appended "BCC" address, so some evil user can get copies of e-mails sent via this link.
Infected Data
<cfset body = "This is the body&bcc=someone#evil.com" />
HTML Output
E-mail
Results when clicked
In order to stop this MAILTO link from being infected, this string needs to be properly encoded.
CFML with HTML Attribute Encoding
Since "href" is an attribute of the <a> tag, you might think to use the HTML Attribute encoder. This would be incorrect.
<cfset email = "someone#example.com" />
<cfset email_cc = "someone_else#example.com" />
<cfset subject = "This is the subject" />
<cfset body = "This is the body&bcc=someone#evil.com" />
E-mail
HTML Output
E-mail
Results when clicked
CFML with URL Encoding
The correct encoding of a MAILTO link is done with the URL encoder.
<cfset email = "someone#example.com" />
<cfset email_cc = "someone_else#example.com" />
<cfset subject = "This is the subject" />
<cfset body = "This is the body&bcc=someone#evil.com" />
E-mail
HTML Output with Correct Encoding
Notice these things about the URL encoder:
Each space (" ") is converted to a plus sign ("+") instead of its expected percent value ("%20").
Encoding is otherwise done using percent ("%") values.
Since the individual query paramters are encoded, the ampersands ("&") connecting each paramter were not encoded.
When the "body" paramter is encoded, it includes the "&body=" string that was maliciously injected. This entire string is now part of the message body, which prevents the unintended "bcc" of the e-mail.
E-mail
Results when clicked
What's with the plus signs? It is up to the individual mail client (e.g. Outlook, GMail, etc.) to correctly decode these URL encoded values.
Store the email addresses in plain text, then encode them when you use them, depending on the context. If it's going to be a part of URL, use EncodeForURL(). If it's going to be displayed in HTML as text, use EncodeForHtml().

Validate regex for PrimeFaces Password

I have password and repeat password fields,But I want to validate passwords depending on validate regex pattern along with matching both the password fields too.
<p:outputLabel for="Password" value="Password" />
<p:password id="Password" redisplay="true"
value="#{newUserBean.newUserDTO.password}" match="RepeatPassword"
label="Password" required="true"
requiredMessage="Password is required, cannot be empty"
validatorMessage="Password and Repeat Password fields must be same" feedback="true"
promptLabel="Password should contain atleast 8 characters ,1 number and 1 special character" >
</p:password>
<p:outputLabel for="RepeatPassword" value="Repeat Password" />
<p:password id="RepeatPassword" redisplay="true"
value="#{newUserBean.newUserDTO.password}" label="RepeatPassword"
required="true"
requiredMessage="Password is required, cannot be empty" feedback="true"
promptLabel="Repeat Password should match with Password">
</p:password>
Make changes as below
<p:outputLabel for="Password" value="Password" />
<p:password id="Password" redisplay="true"
value="#{newUserBean.newUserDTO.password}"validator="#{passwordValidator.validate}"
label="Password" required="true"
requiredMessage="Password is required, cannot be empty"
validatorMessage="Password and Repeat Password fields must be same" feedback="true"
promptLabel="Password should contain atleast 8 characters ,1 number and 1 special character" >
<p:ajax event="blur" update="msgfrpassword" />
</p:password>
<p:outputLabel for="RepeatPassword" value="Repeat Password" />
<p:password id="RepeatPassword" redisplay="true"
value="#{newUserBean.newUserDTO.password}" label="RepeatPassword" validator="#{confirmPasswordValidator.validate}"
required="true"
requiredMessage="Password is required, cannot be empty" feedback="true"
promptLabel="Repeat Password should match with Password">
<p:ajax event="blur" update="msgfrpassword" />
</p:password>
Override java validator to verify regex and compare repeat password and password
PasswordValidatorBean
#Override
public void validate(FacesContext context, UIComponent component,
Object value) throws ValidatorException {
matcher = pattern.matcher(value.toString());
if (!matcher.matches()) {
FacesMessage msg = new FacesMessage(
new MessageProvider()
.getValue("prometheus_passwordpromptlable"));
msg.setSeverity(FacesMessage.SEVERITY_ERROR);
throw new ValidatorException(msg);
}
}
If we assume you need a regex to be both suitable for running on server and client side, I can suggest this regex that
checks the password length - .{8,}
makes sure there is at least 1 digit - (?=.*[0-9].*$)
and 1 special character (please define what special character means for you, add or remove accordingly) - (?=.*[-+()[\]~!##$%^&*+}{":;'/?.><,\].*$)`
Regex:
^(?=.*[-+()[\]~!##$%^&*+}{":;'/?.><,`\\].*$)(?=.*[0-9].*$).{8,}$

How validate number fields with validateRegex in a JSF-Page?

In a managed bean I have a property of the type int.
#ManagedBean
#SessionScoped
public class Nacharbeit implements Serializable {
private int number;
In the JSF page I try to validate this property for 6 digits numeric input only
<h:inputText id="number"
label="Auftragsnummer"
value="#{myController.nacharbeit.number}"
required="true">
<f:validateRegex pattern="(^[1-9]{6}$)" />
</h:inputText>
On runtime I get an exception:
javax.servlet.ServletException: java.lang.Integer cannot be cast to java.lang.String
java.lang.ClassCastException: java.lang.Integer cannot be cast to java.lang.String
Is the regex wrong? Or are the ValidateRegex only for Strings?
The <f:validateRegex> is intented to be used on String properties only. But you've there an int property for which JSF would already convert the submitted String value to Integer before validation. This explains the exception you're seeing.
But as you're already using an int property, you would already get a conversion error when you enter non-digits. The conversion error message is by the way configureable by converterMessage attribute. So you don't need to use regex at all.
As to the concrete functional requirement, you seem to want to validate the min/max length. For that you should be using <f:validateLength> instead. Use this in combination with the maxlength attribute so that the enduser won't be able to enter more than 6 characters anyway.
<h:inputText value="#{bean.number}" maxlength="6">
<f:validateLength minimum="6" maximum="6" />
</h:inputText>
You can configure the validation error message by the validatorMessage by the way. So, all with all it could look like this:
<h:inputText value="#{bean.number}" maxlength="6"
converterMessage="Please enter digits only."
validatorMessage="Please enter 6 digits.">
<f:validateLength minimum="6" maximum="6" />
</h:inputText>
You can achieve this without regex also
To validate int values:
<h:form id="user-form">
<h:outputLabel for="name">Provide Amount to Withdraw </h:outputLabel><br/>
<h:inputText id="age" value="#{user.amount}" validatorMessage="You can Withdraw only between $100 and $5000">
<f:validateLongRange minimum="100" maximum="5000" />
</h:inputText><br/>
<h:commandButton value="OK" action="response.xhtml"></h:commandButton>
</h:form>
To validate float values:
<h:form id="user-form">
<h:outputLabel for="amount">Enter Amount </h:outputLabel>
<h:inputText id="name-id" value="#{user.amount}" validatorMessage="Please enter amount between 1000.50 and 5000.99">
<f:validateDoubleRange minimum="1000.50" maximum="5000.99"/>
</h:inputText><br/><br/>
<h:commandButton value="Submit" action="response.xhtml"></h:commandButton>
</h:form>

JSF 2.0 validateRegex with own validator message

i am having a code similar to this:
<h:inputText id="email" value="#{managePasswordBean.forgotPasswordEmail}"
validatorMessage="#{validate['constraints.email.notValidMessage']}"
requiredMessage="#{validate['constraints.email.emptyMessage']}"
validator="#{managePasswordBean.validateForgotPasswordEmail}"
required="true">
<f:validateRegex pattern="^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,6})$" />
</h:inputText>
The validator in the backing bean has its own validation message generated. but it is overwritten by the validatorMessage of the inputText tag.
My Question is: how can i define a custom validator message for the validateRegex tag? I don't want to remove the validatorMessage cause then JSF is displaying an own error message containing the regex pattern and so on -> which i dont find very pretty.
Thanks for the help :)
You can't define a separate validatorMessage for each individual validator. Best what you can do is to do the regex validation in your custom validator as well, so that you can remove the validatorMessage.
Update: since version 1.3, the <o:validator> component of the JSF utility library OmniFaces allows you to set the validator message on a per-validator basis. Your particular case can then be solved as follows:
<h:inputText id="email" value="#{managePasswordBean.forgotPasswordEmail}"
required="true" requiredMessage="#{validate['constraints.email.emptyMessage']}">
<o:validator binding="#{managePasswordBean.validateForgotPasswordEmail}" message="#{validate['constraints.email.notValidMessage']}" />
<o:validator validatorId="javax.faces.RegularExpression" pattern="^[_a-z0-9-]+(\.[_a-z0-9-]+)*#[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,6})$" message="Your new custom message here" />
</h:inputText>
Unrelated to the concrete problem: these days you would be not ready for world domination as long as you still validate email addresses based on Latin characters. See also Email validation using regular expression in JSF 2 / PrimeFaces.
This worked for me.
You can write your custom messages in "validatorMessage"
<h:form id="form">
<h:outputLabel for="name">Name :</h:outputLabel>
<h:inputText id="name" value="#{editStock.name}" required="true" requiredMessage="Name field must not be empty" validatorMessage="Your name can have only Alphabets">
<f:validateRegex pattern="^[a-zA-Z]*$" />
</h:inputText><br/>
<h:message for="name" style="color:red" />
<h:commandButton value="Update" action="#{stock.update(editStock)}" style="width: 80px;"></h:commandButton>
</h:form>