Skip to content

Remember choice for WAYF per SP #2065

Description

@baszoetekouw

It is already possible to show a checkbox in the WAYF that allows users to save this IdP-choice for future logins. If they select this, then future WAYFs in which their preferred IdP is present are skipped and the user is redirected to the preferred IdP without interaction.

We now want to able to specifiy this behaviour per SP. So when a users enabled the checkbox, this only applies when logging in to this specific SP. When the user logs in to a different SP, they still get the WAYF.

The following changes are required:

  • Add the following extra controls to parameters.yml:

    • introduce feature-toggle wayf.remember_choice_per_idp. All of the below should only be active if both wayf.remember_choice and wayf.remember_choice_per_idp are active.
      • If wayf.remember_choice is true and wayf.remember_choice_per_idp is false, we keep the current global memory feature.
      • If wayf.remember_choice is false, we disable all remember-my-choice features (both global and per-sp).
      • If wayf.remember_choice_per_idp is not defined, act as if it were set to false
    • a parameter to control the life-time of the remembered IdP: wayf.remember_choice_per_idp_lifetime. Typically this would be something like 3 months, but it would be nice to be able to set it to (e.g.) 60 seconds for easy debugging.
    • a parameter to control how many SP-IdP pairs we can store in the cookie wayf.remember_choice_per_idp_lifetime. This defaults to 16. For the logic what to do if we exceed this limit, see below.
  • support new coin:wayf_remember_choice metadata parameter for SPs. If this is not present in the metadata, it defaults to false.

  • if feature is enabled, read and set a cookie rememberedidps with content like this:

    {
        "https://sp_entityid_1": { "idp": "https://idp_entityid_1", "time": 1784534287 },
        "https://sp_entityid_2": { "idp": "https://idp_entityid_2", "time": 1784512345 }
    }
    • Ideally, we would like this cookie to be user-readable (for power users and privacy nerds), but cookies are limited to 4kB so that probably won't work. So the safe way to handle this is to deflate and base64-encode the json, en put that in the cookie.
    • To make sure the structure fits in the cookie, limit this to max 32 entries.
      • If there are more, or a new one needs to be added, drop the oldest ones until there are 32 left.
      • I've run a simulation with current production entities: for 32 entries, we never exceed 2800 bytes. For 64 entries, we sometimes hit 4500 bytes. For unencoded json, we cannot store more than 20 reliably within 4k bytes.
      • It probably makes sense to parametrize this limit, so add a wayf.remember_choice_per_idp_max parameter which defaults to 16 to be on the safe side.
    • if the cookie content is in any way invalid (invalid base64 encoding, invalid json, etc), log a warning and simply ignore it and remove it from the response.
    • The cookie needs to have a broader scope than just Engineblock, because we need to be able to read and reset it from Profile. Therefore give it a domain surfconext.nl (configurable) rather than engine.surfconext.nl.
    • The Max-Age or Expires property of the cookie need to be set in accordance with the wayf.remember_choice_per_idp_lifetime setting.
    • The cookie must have Secure and HttpOnly properties (same as all other EB cookies). SameSite should probably be set to None because we support both Redirect and POST bindings for SAMLRequests.
  • If the cookie is present, and the user is logging in to an SP that is present in the cookie, then do the following:

    • check that the SP's time entry is less than wayf.remember_choice_per_idp_lifetime ago (this should never occur because of the cleanup check below, so it might not be nessecary to duplicate this check if we can be sure that the cleanup check runs before this logic)
    • check that this SP has set coin:wayf_remember_choice in the metadata
    • check that this IdP is available for this SP
    • if so, then skip the WAYF (like the existing rememberchoice cookie does).
    • if not, then remove this SP from the cookie-json and set an updated cookie, and show the regular WAYF
  • When reading/interpreting the cookie, take the following check actions. We need do do this for every AuthnRequest. It is not sufficient to do these checks only when a specific SP is hit, because then entries for removed SPs will linger forever. If changes are made, always update the cookie at the client.

    • remove all expired entries (time is older than wayf.remember_choice_per_idp_lifetime)
    • remove any entries above the maximum number we support (see above). Drop the oldest ones until we are at the limit.
    • remove entries for SPs that do not have coin:wayf_remember_choice set in the metadata
    • if no SPs are left in the cookie, remove the cookie altogether
  • If the users gets the regular WAYF and selects the "remember my choice" checkbox, then do the following if per-SP remembering is enabled (if global remembering is enabled, the behaviour doesn't change):

    • Add the selected (SP,IdP) pair the to the cookie with the current time
    • Run the checks as specified above (if it is not already run at this points in the flow anyway).
    • Set the updated cookie in the response.

Metadata

Metadata

Assignees

No one assigned

    Labels

    discoveryRelates to the WAYF/Discovery screen

    Fields

    No fields configured for Feature.

    Projects

    Status
    Backlog

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions