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", "expires": 1784534287 },
        "https://sp_entityid_2": { "idp": "https://idp_entityid_2", "expires": 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's domain is set to Engineblock's host name
    • The Max-Age or Expires property of the cookie need to be set in accordance with the wayf.remember_choice_per_idp_lifetime setting. To reduce complexity, it is not dependent on the actual expires values in the cookie, so in cornercases (e.g., if the wayf.remember_choice_per_idp_lifetime is reduced) it might occur that the cookie expires earlier than the individual entries in the cookie. That is acceptable behavior.
    • 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 this feature is enabled (wayf.remember_choice_per_idp is set) then do the following when determining whether to show the WAYF:

    • check if this SP has coin:wayf_remember_choice set in the metadata
    • check If the cookie is present and valid, and if the user is logging in to an SP that is present in the cookie
    • check that the SP's expiry entry is in the future
    • check that this SP has set coin:wayf_remember_choice in the metadata
    • check that this IdP is available for this SP (i.e., it should never be possible for a user to get redirected to an IdP that is not available for this SP based on this cookie only; the cookie only allows a selection for IdPs that are already available).
    • if so, then skip the WAYF (like the existing rememberchoice cookie does). Log if this occurs with level INFO and message "WAYF-remember-my-choice WAYF skipped for because of preselected "
    • if any of the above checks fail, show the regular WAYF
  • Only update the cookie if the user set a new "remember my choice" checkbox. If changes are made, always update the cookie at the client like this:

    • remove all expired entries (time is older than current time)
    • remove any entries above the maximum number we support (see above). Drop the oldest ones until we are at the limit. Log if this occurs with level WARNING and message "WAYF-remember-my-choice entities dropped from cookie"
    • if no SPs are left in the cookie, remove the cookie altogether
  • If the cookie is only read and no changes are made by the user, the cookie does not need to be updated.

  • 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 expires field set to now + wayf.remember_choice_per_idp_lifetime
    • Run the checks as specified above
    • Set the updated cookie in the response.
    • Output a log line with level INFO and message "WAYF-remember-my-choice set for SP and IdP and expiry "

Metadata

Metadata

Assignees

No one assigned

    Labels

    discoveryRelates to the WAYF/Discovery screen

    Projects

    Status
    Backlog

    Milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions