Skip to content
This repository has been archived by the owner on Apr 26, 2024. It is now read-only.

add registrations_require_3pid and allow_local_3pids #2813

Merged
merged 9 commits into from Jan 22, 2018

Conversation

ara4n
Copy link
Member

@ara4n ara4n commented Jan 19, 2018

Adds allow_local_3pids: to let homeservers specify a whitelist for the format of 3PIDs that users are allowed to register with or add to their HS accounts.

It does not directly impact the 3PIDs which a user can bind to their account on their IS.

It also adds registrations_require_3pid, to determine which registration flows are advertised by the HS in case an admin wants to force users to specify a given 3PID when they sign up.

Typically useful for stopping people from registering with non-work emails.

lets homeservers specify a whitelist for 3PIDs that users are allowed to associate with.
Typically useful for stopping people from registering with non-work emails
@@ -31,6 +31,7 @@ def read_config(self, config):
strtobool(str(config["disable_registration"]))
)

self.registrations_require_3pid = config.get("registrations_require_3pid", [])
Copy link
Member

@turt2live turt2live Jan 19, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This doesn't seem to affect just registrations and could be misleading to some people.

Edit for clarity: I'm talking about the config key name

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, i've asked @dbkr to clarify the impact on the other 3PID manipulations

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

this convo ended up in IRL as dave presumably missed this comment: the impact is:

  • There are three request tokens atm for verifying 3PIDs:
    • registration
    • password reset
    • adding a 3pid to your account for use in login (which in turn tries to go bind it on the IS if asked)
  • this PR restricts the format of all three with allowed_local_3pids
  • it does not limit IS bindings (other than in a weak manner given in practice the account/3pid api is used by clients today to trigger bindings)

@erikjohnston erikjohnston self-assigned this Jan 19, 2018
Copy link
Member

@dbkr dbkr left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

otherwise, yep, lgtm

])

auth_result, params, session_id = yield self.auth_handler.check_auth(
flows, body, self.hs.get_ip_from_request(request)
)

# doublecheck that we're not trying to register an denied 3pid.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

a

])

auth_result, params, session_id = yield self.auth_handler.check_auth(
flows, body, self.hs.get_ip_from_request(request)
)

# doublecheck that we're not trying to register an denied 3pid.
# the user-facing checks should already have happened when we requested
# a 3PID token to validate them in /register/email/requestToken etc
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not necessarily, since there's nothing to mandate that the user had to proxy their requestToken via the HS, so this check is important.

@erikjohnston
Copy link
Member

I'm confused what this is trying to do. Is this:

  1. requiring that users register with a 3pid in a whitelist? or
  2. stopping users from adding 3pids outside a whitelist?

if (
constraint['medium'] == 'email' and
threepid['medium'] == 'email' and
re.match(constraint['pattern'], threepid['address'])
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do you mean and not re.match?

]}
)
])
return (200, {"flows": flows})
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

What does require_msisdn mean? We don't seem to add a stage for it.


Also I really can't follow whats going on here, there are two many if and nots and ands and ors. It seems that we're building up flows based on required stages, so something like the following might work better:

required_stages = []  # The stages that need to be in every flow

if self.hs.config.enable_registration_captcha:
    required_stages.append(LoginType.RECAPTCHA)

if require_email:
    required_stages.append(LoginType.EMAIL_IDENTITY)

# ... etc ...

# Now we work out what flows we need to offer. 
flows = []

# First we add the base flow with only the required stages:

flows.append({"stages": required_stages})

# If we don't require email, then we add a flow to let people optionally specify it
if not require_email:
    flows.append({"stages": required_stages + [LoginType.EMAIL_IDENTITY]})

for constraint in hs.config.registrations_require_3pid:
logger.debug("Checking 3PID %s (%s) against %s (%s)" % (
address, medium, constraint['pattern'], constraint['medium']
))
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't do string building, like most logging libraries it does it for you: logger.debug("foo: %s, bar: %s", foo, bar)

else:
allow = True

return allow
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Normally I'd do the pattern of returning immediately rather than having an allow variable, e.g.:

def check_3pid_allowed(hs, medium, address):
    if not hs.config.registrations_require_3pid:
        return True
 
    for constraint in hs.config.registrations_require_3pid:
        if allowed:
            return True

    return False

@@ -60,6 +60,27 @@ def set_timeline_upper_limit(filter_json, filter_timeline_limit):
filter_timeline_limit)


def check_3pid_allowed(hs, medium, address):
# check whether the HS has whitelisted the given 3PID
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Proper docstring please.

@@ -47,6 +47,11 @@ def on_POST(self, request):
'id_server', 'client_secret', 'email', 'send_attempt'
])

if not check_3pid_allowed(self.hs, "email", body['email']):
raise SynapseError(
403, "Third party identifier is not allowed", Codes.THREEPID_DENIED
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: Generally we always try and use trailing commas

else:
logger.warn(
"Unrecognised 3PID medium %s in registrations_require_3pid" %
constraint['medium']
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't do string building.

flows.extend([
[LoginType.MSISDN],
[LoginType.MSISDN, LoginType.EMAIL_IDENTITY],
[LoginType.MSISDN, LoginType.EMAIL_IDENTITY]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

(See comment where we do this in v1 register)

):
raise SynapseError(
403, "Third party identifier is not allowed", Codes.THREEPID_DENIED
)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can we not use check_3pid_allowed here?

@erikjohnston
Copy link
Member

I think this does what you want, but I think we need to be a lot more explicit that we're requiring and restricting 3pids here. I think it may be better to split up the config (and PR) into "require 3pid on register" and "disallow 3pids outside a whitelist"

@erikjohnston erikjohnston assigned ara4n and unassigned erikjohnston Jan 19, 2018
 * [ ] split config options into allowed_local_3pids and registrations_require_3pid
 * [ ] simplify and comment logic for picking registration flows
 * [ ] fix docstring and move check_3pid_allowed into a new util module
 * [ ] use check_3pid_allowed everywhere

@erikjohnston PTAL
@ara4n
Copy link
Member Author

ara4n commented Jan 19, 2018

Rewritten based on the above to:

  • split config options into allowed_local_3pids and registrations_require_3pid
  • simplify and comment logic for picking registration flows
  • fix docstring and move check_3pid_allowed into a new util module
  • use check_3pid_allowed everywhere
  • add trailing commas when we wrap args...

if hs.config.allowed_local_3pids:
for constraint in hs.config.allowed_local_3pids:
logger.debug("Checking 3PID %s (%s) against %s (%s)" % (
address, medium, constraint['pattern'], constraint['medium']
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Don't need explicit string formatting, logger.debug does it for you.

)
):
medium = auth_result[LoginType.EMAIL_IDENTITY].threepid['medium']
address = auth_result[LoginType.EMAIL_IDENTITY].threepid['address']
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Doesn't this need to check both msisdn and email?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

oops, thanks

#
# registrations_require_3pid:
# - email
# - msisdn
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Personally I would have the two config option entirely separate, as this doesn't support the use case of "require a work email but let people bind personal emails"

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

we're not trying to solve for that use case here, plus having talked to @dbkr it's hard to do anyway - as /account/3pid goes and adds the email to your account (letting you log in with it) as well as optionally binding it on the identity server... so you can't separate the two easily anyway.

Hence me splitting it into:

  • What 3PID media do we mandate at registration?
  • What format 3PIDs are allowed to be added to accounts on this HS?
    ...with no restrictions on formats valid on ISes.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

btw, this is a good example of a review comment where I'm staring at it thinking "does he really want me to rewrite it again? or is he just voicing a random comment?". It might be worth clearly spelling out which comments actually block accepting the PR from your POV, otherwise the committer has no option than assume everything is a request for change...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ok, in this case it was an observation that this feels odd and questioning whether this is the right thing to do. The synapse review process is not just about whether functional changes are right, but if we should even be doing it like that.

medium (str): 3pid medium - e.g. email, msisdn
address (str): address within that medium (e.g. "wotan@matrix.org")
msisdns need to first have been canonicalised
"""
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should have a:

Returns:
    bool: ...

especially since I think there are other check_ functions raise rather than return a bool

@erikjohnston erikjohnston assigned richvdh and unassigned ara4n Jan 19, 2018
@ara4n ara4n changed the title add registrations_require_3pid add registrations_require_3pid and allow_local_3pids Jan 19, 2018
@ara4n
Copy link
Member Author

ara4n commented Jan 19, 2018

I'm confused what this is trying to do. Is this:

  1. requiring that users register with a 3pid in a whitelist? or
  2. stopping users from adding 3pids outside a whitelist?

Both. It's trying to limit both the 3PIDs which a user can use to register, and add to their HS account. The main focus is on requiring the user has a valid email address for a domain at the point that they register; however if this restriction is in place, it seems unwise to let them then go and add other emails to let them log into the account (such that they might still be able to login and reset passwords etc, even if their official address is no more).

In other words: it feels needlessly confusing to expose a different whitelist for 3PID formats which may be added to an account, than that which is used to register in the first place.

@ara4n
Copy link
Member Author

ara4n commented Jan 19, 2018

I think this does what you want, but I think we need to be a lot more explicit that we're requiring and restricting 3pids here. I think it may be better to split up the config (and PR) into "require 3pid on register" and "disallow 3pids outside a whitelist"

Totally agreed, which is why I rewrote the PR to do this.

@ara4n
Copy link
Member Author

ara4n commented Jan 19, 2018

@erikjohnston ptal again if you can face it.

@richvdh
Copy link
Member

richvdh commented Jan 20, 2018

@erikjohnston did you mean to assign this to me?

@erikjohnston
Copy link
Member

@erikjohnston did you mean to assign this to me?

woops, sorry, must have been muscle memory

@erikjohnston erikjohnston assigned ara4n and unassigned richvdh Jan 22, 2018
@ara4n
Copy link
Member Author

ara4n commented Jan 22, 2018

thanks :)

@ara4n ara4n merged commit d84f652 into develop Jan 22, 2018
@hawkowl hawkowl deleted the matthew/registrations_require_3pid branch September 20, 2018 13:59
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

5 participants