Flask-Middleware / flask-security

Quick and simple security for Flask applications
MIT License
622 stars 154 forks source link

Whitelist of email domains allowed to register #942

Closed brian7704 closed 3 months ago

brian7704 commented 4 months ago

Is there a way to specify a whitelist of domains that can register? Ideally I'd like only people with email addresses from my organization and maybe a few others to be able to register to my site.

Also is there a blacklist if I just wanted to prevent certain domains from registering, such as temporary email accounts?

jwag956 commented 4 months ago

You can subclass mail_util class and add any additional validation you might want. https://flask-security-too.readthedocs.io/en/stable/api/#flask_security.MailUtil

brian7704 commented 4 months ago

Thanks for the suggestion, I was able to subclass MailUtil to add my own validation.

However I'm not sure what I'm doing wrong but I noticed that /register seems to return a 200 status code even if ValueError is thrown. This also happens without my custom validator. I did a POST request to /register with an invalid email address "asdf" and ValueError was thrown. But I think when ValueError is thrown, the registration form doesn't set any errors. Then when base_render_json() check for form.errors and there are none, it returns 200. Can you offer any advice?

jwag956 commented 4 months ago

Are you using forms? or JSON in your request. If forms - they always return 200 - with field.errors set. If JSON - then yes - you should get a 400 Bad Request. As currently implemented - you will get a very generic 'INVALID_EMAIL_ADDRESS" error message.

brian7704 commented 4 months ago

I'm using my own frontend which POST's JSON to /register. The response when I try an invalid email is

{"meta":{"code":200},"response":{"csrf_token":"ImE5Mm..."}}

with no error message.

jwag956 commented 4 months ago

Hmm - there is a unit test that properly returns a 400 - would have see more details of what the POST contains.

brian7704 commented 4 months ago

I think I figured out the problem. When I had SECURITY_RETURN_GENERIC_RESPONSES enabled /register would return 200, even if I used an invalid email address. But when I disabled that setting, /register returned 400 as expected. The problem seems to be that form_errors_munge makes form.errors an empty list. Not sure if it's a bug or a configuration mistake on my part.

Actually I just noticed this comment which seems like this behavior is intended when using generic responses.

jwag956 commented 4 months ago

Well - this is an interesting case - one the one hand - returning that this isn't a valid email (due to whitelist) doesn't help the caller infer existing user emails - so we could return an error. On the other hand - allowing the caller to figure out that just one domain is allowed to register could be of use.

Let me think about this some more. Am re-opening as a bug for now.

brian7704 commented 4 months ago

For my use case I don't really care if a caller knows the whitelisted domain since the site is hosted on the same domain. But ideally I'd like to prevent callers from being able to figure out valid email accounts on the domain by returning generic responses.