Firestore Security Rules - check if field is a valid email address - firebase

How can I verify if an incoming field is a valid e-mail? Is there a way to use string-functions or anything in Firestore security rules?
Example:
Let's say I have a Create-Request with a field called "email". In my Firestore security rules, I would like to check if the email is a valid email address:
contains '#'
ends with either .xx or .xxx (a casual country-domain-ending)
has a '.' before the last three or two letters of the email
the '.' does not follow directly after the '#' - at least two letters have to be in-between
So that e.g. example#emailprovider.com gets accepted, but not example#.com.
I know that this check is quite extensive and further would like to know if it makes sense to introduce such a validation to security rules?

You can use rules.String.matches.
See
https://firebase.google.com/docs/reference/rules/rules.String#matches
https://github.com/google/re2/wiki/Syntax
How to validate an email address using a regular expression?
Performs a regular expression match on the whole string.
A regular expression using Google RE2 syntax.
If you want to set only email address then It's necessary to validate the field as email address.

I found an example of a regex (and adjusted a bit):
^[a-zA-Z0-9._%+-]+#[a-zA-Z0-9.-]+\\.[a-zA-Z]{2,5}$
The source of this is at the bottom of the following page:
https://firebase.google.com/docs/reference/security/database/regex
You should also take into account the note as well:
Note: THIS WILL REJECT SOME VALID EMAILS. Validating email address
in regular expressions is difficult in general. See this site for
more depth on the subject.

Related

GELScript - Email to multiple recipients

How can I send a gel:email to multiple recipients? I have records with 3 email addresses in each and I want to send the same email to all 3.
This is my current code:
<core:forEach items="${getDetails.rows}" var="row">
<core:set value="${row.Manager_Email}" var="manager" />
<core:set value="${row.Delivery_Manager_Email}" var="deliveryManager" />
<core:set value="${row.Director_Email}" var="director" />
<core:choose>
<core:when test="${status == 1}">
<gel:email from="Clarity_Do-Not-Reply#gov.nl.ca" fromName="Clarity Administrator" to="${manager};${deliveryManager};${director}" subject="Notification: Project is due to finish within 7 days">
I've tried that and:
to="${manager;deliveryManager;director}"
Neither seem to work. The doc says they can be split with the ; but it doesn't seem to be working. What am I doing wrong?
Does it work with just one of them? I would start and establish that the mail server works in this environment. Choose one of those variables and print it out. If it's not what you are expecting then fix your query or wherever you are getting those bound variables. If it is correct then remove the other two recipients and establish that you can send an email successfully to just one of the recipients. If that works then continue troubleshooting.
If it doesn't work then you may discover that your mail server does not allow relaying, unauthenticated services or sending mail from a non-existent email account. You can start checking those things.
One of the issues with both the GEL email tag and the CORE email tag is that it doesn't support including the same email address twice. If you check your project you might find that the same resource is listed as both delivery manager and manager or director, etc. This is a problem for the tag.
You can get around this by placing all recipients into a data structure that doesn't allow duplicates (like a hash map/set) and then iterate them out back into a semi colon delimited String.
There are probably lots of examples of this type of thing on regoXchange, a huge repository of free GEL scripts and Clarity related customizations and development.
This approach that was in your original script example is the correct way to do it: to="${manager};${deliveryManager};${director}"
That is, using a single delimiter type (semi-colon in this case) to separate each evaluated variable value.
The style from your second attempt definitely will not work as ${manager;deliveryManager;director} is not a valid JEXL expression.
There are additional points to be aware of, such as:
Each of the values in the to attribute should not have anything else that can be mistaken for another delimiter type (e.g. no spaces or commas), as you may not mix and match.
Only use the email address directly, meaning some.one#somedomain.com and don't use forms like "One, Some" <some.one#somedomain.com>
Make sure none of the email addresses are duplicated in the list. Every address must be unique. As mentioned in the answer provided by #coda, you can filter duplicates out with some extra GEL or you can put the logic into your query (the row source) to de-duplicate.
If this is running in a SaaS environment, make sure none of the user addresses you are picking up are among the defaults for some built-in user accounts like username#mailserver.com or similar, as they have resulted in emails being filtered out before sending.

User info in URI without password

I know that URI supports the following syntax:
http://[user]:[password]#[domain.tld]
When there is no password or if the password is empty, is there a colon?
In other words, should I accept this:
http://[user]:#[domain.tld]
Or this:
http://[user]#[domain.tld]
Or are they both valid?
The current URI standard (STD 66) is RFC 3986, and the relevant section is 3.2.1. User Information.
There it’s defined that the userinfo subcomponent (which gets followed by #) can contain any combination of
the character :,
percent-encoded characters, and
characters from the sets unreserved and sub-delims.
So this means that both of your examples are valid.
However, note that the format user:password is deprecated. Anyway, they give recommendations how applications should handle such URIs, i.e., everything after the first : character should not be displayed by applications, unless
the data after the colon is the empty string (indicating no password).
So according to this recommendation, the userinfo subcomponent user: indicates that there is the username "user" and no password.
This is more like convenience and both are valid. I would go with http://[user]#[domain.tld] (and prompt for a password.) because it's simple and not ambiguous. It does not give any chance for user to think if he has to add anything after :

Adding IP Address to Email Validation RegEx

I am using the RegEx "^[_a-zA-Z0-9-]+(\.[_a-zA-Z0-9-]+)*#[a-zA-Z0-9-]+(\.[a-zA-Z0-9-]+[.])*(\.[a-zA-Z]{2,17})$"to validate Email but my lead want to validate as per the Microsoft standard. SO i need to follow
http://msdn.microsoft.com/en-us/library/01escwtf(v=vs.100).aspx
In that everything working fine as per the standard but still i am facing the issues with
Valid: js#internal#proseware.com
Valid: j_9#[129.126.118.1]
the above mentioned mail ID is still returning as invalid. I tried using the regex used in that page
^(?("")(""[^""]+?""#)|(([0-9a-z]((\.(?!\.))|[-!#\$%&'\*\+/=\?\^`\{\}\|~\w])*)(?<=[0-9a-z])#))(?(\[)(\[(\d{1,3}\.){3}\d{1,3}\])|(([0-9a-z][-\w]*[0-9a-z]*\.)+[a-z0-9]{2,17}))$
but i am getting the error in the server page. Though I pasted the expression inside the validation Expression it can't able to accept the characters.
Note : am using ASP.Net validators for validating the email.
Description
To match both of those email addresses in your sample text, I think I would rewrite your expression like this:
[A-Z0-9._%#+-]+#(?:[A-Z0-9.-]+\.[A-Z]{2,4}|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\])
If you're looking to use this to validate a string which may contain only an email then you can add the start/end of string anchors ^ and $.
Example
Live Demo
Sample Text
Valid: js#internal#proseware.com Valid: j_9#[129.126.118.1]
Matches
[0][0] = js#internal#proseware.com
[1][0] = j_9#[129.126.118.1]

Parsing a HTTP Basic authentication with an email containing a colon character ( ':' )

I'm using the Authorization header with the Basic type for authentication.
I'm following the HTTP Basic authentication specifications which states that the credentials should follow this form -> userIdentifier:password encoded in base64
We are using an email as the user identifier and according to the email format specification, the colon(':') character is permitted.
The colon(':') is also a valid character in the password.
Knowing this, I'm looking for a creative way to parse the credentials part of the header that uses a colon(':') as the separator between userID and password.
In this case it's simple -> francis#gmail.com:myPassword
This is where it gets complicated -> francis#gmail.com:80:myPasswordWith:Inside
francis#gmail.com:80 is a valid email according to the email format specification even though this is not used very often. So where do I know where to split ?
We have made the decision not to accept an email containing a ':'. But we want to notify the user that his email is not valid, how can we ensure that we are splitting the string at the right place ?
Hope I asked my question in a clear manner, don't hesitate to ask for more details
Thank you
Don’t notify the user that the email is invalid. Split according to the RFC 2617 rules (everything after the first colon is the password), then try to authenticate, fail, and return a generic “authentication failure” message.
A situation where john#example.org:80 has password secret and john#example.org has password 80:secret at the same time, seems unrealistic.
If you require your users to register, you probably do it with some other mechanism (forms?) where you can easily separate the username and tell that it is invalid.

What are the risks of allowing quote characters as part of a URL parameter?

I need to allow the user to submit queries as follows;
/search/"my search string"
but it's failing because of request validation, as outlined in the following 2 questions:
How to include quote characters as a route parameter? Getting "Illegal characters in path" message
How to modify request validation?
I'm currently trying to figure out how to disable request validation for the quote character, but i'd like to know the risks before I actually put the site live with this disabled? I will not disable the request validation unless I can only disable it for the quote character, so I do intend to disallow every other character that's currently not allowed.
According to the URI generic syntax specification (RFC 2396), the double-quote character is explicitly excluded and must be escaped (i.e. %22). See section 2.4.3. The reason given in the spec:
The angle-bracket "<" and ">" and double-quote (") characters are excluded because they are often used as the delimiters around URI in text documents and protocol fields.
You can see easily why this is the case -- imagine trying to create a link in HTML to your URL:
<a href="http://somesite/search/"my search string""/>
That would fail HTML parsing (and also breaks SO's syntax highlighting). You also would have trouble doing basic things with the URL like emailing it to someone (the email client wouldn't parse the URL correctly), posting it on a message board, sending it in an instant message, etc.
For what it's worth, spaces are also explicitly excluded (same section of the RFC explains why).

Resources